Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/marian-nmt/marian.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHieu Hoang <hieuhoang@gmail.com>2016-09-03 04:02:03 +0300
committerHieu Hoang <hieuhoang@gmail.com>2016-09-03 04:08:09 +0300
commit9c18d1c230e68c3fcee2fa8c3c1f92c08637a784 (patch)
tree3f566daa3dbe462b6d0965acb328f5b3f8f9ab2e
parentce121e4ee9f65e30982331179183f754b348ee20 (diff)
add cpu
-rw-r--r--CMakeLists.txt2
-rw-r--r--amunmt/.cproject7
-rw-r--r--amunmt/.project5
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/cpu/blaze/Blaze.h60
-rw-r--r--src/cpu/blaze/Math.h84
-rw-r--r--src/cpu/blaze/Tutorial.h10694
-rw-r--r--src/cpu/blaze/Util.h90
-rw-r--r--src/cpu/blaze/config/Assertion.h65
-rw-r--r--src/cpu/blaze/config/BLAS.h92
-rw-r--r--src/cpu/blaze/config/CacheSize.h51
-rw-r--r--src/cpu/blaze/config/Config.h53
-rw-r--r--src/cpu/blaze/config/Debugging.h55
-rw-r--r--src/cpu/blaze/config/Inline.h75
-rw-r--r--src/cpu/blaze/config/Logging.h93
-rw-r--r--src/cpu/blaze/config/MPI.h51
-rw-r--r--src/cpu/blaze/config/Optimizations.h87
-rw-r--r--src/cpu/blaze/config/Precision.h50
-rw-r--r--src/cpu/blaze/config/Random.h51
-rw-r--r--src/cpu/blaze/config/Restrict.h47
-rw-r--r--src/cpu/blaze/config/SMP.h54
-rw-r--r--src/cpu/blaze/config/StorageOrder.h59
-rw-r--r--src/cpu/blaze/config/Thresholds.h1308
-rw-r--r--src/cpu/blaze/config/TransposeFlag.h59
-rw-r--r--src/cpu/blaze/config/Vectorization.h54
-rw-r--r--src/cpu/blaze/math/Accuracy.h906
-rw-r--r--src/cpu/blaze/math/Aliases.h428
-rw-r--r--src/cpu/blaze/math/AlignmentFlag.h90
-rw-r--r--src/cpu/blaze/math/BLAS.h50
-rw-r--r--src/cpu/blaze/math/Column.h315
-rw-r--r--src/cpu/blaze/math/CompressedMatrix.h465
-rw-r--r--src/cpu/blaze/math/CompressedVector.h330
-rw-r--r--src/cpu/blaze/math/Constants.h208
-rw-r--r--src/cpu/blaze/math/Constraints.h132
-rw-r--r--src/cpu/blaze/math/CustomMatrix.h356
-rw-r--r--src/cpu/blaze/math/CustomVector.h140
-rw-r--r--src/cpu/blaze/math/DenseMatrix.h103
-rw-r--r--src/cpu/blaze/math/DenseVector.h69
-rw-r--r--src/cpu/blaze/math/DiagonalMatrix.h685
-rw-r--r--src/cpu/blaze/math/DynamicMatrix.h395
-rw-r--r--src/cpu/blaze/math/DynamicVector.h186
-rw-r--r--src/cpu/blaze/math/Epsilon.h906
-rw-r--r--src/cpu/blaze/math/Exception.h150
-rw-r--r--src/cpu/blaze/math/Forward.h49
-rw-r--r--src/cpu/blaze/math/Functions.h462
-rw-r--r--src/cpu/blaze/math/Functors.h77
-rw-r--r--src/cpu/blaze/math/HermitianMatrix.h687
-rw-r--r--src/cpu/blaze/math/HybridMatrix.h412
-rw-r--r--src/cpu/blaze/math/HybridVector.h188
-rw-r--r--src/cpu/blaze/math/Infinity.h1103
-rw-r--r--src/cpu/blaze/math/InitializerList.h91
-rw-r--r--src/cpu/blaze/math/InversionFlag.h88
-rw-r--r--src/cpu/blaze/math/LAPACK.h84
-rw-r--r--src/cpu/blaze/math/LowerMatrix.h810
-rw-r--r--src/cpu/blaze/math/Math.h49
-rw-r--r--src/cpu/blaze/math/Matrix.h94
-rw-r--r--src/cpu/blaze/math/PaddingFlag.h91
-rw-r--r--src/cpu/blaze/math/Row.h315
-rw-r--r--src/cpu/blaze/math/SIMD.h48
-rw-r--r--src/cpu/blaze/math/SMP.h50
-rw-r--r--src/cpu/blaze/math/Serialization.h47
-rw-r--r--src/cpu/blaze/math/Shims.h84
-rw-r--r--src/cpu/blaze/math/SparseMatrix.h81
-rw-r--r--src/cpu/blaze/math/SparseVector.h66
-rw-r--r--src/cpu/blaze/math/StaticMatrix.h382
-rw-r--r--src/cpu/blaze/math/StaticVector.h187
-rw-r--r--src/cpu/blaze/math/StorageOrder.h104
-rw-r--r--src/cpu/blaze/math/StrictlyLowerMatrix.h673
-rw-r--r--src/cpu/blaze/math/StrictlyUpperMatrix.h673
-rw-r--r--src/cpu/blaze/math/Submatrix.h342
-rw-r--r--src/cpu/blaze/math/Subvector.h315
-rw-r--r--src/cpu/blaze/math/SymmetricMatrix.h686
-rw-r--r--src/cpu/blaze/math/Traits.h235
-rw-r--r--src/cpu/blaze/math/TransposeFlag.h78
-rw-r--r--src/cpu/blaze/math/TypeTraits.h168
-rw-r--r--src/cpu/blaze/math/UniLowerMatrix.h786
-rw-r--r--src/cpu/blaze/math/UniUpperMatrix.h785
-rw-r--r--src/cpu/blaze/math/UpperMatrix.h810
-rw-r--r--src/cpu/blaze/math/Vector.h378
-rw-r--r--src/cpu/blaze/math/Views.h48
-rw-r--r--src/cpu/blaze/math/adaptors/Adaptors.h51
-rw-r--r--src/cpu/blaze/math/adaptors/DiagonalMatrix.h2208
-rw-r--r--src/cpu/blaze/math/adaptors/Forward.h59
-rw-r--r--src/cpu/blaze/math/adaptors/HermitianMatrix.h2130
-rw-r--r--src/cpu/blaze/math/adaptors/LowerMatrix.h2174
-rw-r--r--src/cpu/blaze/math/adaptors/StrictlyLowerMatrix.h1731
-rw-r--r--src/cpu/blaze/math/adaptors/StrictlyUpperMatrix.h1840
-rw-r--r--src/cpu/blaze/math/adaptors/SymmetricMatrix.h1879
-rw-r--r--src/cpu/blaze/math/adaptors/UniLowerMatrix.h2562
-rw-r--r--src/cpu/blaze/math/adaptors/UniUpperMatrix.h2671
-rw-r--r--src/cpu/blaze/math/adaptors/UpperMatrix.h2279
-rw-r--r--src/cpu/blaze/math/adaptors/diagonalmatrix/BaseTemplate.h562
-rw-r--r--src/cpu/blaze/math/adaptors/diagonalmatrix/Dense.h2650
-rw-r--r--src/cpu/blaze/math/adaptors/diagonalmatrix/DiagonalProxy.h665
-rw-r--r--src/cpu/blaze/math/adaptors/diagonalmatrix/Sparse.h2022
-rw-r--r--src/cpu/blaze/math/adaptors/hermitianmatrix/BaseTemplate.h617
-rw-r--r--src/cpu/blaze/math/adaptors/hermitianmatrix/Dense.h3018
-rw-r--r--src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianElement.h434
-rw-r--r--src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianProxy.h851
-rw-r--r--src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianValue.h811
-rw-r--r--src/cpu/blaze/math/adaptors/hermitianmatrix/Sparse.h2404
-rw-r--r--src/cpu/blaze/math/adaptors/lowermatrix/BaseTemplate.h555
-rw-r--r--src/cpu/blaze/math/adaptors/lowermatrix/Dense.h2740
-rw-r--r--src/cpu/blaze/math/adaptors/lowermatrix/LowerProxy.h665
-rw-r--r--src/cpu/blaze/math/adaptors/lowermatrix/Sparse.h2072
-rw-r--r--src/cpu/blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h560
-rw-r--r--src/cpu/blaze/math/adaptors/strictlylowermatrix/Dense.h2757
-rw-r--r--src/cpu/blaze/math/adaptors/strictlylowermatrix/Sparse.h2112
-rw-r--r--src/cpu/blaze/math/adaptors/strictlylowermatrix/StrictlyLowerProxy.h670
-rw-r--r--src/cpu/blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h560
-rw-r--r--src/cpu/blaze/math/adaptors/strictlyuppermatrix/Dense.h2757
-rw-r--r--src/cpu/blaze/math/adaptors/strictlyuppermatrix/Sparse.h2111
-rw-r--r--src/cpu/blaze/math/adaptors/strictlyuppermatrix/StrictlyUpperProxy.h669
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/BaseTemplate.h614
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNonNumeric.h2650
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNumeric.h2970
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/NonNumericProxy.h650
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/NumericProxy.h780
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/SharedValue.h314
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNonNumeric.h2720
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNumeric.h2345
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricElement.h403
-rw-r--r--src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricValue.h767
-rw-r--r--src/cpu/blaze/math/adaptors/unilowermatrix/BaseTemplate.h579
-rw-r--r--src/cpu/blaze/math/adaptors/unilowermatrix/Dense.h2697
-rw-r--r--src/cpu/blaze/math/adaptors/unilowermatrix/Sparse.h2211
-rw-r--r--src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerElement.h367
-rw-r--r--src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerProxy.h809
-rw-r--r--src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerValue.h753
-rw-r--r--src/cpu/blaze/math/adaptors/uniuppermatrix/BaseTemplate.h578
-rw-r--r--src/cpu/blaze/math/adaptors/uniuppermatrix/Dense.h2696
-rw-r--r--src/cpu/blaze/math/adaptors/uniuppermatrix/Sparse.h2211
-rw-r--r--src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperElement.h367
-rw-r--r--src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperProxy.h809
-rw-r--r--src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperValue.h753
-rw-r--r--src/cpu/blaze/math/adaptors/uppermatrix/BaseTemplate.h555
-rw-r--r--src/cpu/blaze/math/adaptors/uppermatrix/Dense.h2739
-rw-r--r--src/cpu/blaze/math/adaptors/uppermatrix/Sparse.h2071
-rw-r--r--src/cpu/blaze/math/adaptors/uppermatrix/UpperProxy.h665
-rw-r--r--src/cpu/blaze/math/blas/BLAS.h51
-rw-r--r--src/cpu/blaze/math/blas/dot.h227
-rw-r--r--src/cpu/blaze/math/blas/gemm.h298
-rw-r--r--src/cpu/blaze/math/blas/gemv.h337
-rw-r--r--src/cpu/blaze/math/blas/trmm.h289
-rw-r--r--src/cpu/blaze/math/blas/trmv.h312
-rw-r--r--src/cpu/blaze/math/blas/trsm.h358
-rw-r--r--src/cpu/blaze/math/constraints/Adaptor.h87
-rw-r--r--src/cpu/blaze/math/constraints/AddExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/Aligned.h87
-rw-r--r--src/cpu/blaze/math/constraints/BLASCompatible.h87
-rw-r--r--src/cpu/blaze/math/constraints/Column.h87
-rw-r--r--src/cpu/blaze/math/constraints/ColumnMajorMatrix.h87
-rw-r--r--src/cpu/blaze/math/constraints/ColumnVector.h87
-rw-r--r--src/cpu/blaze/math/constraints/Columns.h101
-rw-r--r--src/cpu/blaze/math/constraints/Computation.h87
-rw-r--r--src/cpu/blaze/math/constraints/ConstDataAccess.h87
-rw-r--r--src/cpu/blaze/math/constraints/Constraints.h51
-rw-r--r--src/cpu/blaze/math/constraints/CrossExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/Custom.h87
-rw-r--r--src/cpu/blaze/math/constraints/DenseMatrix.h87
-rw-r--r--src/cpu/blaze/math/constraints/DenseVector.h87
-rw-r--r--src/cpu/blaze/math/constraints/Diagonal.h85
-rw-r--r--src/cpu/blaze/math/constraints/DivExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/EvalExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/Expression.h87
-rw-r--r--src/cpu/blaze/math/constraints/ForEachExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/General.h85
-rw-r--r--src/cpu/blaze/math/constraints/Hermitian.h85
-rw-r--r--src/cpu/blaze/math/constraints/Identity.h85
-rw-r--r--src/cpu/blaze/math/constraints/Invertible.h89
-rw-r--r--src/cpu/blaze/math/constraints/Lower.h87
-rw-r--r--src/cpu/blaze/math/constraints/MatEvalExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/MatForEachExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/MatInvExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/MatMatAddExpr.h151
-rw-r--r--src/cpu/blaze/math/constraints/MatMatMultExpr.h145
-rw-r--r--src/cpu/blaze/math/constraints/MatMatSubExpr.h151
-rw-r--r--src/cpu/blaze/math/constraints/MatScalarDivExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/MatScalarMultExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/MatSerialExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/MatTransExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/MatVecMultExpr.h146
-rw-r--r--src/cpu/blaze/math/constraints/Matrix.h87
-rw-r--r--src/cpu/blaze/math/constraints/MultExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/MutableDataAccess.h87
-rw-r--r--src/cpu/blaze/math/constraints/NumericMatrix.h85
-rw-r--r--src/cpu/blaze/math/constraints/NumericVector.h85
-rw-r--r--src/cpu/blaze/math/constraints/OpposedView.h87
-rw-r--r--src/cpu/blaze/math/constraints/Padded.h87
-rw-r--r--src/cpu/blaze/math/constraints/Proxy.h87
-rw-r--r--src/cpu/blaze/math/constraints/RequiresEvaluation.h87
-rw-r--r--src/cpu/blaze/math/constraints/Resizable.h87
-rw-r--r--src/cpu/blaze/math/constraints/Restricted.h87
-rw-r--r--src/cpu/blaze/math/constraints/Row.h87
-rw-r--r--src/cpu/blaze/math/constraints/RowMajorMatrix.h87
-rw-r--r--src/cpu/blaze/math/constraints/RowVector.h87
-rw-r--r--src/cpu/blaze/math/constraints/Rows.h101
-rw-r--r--src/cpu/blaze/math/constraints/SIMDEnabled.h87
-rw-r--r--src/cpu/blaze/math/constraints/SIMDPack.h85
-rw-r--r--src/cpu/blaze/math/constraints/SMPAssignable.h87
-rw-r--r--src/cpu/blaze/math/constraints/SerialExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/Size.h101
-rw-r--r--src/cpu/blaze/math/constraints/SparseElement.h87
-rw-r--r--src/cpu/blaze/math/constraints/SparseMatrix.h87
-rw-r--r--src/cpu/blaze/math/constraints/SparseVector.h87
-rw-r--r--src/cpu/blaze/math/constraints/Square.h85
-rw-r--r--src/cpu/blaze/math/constraints/StorageOrder.h114
-rw-r--r--src/cpu/blaze/math/constraints/StrictlyLower.h87
-rw-r--r--src/cpu/blaze/math/constraints/StrictlyTriangular.h87
-rw-r--r--src/cpu/blaze/math/constraints/StrictlyUpper.h87
-rw-r--r--src/cpu/blaze/math/constraints/SubExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/Submatrix.h87
-rw-r--r--src/cpu/blaze/math/constraints/Subvector.h87
-rw-r--r--src/cpu/blaze/math/constraints/Symmetric.h85
-rw-r--r--src/cpu/blaze/math/constraints/TVecMatMultExpr.h146
-rw-r--r--src/cpu/blaze/math/constraints/TransExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/TransposeFlag.h114
-rw-r--r--src/cpu/blaze/math/constraints/Triangular.h87
-rw-r--r--src/cpu/blaze/math/constraints/UniLower.h87
-rw-r--r--src/cpu/blaze/math/constraints/UniTriangular.h87
-rw-r--r--src/cpu/blaze/math/constraints/UniUpper.h87
-rw-r--r--src/cpu/blaze/math/constraints/Upper.h87
-rw-r--r--src/cpu/blaze/math/constraints/VecEvalExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/VecForEachExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/VecScalarDivExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/VecScalarMultExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/VecSerialExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/VecTVecMultExpr.h135
-rw-r--r--src/cpu/blaze/math/constraints/VecTransExpr.h87
-rw-r--r--src/cpu/blaze/math/constraints/VecVecAddExpr.h149
-rw-r--r--src/cpu/blaze/math/constraints/VecVecDivExpr.h149
-rw-r--r--src/cpu/blaze/math/constraints/VecVecMultExpr.h149
-rw-r--r--src/cpu/blaze/math/constraints/VecVecSubExpr.h149
-rw-r--r--src/cpu/blaze/math/constraints/Vector.h87
-rw-r--r--src/cpu/blaze/math/constraints/View.h87
-rw-r--r--src/cpu/blaze/math/dense/CustomMatrix.h6636
-rw-r--r--src/cpu/blaze/math/dense/CustomVector.h5654
-rw-r--r--src/cpu/blaze/math/dense/DenseIterator.h755
-rw-r--r--src/cpu/blaze/math/dense/DenseMatrix.h1750
-rw-r--r--src/cpu/blaze/math/dense/DenseVector.h648
-rw-r--r--src/cpu/blaze/math/dense/DynamicMatrix.h6324
-rw-r--r--src/cpu/blaze/math/dense/DynamicVector.h2973
-rw-r--r--src/cpu/blaze/math/dense/Forward.h65
-rw-r--r--src/cpu/blaze/math/dense/HybridMatrix.h6663
-rw-r--r--src/cpu/blaze/math/dense/HybridVector.h3015
-rw-r--r--src/cpu/blaze/math/dense/Inversion.h1126
-rw-r--r--src/cpu/blaze/math/dense/LLH.h175
-rw-r--r--src/cpu/blaze/math/dense/LQ.h246
-rw-r--r--src/cpu/blaze/math/dense/LU.h329
-rw-r--r--src/cpu/blaze/math/dense/QL.h247
-rw-r--r--src/cpu/blaze/math/dense/QR.h246
-rw-r--r--src/cpu/blaze/math/dense/RQ.h248
-rw-r--r--src/cpu/blaze/math/dense/StaticMatrix.h6270
-rw-r--r--src/cpu/blaze/math/dense/StaticVector.h2842
-rw-r--r--src/cpu/blaze/math/expressions/AddExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/Computation.h65
-rw-r--r--src/cpu/blaze/math/expressions/CrossExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/DMatDMatAddExpr.h1276
-rw-r--r--src/cpu/blaze/math/expressions/DMatDMatMultExpr.h8100
-rw-r--r--src/cpu/blaze/math/expressions/DMatDMatSubExpr.h1264
-rw-r--r--src/cpu/blaze/math/expressions/DMatDVecMultExpr.h5453
-rw-r--r--src/cpu/blaze/math/expressions/DMatDetExpr.h428
-rw-r--r--src/cpu/blaze/math/expressions/DMatEvalExpr.h1022
-rw-r--r--src/cpu/blaze/math/expressions/DMatForEachExpr.h3080
-rw-r--r--src/cpu/blaze/math/expressions/DMatInvExpr.h617
-rw-r--r--src/cpu/blaze/math/expressions/DMatSMatAddExpr.h1150
-rw-r--r--src/cpu/blaze/math/expressions/DMatSMatMultExpr.h1766
-rw-r--r--src/cpu/blaze/math/expressions/DMatSMatSubExpr.h1107
-rw-r--r--src/cpu/blaze/math/expressions/DMatSVecMultExpr.h1031
-rw-r--r--src/cpu/blaze/math/expressions/DMatScalarDivExpr.h1398
-rw-r--r--src/cpu/blaze/math/expressions/DMatScalarMultExpr.h2943
-rw-r--r--src/cpu/blaze/math/expressions/DMatSerialExpr.h1040
-rw-r--r--src/cpu/blaze/math/expressions/DMatTDMatAddExpr.h1270
-rw-r--r--src/cpu/blaze/math/expressions/DMatTDMatMultExpr.h8114
-rw-r--r--src/cpu/blaze/math/expressions/DMatTDMatSubExpr.h1264
-rw-r--r--src/cpu/blaze/math/expressions/DMatTSMatAddExpr.h1080
-rw-r--r--src/cpu/blaze/math/expressions/DMatTSMatMultExpr.h2075
-rw-r--r--src/cpu/blaze/math/expressions/DMatTSMatSubExpr.h1031
-rw-r--r--src/cpu/blaze/math/expressions/DMatTransExpr.h1296
-rw-r--r--src/cpu/blaze/math/expressions/DMatTransposer.h1968
-rw-r--r--src/cpu/blaze/math/expressions/DVecDVecAddExpr.h1150
-rw-r--r--src/cpu/blaze/math/expressions/DVecDVecCrossExpr.h569
-rw-r--r--src/cpu/blaze/math/expressions/DVecDVecDivExpr.h1151
-rw-r--r--src/cpu/blaze/math/expressions/DVecDVecMultExpr.h1208
-rw-r--r--src/cpu/blaze/math/expressions/DVecDVecSubExpr.h1142
-rw-r--r--src/cpu/blaze/math/expressions/DVecEvalExpr.h867
-rw-r--r--src/cpu/blaze/math/expressions/DVecForEachExpr.h2404
-rw-r--r--src/cpu/blaze/math/expressions/DVecSVecAddExpr.h946
-rw-r--r--src/cpu/blaze/math/expressions/DVecSVecCrossExpr.h573
-rw-r--r--src/cpu/blaze/math/expressions/DVecSVecMultExpr.h777
-rw-r--r--src/cpu/blaze/math/expressions/DVecSVecSubExpr.h904
-rw-r--r--src/cpu/blaze/math/expressions/DVecScalarDivExpr.h1314
-rw-r--r--src/cpu/blaze/math/expressions/DVecScalarMultExpr.h2678
-rw-r--r--src/cpu/blaze/math/expressions/DVecSerialExpr.h889
-rw-r--r--src/cpu/blaze/math/expressions/DVecTDVecMultExpr.h1792
-rw-r--r--src/cpu/blaze/math/expressions/DVecTSVecMultExpr.h1326
-rw-r--r--src/cpu/blaze/math/expressions/DVecTransExpr.h1120
-rw-r--r--src/cpu/blaze/math/expressions/DVecTransposer.h833
-rw-r--r--src/cpu/blaze/math/expressions/DenseMatrix.h76
-rw-r--r--src/cpu/blaze/math/expressions/DenseVector.h76
-rw-r--r--src/cpu/blaze/math/expressions/DivExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/EvalExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/Expression.h63
-rw-r--r--src/cpu/blaze/math/expressions/ForEachExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/Forward.h194
-rw-r--r--src/cpu/blaze/math/expressions/MatEvalExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatForEachExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatInvExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatMatAddExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatMatMultExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatMatSubExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatScalarDivExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatScalarMultExpr.h72
-rw-r--r--src/cpu/blaze/math/expressions/MatSerialExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatTransExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/MatVecMultExpr.h72
-rw-r--r--src/cpu/blaze/math/expressions/Matrix.h1331
-rw-r--r--src/cpu/blaze/math/expressions/MultExpr.h72
-rw-r--r--src/cpu/blaze/math/expressions/SMatDMatMultExpr.h2024
-rw-r--r--src/cpu/blaze/math/expressions/SMatDMatSubExpr.h1097
-rw-r--r--src/cpu/blaze/math/expressions/SMatDVecMultExpr.h949
-rw-r--r--src/cpu/blaze/math/expressions/SMatEvalExpr.h1011
-rw-r--r--src/cpu/blaze/math/expressions/SMatForEachExpr.h2591
-rw-r--r--src/cpu/blaze/math/expressions/SMatSMatAddExpr.h1058
-rw-r--r--src/cpu/blaze/math/expressions/SMatSMatMultExpr.h1433
-rw-r--r--src/cpu/blaze/math/expressions/SMatSMatSubExpr.h1056
-rw-r--r--src/cpu/blaze/math/expressions/SMatSVecMultExpr.h1077
-rw-r--r--src/cpu/blaze/math/expressions/SMatScalarDivExpr.h1201
-rw-r--r--src/cpu/blaze/math/expressions/SMatScalarMultExpr.h2540
-rw-r--r--src/cpu/blaze/math/expressions/SMatSerialExpr.h1029
-rw-r--r--src/cpu/blaze/math/expressions/SMatTDMatMultExpr.h2088
-rw-r--r--src/cpu/blaze/math/expressions/SMatTDMatSubExpr.h1022
-rw-r--r--src/cpu/blaze/math/expressions/SMatTSMatAddExpr.h1108
-rw-r--r--src/cpu/blaze/math/expressions/SMatTSMatMultExpr.h1432
-rw-r--r--src/cpu/blaze/math/expressions/SMatTSMatSubExpr.h1060
-rw-r--r--src/cpu/blaze/math/expressions/SMatTransExpr.h1110
-rw-r--r--src/cpu/blaze/math/expressions/SMatTransposer.h1149
-rw-r--r--src/cpu/blaze/math/expressions/SVecDVecCrossExpr.h573
-rw-r--r--src/cpu/blaze/math/expressions/SVecDVecDivExpr.h774
-rw-r--r--src/cpu/blaze/math/expressions/SVecDVecMultExpr.h775
-rw-r--r--src/cpu/blaze/math/expressions/SVecDVecSubExpr.h893
-rw-r--r--src/cpu/blaze/math/expressions/SVecEvalExpr.h749
-rw-r--r--src/cpu/blaze/math/expressions/SVecForEachExpr.h2059
-rw-r--r--src/cpu/blaze/math/expressions/SVecSVecAddExpr.h728
-rw-r--r--src/cpu/blaze/math/expressions/SVecSVecCrossExpr.h569
-rw-r--r--src/cpu/blaze/math/expressions/SVecSVecMultExpr.h662
-rw-r--r--src/cpu/blaze/math/expressions/SVecSVecSubExpr.h729
-rw-r--r--src/cpu/blaze/math/expressions/SVecScalarDivExpr.h1038
-rw-r--r--src/cpu/blaze/math/expressions/SVecScalarMultExpr.h2168
-rw-r--r--src/cpu/blaze/math/expressions/SVecSerialExpr.h769
-rw-r--r--src/cpu/blaze/math/expressions/SVecTDVecMultExpr.h1331
-rw-r--r--src/cpu/blaze/math/expressions/SVecTSVecMultExpr.h846
-rw-r--r--src/cpu/blaze/math/expressions/SVecTransExpr.h903
-rw-r--r--src/cpu/blaze/math/expressions/SVecTransposer.h509
-rw-r--r--src/cpu/blaze/math/expressions/SerialExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/SparseMatrix.h76
-rw-r--r--src/cpu/blaze/math/expressions/SparseVector.h76
-rw-r--r--src/cpu/blaze/math/expressions/SubExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/TDMatDMatMultExpr.h11474
-rw-r--r--src/cpu/blaze/math/expressions/TDMatDVecMultExpr.h4829
-rw-r--r--src/cpu/blaze/math/expressions/TDMatSMatAddExpr.h1082
-rw-r--r--src/cpu/blaze/math/expressions/TDMatSMatMultExpr.h2128
-rw-r--r--src/cpu/blaze/math/expressions/TDMatSMatSubExpr.h1032
-rw-r--r--src/cpu/blaze/math/expressions/TDMatSVecMultExpr.h1819
-rw-r--r--src/cpu/blaze/math/expressions/TDMatTDMatMultExpr.h8119
-rw-r--r--src/cpu/blaze/math/expressions/TDMatTSMatMultExpr.h2024
-rw-r--r--src/cpu/blaze/math/expressions/TDVecDMatMultExpr.h4864
-rw-r--r--src/cpu/blaze/math/expressions/TDVecDVecMultExpr.h261
-rw-r--r--src/cpu/blaze/math/expressions/TDVecSMatMultExpr.h1037
-rw-r--r--src/cpu/blaze/math/expressions/TDVecSVecMultExpr.h142
-rw-r--r--src/cpu/blaze/math/expressions/TDVecTDMatMultExpr.h5439
-rw-r--r--src/cpu/blaze/math/expressions/TDVecTSMatMultExpr.h884
-rw-r--r--src/cpu/blaze/math/expressions/TSMatDMatMultExpr.h2084
-rw-r--r--src/cpu/blaze/math/expressions/TSMatDMatSubExpr.h1021
-rw-r--r--src/cpu/blaze/math/expressions/TSMatDVecMultExpr.h1033
-rw-r--r--src/cpu/blaze/math/expressions/TSMatSMatMultExpr.h1519
-rw-r--r--src/cpu/blaze/math/expressions/TSMatSMatSubExpr.h1060
-rw-r--r--src/cpu/blaze/math/expressions/TSMatSVecMultExpr.h896
-rw-r--r--src/cpu/blaze/math/expressions/TSMatTDMatMultExpr.h2118
-rw-r--r--src/cpu/blaze/math/expressions/TSMatTSMatAddExpr.h1066
-rw-r--r--src/cpu/blaze/math/expressions/TSMatTSMatMultExpr.h1439
-rw-r--r--src/cpu/blaze/math/expressions/TSMatTSMatSubExpr.h1064
-rw-r--r--src/cpu/blaze/math/expressions/TSVecDMatMultExpr.h1839
-rw-r--r--src/cpu/blaze/math/expressions/TSVecDVecMultExpr.h142
-rw-r--r--src/cpu/blaze/math/expressions/TSVecSMatMultExpr.h927
-rw-r--r--src/cpu/blaze/math/expressions/TSVecSVecMultExpr.h215
-rw-r--r--src/cpu/blaze/math/expressions/TSVecTDMatMultExpr.h981
-rw-r--r--src/cpu/blaze/math/expressions/TSVecTSMatMultExpr.h1052
-rw-r--r--src/cpu/blaze/math/expressions/TVecMatMultExpr.h72
-rw-r--r--src/cpu/blaze/math/expressions/TransExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecEvalExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecForEachExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecScalarDivExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecScalarMultExpr.h72
-rw-r--r--src/cpu/blaze/math/expressions/VecSerialExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecTVecMultExpr.h72
-rw-r--r--src/cpu/blaze/math/expressions/VecTransExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecVecAddExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecVecDivExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecVecMultExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/VecVecSubExpr.h71
-rw-r--r--src/cpu/blaze/math/expressions/Vector.h770
-rw-r--r--src/cpu/blaze/math/expressions/View.h70
-rw-r--r--src/cpu/blaze/math/functors/Abs.h104
-rw-r--r--src/cpu/blaze/math/functors/Acos.h104
-rw-r--r--src/cpu/blaze/math/functors/Acosh.h104
-rw-r--r--src/cpu/blaze/math/functors/Asin.h104
-rw-r--r--src/cpu/blaze/math/functors/Asinh.h104
-rw-r--r--src/cpu/blaze/math/functors/Atan.h104
-rw-r--r--src/cpu/blaze/math/functors/Atanh.h104
-rw-r--r--src/cpu/blaze/math/functors/CTrans.h77
-rw-r--r--src/cpu/blaze/math/functors/Cbrt.h104
-rw-r--r--src/cpu/blaze/math/functors/Ceil.h104
-rw-r--r--src/cpu/blaze/math/functors/Conj.h104
-rw-r--r--src/cpu/blaze/math/functors/Cos.h104
-rw-r--r--src/cpu/blaze/math/functors/Cosh.h104
-rw-r--r--src/cpu/blaze/math/functors/Erf.h104
-rw-r--r--src/cpu/blaze/math/functors/Erfc.h104
-rw-r--r--src/cpu/blaze/math/functors/Eval.h77
-rw-r--r--src/cpu/blaze/math/functors/Exp.h104
-rw-r--r--src/cpu/blaze/math/functors/Floor.h104
-rw-r--r--src/cpu/blaze/math/functors/Forward.h83
-rw-r--r--src/cpu/blaze/math/functors/Functors.h51
-rw-r--r--src/cpu/blaze/math/functors/Imag.h78
-rw-r--r--src/cpu/blaze/math/functors/Inv.h78
-rw-r--r--src/cpu/blaze/math/functors/InvCbrt.h104
-rw-r--r--src/cpu/blaze/math/functors/InvSqrt.h104
-rw-r--r--src/cpu/blaze/math/functors/Log.h104
-rw-r--r--src/cpu/blaze/math/functors/Log10.h104
-rw-r--r--src/cpu/blaze/math/functors/Pow.h139
-rw-r--r--src/cpu/blaze/math/functors/Real.h78
-rw-r--r--src/cpu/blaze/math/functors/Serial.h77
-rw-r--r--src/cpu/blaze/math/functors/Sin.h104
-rw-r--r--src/cpu/blaze/math/functors/Sinh.h104
-rw-r--r--src/cpu/blaze/math/functors/Sqrt.h104
-rw-r--r--src/cpu/blaze/math/functors/Tan.h104
-rw-r--r--src/cpu/blaze/math/functors/Tanh.h104
-rw-r--r--src/cpu/blaze/math/functors/Trans.h77
-rw-r--r--src/cpu/blaze/math/lapack/LAPACK.h79
-rw-r--r--src/cpu/blaze/math/lapack/clapack/gelqf.h326
-rw-r--r--src/cpu/blaze/math/lapack/clapack/geqlf.h330
-rw-r--r--src/cpu/blaze/math/lapack/clapack/geqp3.h194
-rw-r--r--src/cpu/blaze/math/lapack/clapack/geqrf.h326
-rw-r--r--src/cpu/blaze/math/lapack/clapack/gerqf.h330
-rw-r--r--src/cpu/blaze/math/lapack/clapack/gesv.h294
-rw-r--r--src/cpu/blaze/math/lapack/clapack/getrf.h272
-rw-r--r--src/cpu/blaze/math/lapack/clapack/getri.h270
-rw-r--r--src/cpu/blaze/math/lapack/clapack/getrs.h288
-rw-r--r--src/cpu/blaze/math/lapack/clapack/hesv.h206
-rw-r--r--src/cpu/blaze/math/lapack/clapack/hetrf.h204
-rw-r--r--src/cpu/blaze/math/lapack/clapack/hetri.h172
-rw-r--r--src/cpu/blaze/math/lapack/clapack/hetrs.h176
-rw-r--r--src/cpu/blaze/math/lapack/clapack/orglq.h162
-rw-r--r--src/cpu/blaze/math/lapack/clapack/orgql.h162
-rw-r--r--src/cpu/blaze/math/lapack/clapack/orgqr.h162
-rw-r--r--src/cpu/blaze/math/lapack/clapack/orgrq.h162
-rw-r--r--src/cpu/blaze/math/lapack/clapack/ormlq.h190
-rw-r--r--src/cpu/blaze/math/lapack/clapack/ormql.h190
-rw-r--r--src/cpu/blaze/math/lapack/clapack/ormqr.h190
-rw-r--r--src/cpu/blaze/math/lapack/clapack/ormrq.h190
-rw-r--r--src/cpu/blaze/math/lapack/clapack/posv.h302
-rw-r--r--src/cpu/blaze/math/lapack/clapack/potrf.h272
-rw-r--r--src/cpu/blaze/math/lapack/clapack/potri.h244
-rw-r--r--src/cpu/blaze/math/lapack/clapack/potrs.h256
-rw-r--r--src/cpu/blaze/math/lapack/clapack/sysv.h326
-rw-r--r--src/cpu/blaze/math/lapack/clapack/sytrf.h322
-rw-r--r--src/cpu/blaze/math/lapack/clapack/sytri.h254
-rw-r--r--src/cpu/blaze/math/lapack/clapack/sytrs.h268
-rw-r--r--src/cpu/blaze/math/lapack/clapack/trsv.h270
-rw-r--r--src/cpu/blaze/math/lapack/clapack/trtri.h244
-rw-r--r--src/cpu/blaze/math/lapack/clapack/trtrs.h286
-rw-r--r--src/cpu/blaze/math/lapack/clapack/unglq.h172
-rw-r--r--src/cpu/blaze/math/lapack/clapack/ungql.h172
-rw-r--r--src/cpu/blaze/math/lapack/clapack/ungqr.h172
-rw-r--r--src/cpu/blaze/math/lapack/clapack/ungrq.h172
-rw-r--r--src/cpu/blaze/math/lapack/clapack/unmlq.h212
-rw-r--r--src/cpu/blaze/math/lapack/clapack/unmql.h212
-rw-r--r--src/cpu/blaze/math/lapack/clapack/unmqr.h212
-rw-r--r--src/cpu/blaze/math/lapack/clapack/unmrq.h212
-rw-r--r--src/cpu/blaze/math/lapack/gelqf.h152
-rw-r--r--src/cpu/blaze/math/lapack/geqlf.h153
-rw-r--r--src/cpu/blaze/math/lapack/geqp3.h45
-rw-r--r--src/cpu/blaze/math/lapack/geqrf.h152
-rw-r--r--src/cpu/blaze/math/lapack/gerqf.h153
-rw-r--r--src/cpu/blaze/math/lapack/gesv.h273
-rw-r--r--src/cpu/blaze/math/lapack/getrf.h147
-rw-r--r--src/cpu/blaze/math/lapack/getri.h147
-rw-r--r--src/cpu/blaze/math/lapack/getrs.h336
-rw-r--r--src/cpu/blaze/math/lapack/hesv.h314
-rw-r--r--src/cpu/blaze/math/lapack/hetrf.h161
-rw-r--r--src/cpu/blaze/math/lapack/hetri.h159
-rw-r--r--src/cpu/blaze/math/lapack/hetrs.h343
-rw-r--r--src/cpu/blaze/math/lapack/orglq.h154
-rw-r--r--src/cpu/blaze/math/lapack/orgql.h157
-rw-r--r--src/cpu/blaze/math/lapack/orgqr.h154
-rw-r--r--src/cpu/blaze/math/lapack/orgrq.h157
-rw-r--r--src/cpu/blaze/math/lapack/ormlq.h201
-rw-r--r--src/cpu/blaze/math/lapack/ormql.h202
-rw-r--r--src/cpu/blaze/math/lapack/ormqr.h201
-rw-r--r--src/cpu/blaze/math/lapack/ormrq.h202
-rw-r--r--src/cpu/blaze/math/lapack/posv.h299
-rw-r--r--src/cpu/blaze/math/lapack/potrf.h157
-rw-r--r--src/cpu/blaze/math/lapack/potri.h154
-rw-r--r--src/cpu/blaze/math/lapack/potrs.h336
-rw-r--r--src/cpu/blaze/math/lapack/sysv.h314
-rw-r--r--src/cpu/blaze/math/lapack/sytrf.h161
-rw-r--r--src/cpu/blaze/math/lapack/sytri.h158
-rw-r--r--src/cpu/blaze/math/lapack/sytrs.h343
-rw-r--r--src/cpu/blaze/math/lapack/trsv.h210
-rw-r--r--src/cpu/blaze/math/lapack/trtri.h159
-rw-r--r--src/cpu/blaze/math/lapack/trtrs.h362
-rw-r--r--src/cpu/blaze/math/lapack/unglq.h156
-rw-r--r--src/cpu/blaze/math/lapack/ungql.h159
-rw-r--r--src/cpu/blaze/math/lapack/ungqr.h156
-rw-r--r--src/cpu/blaze/math/lapack/ungrq.h158
-rw-r--r--src/cpu/blaze/math/lapack/unmlq.h195
-rw-r--r--src/cpu/blaze/math/lapack/unmql.h196
-rw-r--r--src/cpu/blaze/math/lapack/unmqr.h195
-rw-r--r--src/cpu/blaze/math/lapack/unmrq.h196
-rw-r--r--src/cpu/blaze/math/proxy/ComplexProxy.h227
-rw-r--r--src/cpu/blaze/math/proxy/DefaultProxy.h119
-rw-r--r--src/cpu/blaze/math/proxy/DenseMatrixProxy.h1109
-rw-r--r--src/cpu/blaze/math/proxy/DenseVectorProxy.h757
-rw-r--r--src/cpu/blaze/math/proxy/Forward.h57
-rw-r--r--src/cpu/blaze/math/proxy/Proxy.h1793
-rw-r--r--src/cpu/blaze/math/proxy/SparseMatrixProxy.h1339
-rw-r--r--src/cpu/blaze/math/proxy/SparseVectorProxy.h886
-rw-r--r--src/cpu/blaze/math/serialization/MatrixSerializer.h1298
-rw-r--r--src/cpu/blaze/math/serialization/Serialization.h126
-rw-r--r--src/cpu/blaze/math/serialization/TypeValueMapping.h180
-rw-r--r--src/cpu/blaze/math/serialization/VectorSerializer.h887
-rw-r--r--src/cpu/blaze/math/shims/Abs.h63
-rw-r--r--src/cpu/blaze/math/shims/Acos.h63
-rw-r--r--src/cpu/blaze/math/shims/Acosh.h63
-rw-r--r--src/cpu/blaze/math/shims/Asin.h63
-rw-r--r--src/cpu/blaze/math/shims/Asinh.h63
-rw-r--r--src/cpu/blaze/math/shims/Atan.h63
-rw-r--r--src/cpu/blaze/math/shims/Atanh.h63
-rw-r--r--src/cpu/blaze/math/shims/Cbrt.h63
-rw-r--r--src/cpu/blaze/math/shims/Ceil.h63
-rw-r--r--src/cpu/blaze/math/shims/Clear.h73
-rw-r--r--src/cpu/blaze/math/shims/Conjugate.h203
-rw-r--r--src/cpu/blaze/math/shims/Cos.h63
-rw-r--r--src/cpu/blaze/math/shims/Cosh.h63
-rw-r--r--src/cpu/blaze/math/shims/Equal.h383
-rw-r--r--src/cpu/blaze/math/shims/Erf.h63
-rw-r--r--src/cpu/blaze/math/shims/Erfc.h63
-rw-r--r--src/cpu/blaze/math/shims/Exp.h63
-rw-r--r--src/cpu/blaze/math/shims/Floor.h63
-rw-r--r--src/cpu/blaze/math/shims/Imaginary.h94
-rw-r--r--src/cpu/blaze/math/shims/InvCbrt.h79
-rw-r--r--src/cpu/blaze/math/shims/InvSqrt.h100
-rw-r--r--src/cpu/blaze/math/shims/Invert.h318
-rw-r--r--src/cpu/blaze/math/shims/IsDefault.h168
-rw-r--r--src/cpu/blaze/math/shims/IsDivisor.h89
-rw-r--r--src/cpu/blaze/math/shims/IsNaN.h87
-rw-r--r--src/cpu/blaze/math/shims/IsOne.h108
-rw-r--r--src/cpu/blaze/math/shims/IsReal.h109
-rw-r--r--src/cpu/blaze/math/shims/IsZero.h108
-rw-r--r--src/cpu/blaze/math/shims/Log.h63
-rw-r--r--src/cpu/blaze/math/shims/Log10.h63
-rw-r--r--src/cpu/blaze/math/shims/Pow.h63
-rw-r--r--src/cpu/blaze/math/shims/Real.h91
-rw-r--r--src/cpu/blaze/math/shims/Reset.h73
-rw-r--r--src/cpu/blaze/math/shims/Serial.h79
-rw-r--r--src/cpu/blaze/math/shims/Shims.h51
-rw-r--r--src/cpu/blaze/math/shims/Sin.h63
-rw-r--r--src/cpu/blaze/math/shims/Sinh.h63
-rw-r--r--src/cpu/blaze/math/shims/Sqrt.h63
-rw-r--r--src/cpu/blaze/math/shims/Square.h75
-rw-r--r--src/cpu/blaze/math/shims/Tan.h63
-rw-r--r--src/cpu/blaze/math/shims/Tanh.h63
-rw-r--r--src/cpu/blaze/math/simd/Abs.h177
-rw-r--r--src/cpu/blaze/math/simd/Acos.h123
-rw-r--r--src/cpu/blaze/math/simd/Acosh.h123
-rw-r--r--src/cpu/blaze/math/simd/Addition.h573
-rw-r--r--src/cpu/blaze/math/simd/Asin.h123
-rw-r--r--src/cpu/blaze/math/simd/Asinh.h123
-rw-r--r--src/cpu/blaze/math/simd/Atan.h123
-rw-r--r--src/cpu/blaze/math/simd/Atanh.h123
-rw-r--r--src/cpu/blaze/math/simd/BasicTypes.h1348
-rw-r--r--src/cpu/blaze/math/simd/Cbrt.h123
-rw-r--r--src/cpu/blaze/math/simd/Ceil.h125
-rw-r--r--src/cpu/blaze/math/simd/Conj.h298
-rw-r--r--src/cpu/blaze/math/simd/Cos.h123
-rw-r--r--src/cpu/blaze/math/simd/Cosh.h123
-rw-r--r--src/cpu/blaze/math/simd/DerivedTypes.h216
-rw-r--r--src/cpu/blaze/math/simd/Division.h293
-rw-r--r--src/cpu/blaze/math/simd/Erf.h123
-rw-r--r--src/cpu/blaze/math/simd/Erfc.h125
-rw-r--r--src/cpu/blaze/math/simd/Exp.h123
-rw-r--r--src/cpu/blaze/math/simd/FMA.h1476
-rw-r--r--src/cpu/blaze/math/simd/Floor.h125
-rw-r--r--src/cpu/blaze/math/simd/Functions.h83
-rw-r--r--src/cpu/blaze/math/simd/InvCbrt.h115
-rw-r--r--src/cpu/blaze/math/simd/InvSqrt.h123
-rw-r--r--src/cpu/blaze/math/simd/Loada.h465
-rw-r--r--src/cpu/blaze/math/simd/Loadu.h457
-rw-r--r--src/cpu/blaze/math/simd/Log.h123
-rw-r--r--src/cpu/blaze/math/simd/Log10.h123
-rw-r--r--src/cpu/blaze/math/simd/Multiplication.h881
-rw-r--r--src/cpu/blaze/math/simd/Pow.h125
-rw-r--r--src/cpu/blaze/math/simd/Reduction.h364
-rw-r--r--src/cpu/blaze/math/simd/SIMD.h51
-rw-r--r--src/cpu/blaze/math/simd/SIMDPack.h89
-rw-r--r--src/cpu/blaze/math/simd/SIMDTrait.h320
-rw-r--r--src/cpu/blaze/math/simd/Set.h417
-rw-r--r--src/cpu/blaze/math/simd/Setzero.h361
-rw-r--r--src/cpu/blaze/math/simd/Sin.h123
-rw-r--r--src/cpu/blaze/math/simd/Sinh.h123
-rw-r--r--src/cpu/blaze/math/simd/Sqrt.h123
-rw-r--r--src/cpu/blaze/math/simd/Storea.h477
-rw-r--r--src/cpu/blaze/math/simd/Storeu.h455
-rw-r--r--src/cpu/blaze/math/simd/Stream.h429
-rw-r--r--src/cpu/blaze/math/simd/Subtraction.h573
-rw-r--r--src/cpu/blaze/math/simd/Tan.h123
-rw-r--r--src/cpu/blaze/math/simd/Tanh.h123
-rw-r--r--src/cpu/blaze/math/smp/DenseMatrix.h53
-rw-r--r--src/cpu/blaze/math/smp/DenseVector.h53
-rw-r--r--src/cpu/blaze/math/smp/Functions.h53
-rw-r--r--src/cpu/blaze/math/smp/ParallelSection.h252
-rw-r--r--src/cpu/blaze/math/smp/SMP.h51
-rw-r--r--src/cpu/blaze/math/smp/SerialSection.h268
-rw-r--r--src/cpu/blaze/math/smp/SparseMatrix.h45
-rw-r--r--src/cpu/blaze/math/smp/SparseVector.h45
-rw-r--r--src/cpu/blaze/math/smp/default/DenseMatrix.h193
-rw-r--r--src/cpu/blaze/math/smp/default/DenseVector.h253
-rw-r--r--src/cpu/blaze/math/smp/default/Functions.h154
-rw-r--r--src/cpu/blaze/math/smp/default/SparseMatrix.h171
-rw-r--r--src/cpu/blaze/math/smp/default/SparseVector.h200
-rw-r--r--src/cpu/blaze/math/smp/openmp/DenseMatrix.h1165
-rw-r--r--src/cpu/blaze/math/smp/openmp/DenseVector.h1129
-rw-r--r--src/cpu/blaze/math/smp/openmp/Functions.h154
-rw-r--r--src/cpu/blaze/math/smp/threads/DenseMatrix.h1182
-rw-r--r--src/cpu/blaze/math/smp/threads/DenseVector.h1145
-rw-r--r--src/cpu/blaze/math/smp/threads/Functions.h156
-rw-r--r--src/cpu/blaze/math/smp/threads/ThreadBackend.h665
-rw-r--r--src/cpu/blaze/math/sparse/CompressedMatrix.h5650
-rw-r--r--src/cpu/blaze/math/sparse/CompressedVector.h2655
-rw-r--r--src/cpu/blaze/math/sparse/Forward.h52
-rw-r--r--src/cpu/blaze/math/sparse/MatrixAccessProxy.h694
-rw-r--r--src/cpu/blaze/math/sparse/SparseElement.h63
-rw-r--r--src/cpu/blaze/math/sparse/SparseMatrix.h1589
-rw-r--r--src/cpu/blaze/math/sparse/SparseVector.h488
-rw-r--r--src/cpu/blaze/math/sparse/ValueIndexPair.h337
-rw-r--r--src/cpu/blaze/math/sparse/VectorAccessProxy.h673
-rw-r--r--src/cpu/blaze/math/traits/AddExprTrait.h224
-rw-r--r--src/cpu/blaze/math/traits/AddTrait.h236
-rw-r--r--src/cpu/blaze/math/traits/CTransExprTrait.h148
-rw-r--r--src/cpu/blaze/math/traits/ColumnExprTrait.h138
-rw-r--r--src/cpu/blaze/math/traits/ColumnTrait.h157
-rw-r--r--src/cpu/blaze/math/traits/CrossExprTrait.h155
-rw-r--r--src/cpu/blaze/math/traits/CrossTrait.h140
-rw-r--r--src/cpu/blaze/math/traits/DMatCTransExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/DMatDMatAddExprTrait.h121
-rw-r--r--src/cpu/blaze/math/traits/DMatDMatMultExprTrait.h121
-rw-r--r--src/cpu/blaze/math/traits/DMatDMatSubExprTrait.h121
-rw-r--r--src/cpu/blaze/math/traits/DMatDVecMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/DMatEvalExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/DMatForEachExprTrait.h119
-rw-r--r--src/cpu/blaze/math/traits/DMatInvExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/DMatSMatAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/DMatSMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/DMatSMatSubExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/DMatSVecMultExprTrait.h128
-rw-r--r--src/cpu/blaze/math/traits/DMatScalarDivExprTrait.h172
-rw-r--r--src/cpu/blaze/math/traits/DMatScalarMultExprTrait.h169
-rw-r--r--src/cpu/blaze/math/traits/DMatSerialExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/DMatTDMatAddExprTrait.h131
-rw-r--r--src/cpu/blaze/math/traits/DMatTDMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/DMatTDMatSubExprTrait.h131
-rw-r--r--src/cpu/blaze/math/traits/DMatTSMatAddExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/DMatTSMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/DMatTSMatSubExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/DMatTransExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/DVecCTransExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/DVecDVecAddExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/DVecDVecCrossExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/DVecDVecDivExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/DVecDVecMultExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/DVecDVecSubExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/DVecEvalExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/DVecForEachExprTrait.h119
-rw-r--r--src/cpu/blaze/math/traits/DVecSVecAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/DVecSVecCrossExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/DVecSVecMultExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/DVecSVecSubExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/DVecScalarDivExprTrait.h172
-rw-r--r--src/cpu/blaze/math/traits/DVecScalarMultExprTrait.h169
-rw-r--r--src/cpu/blaze/math/traits/DVecSerialExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/DVecTDVecMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/DVecTSVecMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/DVecTransExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/DerestrictTrait.h115
-rw-r--r--src/cpu/blaze/math/traits/DivExprTrait.h201
-rw-r--r--src/cpu/blaze/math/traits/DivTrait.h236
-rw-r--r--src/cpu/blaze/math/traits/EvalExprTrait.h147
-rw-r--r--src/cpu/blaze/math/traits/ForEachExprTrait.h149
-rw-r--r--src/cpu/blaze/math/traits/ForEachTrait.h151
-rw-r--r--src/cpu/blaze/math/traits/ImagTrait.h157
-rw-r--r--src/cpu/blaze/math/traits/InvExprTrait.h139
-rw-r--r--src/cpu/blaze/math/traits/MathTrait.h775
-rw-r--r--src/cpu/blaze/math/traits/MultExprTrait.h349
-rw-r--r--src/cpu/blaze/math/traits/MultTrait.h236
-rw-r--r--src/cpu/blaze/math/traits/RealTrait.h157
-rw-r--r--src/cpu/blaze/math/traits/RowExprTrait.h139
-rw-r--r--src/cpu/blaze/math/traits/RowTrait.h157
-rw-r--r--src/cpu/blaze/math/traits/SMatCTransExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/SMatDMatAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/SMatDMatMultExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/SMatDMatSubExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/SMatDVecMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SMatEvalExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/SMatForEachExprTrait.h119
-rw-r--r--src/cpu/blaze/math/traits/SMatSMatAddExprTrait.h121
-rw-r--r--src/cpu/blaze/math/traits/SMatSMatMultExprTrait.h121
-rw-r--r--src/cpu/blaze/math/traits/SMatSMatSubExprTrait.h121
-rw-r--r--src/cpu/blaze/math/traits/SMatSVecMultExprTrait.h128
-rw-r--r--src/cpu/blaze/math/traits/SMatScalarDivExprTrait.h172
-rw-r--r--src/cpu/blaze/math/traits/SMatScalarMultExprTrait.h169
-rw-r--r--src/cpu/blaze/math/traits/SMatSerialExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/SMatTDMatAddExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SMatTDMatMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/SMatTDMatSubExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/SMatTSMatAddExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SMatTSMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SMatTSMatSubExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SMatTransExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/SVecCTransExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/SVecDVecAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/SVecDVecCrossExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SVecDVecDivExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SVecDVecMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SVecDVecSubExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/SVecEvalExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/SVecForEachExprTrait.h119
-rw-r--r--src/cpu/blaze/math/traits/SVecSVecAddExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/SVecSVecCrossExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/SVecSVecMultExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/SVecSVecSubExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/SVecScalarDivExprTrait.h172
-rw-r--r--src/cpu/blaze/math/traits/SVecScalarMultExprTrait.h169
-rw-r--r--src/cpu/blaze/math/traits/SVecSerialExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/SVecTDVecMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/SVecTSVecMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/SVecTransExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/SerialExprTrait.h147
-rw-r--r--src/cpu/blaze/math/traits/SubExprTrait.h225
-rw-r--r--src/cpu/blaze/math/traits/SubTrait.h236
-rw-r--r--src/cpu/blaze/math/traits/SubmatrixExprTrait.h138
-rw-r--r--src/cpu/blaze/math/traits/SubmatrixTrait.h158
-rw-r--r--src/cpu/blaze/math/traits/SubvectorExprTrait.h138
-rw-r--r--src/cpu/blaze/math/traits/SubvectorTrait.h160
-rw-r--r--src/cpu/blaze/math/traits/TDMatCTransExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDMatDMatAddExprTrait.h130
-rw-r--r--src/cpu/blaze/math/traits/TDMatDMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TDMatDMatSubExprTrait.h130
-rw-r--r--src/cpu/blaze/math/traits/TDMatDVecMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDMatEvalExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TDMatForEachExprTrait.h119
-rw-r--r--src/cpu/blaze/math/traits/TDMatInvExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TDMatSMatAddExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TDMatSMatMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDMatSMatSubExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDMatSVecMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDMatScalarDivExprTrait.h172
-rw-r--r--src/cpu/blaze/math/traits/TDMatScalarMultExprTrait.h169
-rw-r--r--src/cpu/blaze/math/traits/TDMatSerialExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TDMatTDMatAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TDMatTDMatMultExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TDMatTDMatSubExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TDMatTSMatAddExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDMatTSMatMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDMatTSMatSubExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDMatTransExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TDVecCTransExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDVecDMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TDVecDVecMultExprTrait.h157
-rw-r--r--src/cpu/blaze/math/traits/TDVecEvalExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TDVecForEachExprTrait.h119
-rw-r--r--src/cpu/blaze/math/traits/TDVecSMatMultExprTrait.h128
-rw-r--r--src/cpu/blaze/math/traits/TDVecSVecMultExprTrait.h158
-rw-r--r--src/cpu/blaze/math/traits/TDVecScalarDivExprTrait.h172
-rw-r--r--src/cpu/blaze/math/traits/TDVecScalarMultExprTrait.h169
-rw-r--r--src/cpu/blaze/math/traits/TDVecSerialExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TDVecTDMatMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDVecTDVecAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TDVecTDVecCrossExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/TDVecTDVecDivExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TDVecTDVecMultExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TDVecTDVecSubExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TDVecTSMatMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TDVecTSVecAddExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TDVecTSVecCrossExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TDVecTSVecMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TDVecTSVecSubExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TDVecTransExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TSMatCTransExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TSMatDMatAddExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSMatDMatMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TSMatDMatSubExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSMatDVecMultExprTrait.h129
-rw-r--r--src/cpu/blaze/math/traits/TSMatEvalExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TSMatForEachExprTrait.h119
-rw-r--r--src/cpu/blaze/math/traits/TSMatSMatAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TSMatSMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSMatSMatSubExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSMatSVecMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TSMatScalarDivExprTrait.h172
-rw-r--r--src/cpu/blaze/math/traits/TSMatScalarMultExprTrait.h169
-rw-r--r--src/cpu/blaze/math/traits/TSMatSerialExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TSMatTDMatAddExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TSMatTDMatMultExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TSMatTDMatSubExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TSMatTSMatAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TSMatTSMatMultExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TSMatTSMatSubExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TSMatTransExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TSVecCTransExprTrait.h125
-rw-r--r--src/cpu/blaze/math/traits/TSVecDMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSVecDVecMultExprTrait.h158
-rw-r--r--src/cpu/blaze/math/traits/TSVecEvalExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TSVecForEachExprTrait.h119
-rw-r--r--src/cpu/blaze/math/traits/TSVecSMatMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSVecSVecMultExprTrait.h157
-rw-r--r--src/cpu/blaze/math/traits/TSVecScalarDivExprTrait.h172
-rw-r--r--src/cpu/blaze/math/traits/TSVecScalarMultExprTrait.h169
-rw-r--r--src/cpu/blaze/math/traits/TSVecSerialExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/TSVecTDMatMultExprTrait.h129
-rw-r--r--src/cpu/blaze/math/traits/TSVecTDVecAddExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSVecTDVecCrossExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TSVecTDVecDivExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSVecTDVecMultExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSVecTDVecSubExprTrait.h124
-rw-r--r--src/cpu/blaze/math/traits/TSVecTSMatMultExprTrait.h129
-rw-r--r--src/cpu/blaze/math/traits/TSVecTSVecAddExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TSVecTSVecCrossExprTrait.h122
-rw-r--r--src/cpu/blaze/math/traits/TSVecTSVecMultExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TSVecTSVecSubExprTrait.h123
-rw-r--r--src/cpu/blaze/math/traits/TSVecTransExprTrait.h116
-rw-r--r--src/cpu/blaze/math/traits/Traits.h51
-rw-r--r--src/cpu/blaze/math/traits/TransExprTrait.h148
-rw-r--r--src/cpu/blaze/math/typetraits/AreSIMDCombinable.h128
-rw-r--r--src/cpu/blaze/math/typetraits/Columns.h118
-rw-r--r--src/cpu/blaze/math/typetraits/HasConstDataAccess.h117
-rw-r--r--src/cpu/blaze/math/typetraits/HasMutableDataAccess.h117
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDAbs.h116
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDAcos.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDAcosh.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDAdd.h168
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDAsin.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDAsinh.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDAtan.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDAtanh.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDCbrt.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDCeil.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDConj.h112
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDCos.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDCosh.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDDiv.h150
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDErf.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDErfc.h116
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDExp.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDFloor.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDInvCbrt.h113
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDInvSqrt.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDLog.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDLog10.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDMult.h168
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDPow.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDSin.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDSinh.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDSqrt.h122
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDSub.h169
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDTan.h115
-rw-r--r--src/cpu/blaze/math/typetraits/HasSIMDTanh.h115
-rw-r--r--src/cpu/blaze/math/typetraits/IsAdaptor.h130
-rw-r--r--src/cpu/blaze/math/typetraits/IsAddExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsAligned.h129
-rw-r--r--src/cpu/blaze/math/typetraits/IsBLASCompatible.h87
-rw-r--r--src/cpu/blaze/math/typetraits/IsColumn.h139
-rw-r--r--src/cpu/blaze/math/typetraits/IsColumnMajorMatrix.h90
-rw-r--r--src/cpu/blaze/math/typetraits/IsColumnVector.h87
-rw-r--r--src/cpu/blaze/math/typetraits/IsComputation.h79
-rw-r--r--src/cpu/blaze/math/typetraits/IsCrossExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsCustom.h126
-rw-r--r--src/cpu/blaze/math/typetraits/IsDenseMatrix.h86
-rw-r--r--src/cpu/blaze/math/typetraits/IsDenseVector.h86
-rw-r--r--src/cpu/blaze/math/typetraits/IsDiagonal.h132
-rw-r--r--src/cpu/blaze/math/typetraits/IsDivExpr.h79
-rw-r--r--src/cpu/blaze/math/typetraits/IsEvalExpr.h77
-rw-r--r--src/cpu/blaze/math/typetraits/IsExpression.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsForEachExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsGeneral.h133
-rw-r--r--src/cpu/blaze/math/typetraits/IsHermitian.h127
-rw-r--r--src/cpu/blaze/math/typetraits/IsIdentity.h132
-rw-r--r--src/cpu/blaze/math/typetraits/IsInvertible.h93
-rw-r--r--src/cpu/blaze/math/typetraits/IsLower.h130
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatEvalExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatForEachExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatInvExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatMatAddExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatMatMultExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatMatSubExpr.h79
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatScalarDivExpr.h79
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatScalarMultExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatSerialExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatTransExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatVecMultExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsMatrix.h86
-rw-r--r--src/cpu/blaze/math/typetraits/IsMultExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsNumericMatrix.h93
-rw-r--r--src/cpu/blaze/math/typetraits/IsNumericVector.h93
-rw-r--r--src/cpu/blaze/math/typetraits/IsOpposedView.h123
-rw-r--r--src/cpu/blaze/math/typetraits/IsPadded.h118
-rw-r--r--src/cpu/blaze/math/typetraits/IsProxy.h116
-rw-r--r--src/cpu/blaze/math/typetraits/IsResizable.h117
-rw-r--r--src/cpu/blaze/math/typetraits/IsRestricted.h124
-rw-r--r--src/cpu/blaze/math/typetraits/IsRow.h139
-rw-r--r--src/cpu/blaze/math/typetraits/IsRowMajorMatrix.h90
-rw-r--r--src/cpu/blaze/math/typetraits/IsRowVector.h87
-rw-r--r--src/cpu/blaze/math/typetraits/IsSIMDEnabled.h106
-rw-r--r--src/cpu/blaze/math/typetraits/IsSIMDPack.h121
-rw-r--r--src/cpu/blaze/math/typetraits/IsSMPAssignable.h125
-rw-r--r--src/cpu/blaze/math/typetraits/IsSerialExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsSparseElement.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsSparseMatrix.h86
-rw-r--r--src/cpu/blaze/math/typetraits/IsSparseVector.h86
-rw-r--r--src/cpu/blaze/math/typetraits/IsSquare.h130
-rw-r--r--src/cpu/blaze/math/typetraits/IsStrictlyLower.h128
-rw-r--r--src/cpu/blaze/math/typetraits/IsStrictlyTriangular.h94
-rw-r--r--src/cpu/blaze/math/typetraits/IsStrictlyUpper.h128
-rw-r--r--src/cpu/blaze/math/typetraits/IsSubExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsSubmatrix.h139
-rw-r--r--src/cpu/blaze/math/typetraits/IsSubvector.h139
-rw-r--r--src/cpu/blaze/math/typetraits/IsSymmetric.h127
-rw-r--r--src/cpu/blaze/math/typetraits/IsTVecMatMultExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsTemporary.h77
-rw-r--r--src/cpu/blaze/math/typetraits/IsTransExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsTriangular.h93
-rw-r--r--src/cpu/blaze/math/typetraits/IsUniLower.h128
-rw-r--r--src/cpu/blaze/math/typetraits/IsUniTriangular.h93
-rw-r--r--src/cpu/blaze/math/typetraits/IsUniUpper.h128
-rw-r--r--src/cpu/blaze/math/typetraits/IsUpper.h130
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecEvalExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecForEachExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecScalarDivExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecScalarMultExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecSerialExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecTVecMultExpr.h79
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecTransExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecVecAddExpr.h78
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecVecDivExpr.h79
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecVecMultExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsVecVecSubExpr.h80
-rw-r--r--src/cpu/blaze/math/typetraits/IsVector.h86
-rw-r--r--src/cpu/blaze/math/typetraits/IsView.h93
-rw-r--r--src/cpu/blaze/math/typetraits/RemoveAdaptor.h158
-rw-r--r--src/cpu/blaze/math/typetraits/RequiresEvaluation.h79
-rw-r--r--src/cpu/blaze/math/typetraits/Rows.h118
-rw-r--r--src/cpu/blaze/math/typetraits/Size.h117
-rw-r--r--src/cpu/blaze/math/typetraits/StorageOrder.h83
-rw-r--r--src/cpu/blaze/math/typetraits/TransposeFlag.h83
-rw-r--r--src/cpu/blaze/math/typetraits/TypeTraits.h51
-rw-r--r--src/cpu/blaze/math/typetraits/UnderlyingBuiltin.h138
-rw-r--r--src/cpu/blaze/math/typetraits/UnderlyingElement.h138
-rw-r--r--src/cpu/blaze/math/typetraits/UnderlyingNumeric.h130
-rw-r--r--src/cpu/blaze/math/views/Column.h1074
-rw-r--r--src/cpu/blaze/math/views/Forward.h54
-rw-r--r--src/cpu/blaze/math/views/Row.h1072
-rw-r--r--src/cpu/blaze/math/views/Submatrix.h2159
-rw-r--r--src/cpu/blaze/math/views/Subvector.h1500
-rw-r--r--src/cpu/blaze/math/views/Views.h51
-rw-r--r--src/cpu/blaze/math/views/column/BaseTemplate.h360
-rw-r--r--src/cpu/blaze/math/views/column/Dense.h5817
-rw-r--r--src/cpu/blaze/math/views/column/Sparse.h5360
-rw-r--r--src/cpu/blaze/math/views/row/BaseTemplate.h361
-rw-r--r--src/cpu/blaze/math/views/row/Dense.h5800
-rw-r--r--src/cpu/blaze/math/views/row/Sparse.h5340
-rw-r--r--src/cpu/blaze/math/views/submatrix/BaseTemplate.h509
-rw-r--r--src/cpu/blaze/math/views/submatrix/Dense.h11127
-rw-r--r--src/cpu/blaze/math/views/submatrix/Sparse.h4940
-rw-r--r--src/cpu/blaze/math/views/subvector/BaseTemplate.h440
-rw-r--r--src/cpu/blaze/math/views/subvector/Dense.h5270
-rw-r--r--src/cpu/blaze/math/views/subvector/Sparse.h2004
-rw-r--r--src/cpu/blaze/system/Assertion.h47
-rw-r--r--src/cpu/blaze/system/BLAS.h62
-rw-r--r--src/cpu/blaze/system/Blocking.h129
-rw-r--r--src/cpu/blaze/system/CacheSize.h76
-rw-r--r--src/cpu/blaze/system/Debugging.h64
-rw-r--r--src/cpu/blaze/system/Deprecated.h68
-rw-r--r--src/cpu/blaze/system/Inline.h89
-rw-r--r--src/cpu/blaze/system/Logging.h56
-rw-r--r--src/cpu/blaze/system/MPI.h47
-rw-r--r--src/cpu/blaze/system/Optimizations.h47
-rw-r--r--src/cpu/blaze/system/Precision.h75
-rw-r--r--src/cpu/blaze/system/Random.h56
-rw-r--r--src/cpu/blaze/system/Restrict.h85
-rw-r--r--src/cpu/blaze/system/SMP.h126
-rw-r--r--src/cpu/blaze/system/Signature.h72
-rw-r--r--src/cpu/blaze/system/StorageOrder.h56
-rw-r--r--src/cpu/blaze/system/System.h52
-rw-r--r--src/cpu/blaze/system/Thresholds.h1034
-rw-r--r--src/cpu/blaze/system/TransposeFlag.h56
-rw-r--r--src/cpu/blaze/system/Vectorization.h349
-rw-r--r--src/cpu/blaze/system/Version.h66
-rw-r--r--src/cpu/blaze/system/WarningDisable.h79
-rw-r--r--src/cpu/blaze/util/Algorithm.h150
-rw-r--r--src/cpu/blaze/util/AlignedAllocator.h387
-rw-r--r--src/cpu/blaze/util/AlignedArray.h501
-rw-r--r--src/cpu/blaze/util/AlignmentCheck.h76
-rw-r--r--src/cpu/blaze/util/Assert.h123
-rw-r--r--src/cpu/blaze/util/ColorMacros.h166
-rw-r--r--src/cpu/blaze/util/Complex.h64
-rw-r--r--src/cpu/blaze/util/Constraints.h85
-rw-r--r--src/cpu/blaze/util/Convert.h654
-rw-r--r--src/cpu/blaze/util/DimensionOf.h101
-rw-r--r--src/cpu/blaze/util/DisableIf.h228
-rw-r--r--src/cpu/blaze/util/EmptyType.h51
-rw-r--r--src/cpu/blaze/util/EnableIf.h228
-rw-r--r--src/cpu/blaze/util/Exception.h383
-rw-r--r--src/cpu/blaze/util/FalseType.h66
-rw-r--r--src/cpu/blaze/util/Indices.h220
-rw-r--r--src/cpu/blaze/util/InputString.h434
-rw-r--r--src/cpu/blaze/util/IntegralConstant.h105
-rw-r--r--src/cpu/blaze/util/InvalidType.h59
-rw-r--r--src/cpu/blaze/util/Limits.h440
-rw-r--r--src/cpu/blaze/util/Logging.h51
-rw-r--r--src/cpu/blaze/util/MPL.h64
-rw-r--r--src/cpu/blaze/util/Memory.h278
-rw-r--r--src/cpu/blaze/util/MemoryPool.h300
-rw-r--r--src/cpu/blaze/util/Misalignment.h76
-rw-r--r--src/cpu/blaze/util/NonCopyable.h86
-rw-r--r--src/cpu/blaze/util/NonCreatable.h81
-rw-r--r--src/cpu/blaze/util/NullType.h60
-rw-r--r--src/cpu/blaze/util/PointerCast.h286
-rw-r--r--src/cpu/blaze/util/Policies.h52
-rw-r--r--src/cpu/blaze/util/PtrIterator.h563
-rw-r--r--src/cpu/blaze/util/PtrVector.h2615
-rw-r--r--src/cpu/blaze/util/Random.h1000
-rw-r--r--src/cpu/blaze/util/Serialization.h45
-rw-r--r--src/cpu/blaze/util/Singleton.h46
-rw-r--r--src/cpu/blaze/util/StaticAssert.h129
-rw-r--r--src/cpu/blaze/util/Suffix.h55
-rw-r--r--src/cpu/blaze/util/SystemClock.h194
-rw-r--r--src/cpu/blaze/util/SystemClockID.h82
-rw-r--r--src/cpu/blaze/util/Template.h80
-rw-r--r--src/cpu/blaze/util/Thread.h498
-rw-r--r--src/cpu/blaze/util/ThreadPool.h801
-rw-r--r--src/cpu/blaze/util/Time.h171
-rw-r--r--src/cpu/blaze/util/Timing.h49
-rw-r--r--src/cpu/blaze/util/TrueType.h66
-rw-r--r--src/cpu/blaze/util/TypeList.h1071
-rw-r--r--src/cpu/blaze/util/TypeTraits.h106
-rw-r--r--src/cpu/blaze/util/Types.h180
-rw-r--r--src/cpu/blaze/util/UnsignedValue.h391
-rw-r--r--src/cpu/blaze/util/Unused.h157
-rw-r--r--src/cpu/blaze/util/Util.h49
-rw-r--r--src/cpu/blaze/util/ValueTraits.h48
-rw-r--r--src/cpu/blaze/util/constraints/Arithmetic.h86
-rw-r--r--src/cpu/blaze/util/constraints/Array.h85
-rw-r--r--src/cpu/blaze/util/constraints/Assignable.h207
-rw-r--r--src/cpu/blaze/util/constraints/BaseOf.h128
-rw-r--r--src/cpu/blaze/util/constraints/Boolean.h85
-rw-r--r--src/cpu/blaze/util/constraints/Builtin.h85
-rw-r--r--src/cpu/blaze/util/constraints/Class.h87
-rw-r--r--src/cpu/blaze/util/constraints/Comparable.h66
-rw-r--r--src/cpu/blaze/util/constraints/Complex.h89
-rw-r--r--src/cpu/blaze/util/constraints/ComplexDouble.h89
-rw-r--r--src/cpu/blaze/util/constraints/ComplexFloat.h89
-rw-r--r--src/cpu/blaze/util/constraints/Const.h85
-rw-r--r--src/cpu/blaze/util/constraints/Constraints.h115
-rw-r--r--src/cpu/blaze/util/constraints/Constructible.h287
-rw-r--r--src/cpu/blaze/util/constraints/Convertible.h85
-rw-r--r--src/cpu/blaze/util/constraints/DerivedFrom.h128
-rw-r--r--src/cpu/blaze/util/constraints/Destructible.h127
-rw-r--r--src/cpu/blaze/util/constraints/Double.h89
-rw-r--r--src/cpu/blaze/util/constraints/Empty.h85
-rw-r--r--src/cpu/blaze/util/constraints/Float.h89
-rw-r--r--src/cpu/blaze/util/constraints/FloatingPoint.h87
-rw-r--r--src/cpu/blaze/util/constraints/Integer.h88
-rw-r--r--src/cpu/blaze/util/constraints/Integral.h85
-rw-r--r--src/cpu/blaze/util/constraints/LongDouble.h89
-rw-r--r--src/cpu/blaze/util/constraints/Numeric.h87
-rw-r--r--src/cpu/blaze/util/constraints/Object.h86
-rw-r--r--src/cpu/blaze/util/constraints/Pod.h85
-rw-r--r--src/cpu/blaze/util/constraints/Pointer.h85
-rw-r--r--src/cpu/blaze/util/constraints/Rank.h85
-rw-r--r--src/cpu/blaze/util/constraints/Reference.h85
-rw-r--r--src/cpu/blaze/util/constraints/SameSize.h85
-rw-r--r--src/cpu/blaze/util/constraints/SameType.h166
-rw-r--r--src/cpu/blaze/util/constraints/Signed.h87
-rw-r--r--src/cpu/blaze/util/constraints/Size.h238
-rw-r--r--src/cpu/blaze/util/constraints/Subscriptable.h85
-rw-r--r--src/cpu/blaze/util/constraints/TypeRestriction.h87
-rw-r--r--src/cpu/blaze/util/constraints/Union.h85
-rw-r--r--src/cpu/blaze/util/constraints/Unsigned.h87
-rw-r--r--src/cpu/blaze/util/constraints/Valid.h85
-rw-r--r--src/cpu/blaze/util/constraints/Vectorizable.h87
-rw-r--r--src/cpu/blaze/util/constraints/Void.h85
-rw-r--r--src/cpu/blaze/util/constraints/Volatile.h85
-rw-r--r--src/cpu/blaze/util/logging/DebugSection.h105
-rw-r--r--src/cpu/blaze/util/logging/DetailSection.h105
-rw-r--r--src/cpu/blaze/util/logging/ErrorSection.h105
-rw-r--r--src/cpu/blaze/util/logging/FunctionTrace.h165
-rw-r--r--src/cpu/blaze/util/logging/InfoSection.h105
-rw-r--r--src/cpu/blaze/util/logging/LogLevel.h91
-rw-r--r--src/cpu/blaze/util/logging/LogSection.h230
-rw-r--r--src/cpu/blaze/util/logging/Logger.h161
-rw-r--r--src/cpu/blaze/util/logging/Logging.h224
-rw-r--r--src/cpu/blaze/util/logging/ProgressSection.h105
-rw-r--r--src/cpu/blaze/util/logging/WarningSection.h105
-rw-r--r--src/cpu/blaze/util/mpl/And.h108
-rw-r--r--src/cpu/blaze/util/mpl/Bool.h76
-rw-r--r--src/cpu/blaze/util/mpl/Char.h76
-rw-r--r--src/cpu/blaze/util/mpl/Equal.h79
-rw-r--r--src/cpu/blaze/util/mpl/Greater.h80
-rw-r--r--src/cpu/blaze/util/mpl/If.h165
-rw-r--r--src/cpu/blaze/util/mpl/Int.h76
-rw-r--r--src/cpu/blaze/util/mpl/Less.h84
-rw-r--r--src/cpu/blaze/util/mpl/Long.h76
-rw-r--r--src/cpu/blaze/util/mpl/MPL.h51
-rw-r--r--src/cpu/blaze/util/mpl/Max.h78
-rw-r--r--src/cpu/blaze/util/mpl/Min.h78
-rw-r--r--src/cpu/blaze/util/mpl/Minus.h80
-rw-r--r--src/cpu/blaze/util/mpl/Modulus.h81
-rw-r--r--src/cpu/blaze/util/mpl/NextMultiple.h93
-rw-r--r--src/cpu/blaze/util/mpl/Not.h76
-rw-r--r--src/cpu/blaze/util/mpl/Or.h108
-rw-r--r--src/cpu/blaze/util/mpl/Plus.h80
-rw-r--r--src/cpu/blaze/util/mpl/SizeT.h78
-rw-r--r--src/cpu/blaze/util/mpl/Times.h80
-rw-r--r--src/cpu/blaze/util/mpl/Xor.h80
-rw-r--r--src/cpu/blaze/util/policies/ArrayDelete.h104
-rw-r--r--src/cpu/blaze/util/policies/ConstantGrowth.h112
-rw-r--r--src/cpu/blaze/util/policies/Deallocate.h105
-rw-r--r--src/cpu/blaze/util/policies/DefaultDelete.h158
-rw-r--r--src/cpu/blaze/util/policies/LinearGrowth.h122
-rw-r--r--src/cpu/blaze/util/policies/NoDelete.h85
-rw-r--r--src/cpu/blaze/util/policies/OptimalGrowth.h101
-rw-r--r--src/cpu/blaze/util/policies/PtrDelete.h104
-rw-r--r--src/cpu/blaze/util/serialization/Archive.h537
-rw-r--r--src/cpu/blaze/util/serialization/Serialization.h51
-rw-r--r--src/cpu/blaze/util/singleton/Dependency.h135
-rw-r--r--src/cpu/blaze/util/singleton/Singleton.h1341
-rw-r--r--src/cpu/blaze/util/threadpool/Task.h67
-rw-r--r--src/cpu/blaze/util/threadpool/TaskQueue.h315
-rw-r--r--src/cpu/blaze/util/threadpool/ThreadPool.h54
-rw-r--r--src/cpu/blaze/util/timing/CpuPolicy.h100
-rw-r--r--src/cpu/blaze/util/timing/CpuTimer.h72
-rw-r--r--src/cpu/blaze/util/timing/Timer.h370
-rw-r--r--src/cpu/blaze/util/timing/Timing.h108
-rw-r--r--src/cpu/blaze/util/timing/WcPolicy.h100
-rw-r--r--src/cpu/blaze/util/timing/WcTimer.h73
-rw-r--r--src/cpu/blaze/util/typetraits/AddCV.h101
-rw-r--r--src/cpu/blaze/util/typetraits/AddConst.h100
-rw-r--r--src/cpu/blaze/util/typetraits/AddPointer.h100
-rw-r--r--src/cpu/blaze/util/typetraits/AddReference.h100
-rw-r--r--src/cpu/blaze/util/typetraits/AddVolatile.h100
-rw-r--r--src/cpu/blaze/util/typetraits/AlignmentOf.h249
-rw-r--r--src/cpu/blaze/util/typetraits/All.h86
-rw-r--r--src/cpu/blaze/util/typetraits/Any.h86
-rw-r--r--src/cpu/blaze/util/typetraits/CommonType.h100
-rw-r--r--src/cpu/blaze/util/typetraits/Decay.h103
-rw-r--r--src/cpu/blaze/util/typetraits/Extent.h127
-rw-r--r--src/cpu/blaze/util/typetraits/GetMemberType.h116
-rw-r--r--src/cpu/blaze/util/typetraits/HasMember.h284
-rw-r--r--src/cpu/blaze/util/typetraits/HasSize.h285
-rw-r--r--src/cpu/blaze/util/typetraits/HaveSameSize.h150
-rw-r--r--src/cpu/blaze/util/typetraits/IsArithmetic.h84
-rw-r--r--src/cpu/blaze/util/typetraits/IsArray.h81
-rw-r--r--src/cpu/blaze/util/typetraits/IsAssignable.h191
-rw-r--r--src/cpu/blaze/util/typetraits/IsBaseOf.h86
-rw-r--r--src/cpu/blaze/util/typetraits/IsBoolean.h121
-rw-r--r--src/cpu/blaze/util/typetraits/IsBuiltin.h81
-rw-r--r--src/cpu/blaze/util/typetraits/IsCharacter.h152
-rw-r--r--src/cpu/blaze/util/typetraits/IsClass.h83
-rw-r--r--src/cpu/blaze/util/typetraits/IsComplex.h122
-rw-r--r--src/cpu/blaze/util/typetraits/IsComplexDouble.h122
-rw-r--r--src/cpu/blaze/util/typetraits/IsComplexFloat.h122
-rw-r--r--src/cpu/blaze/util/typetraits/IsConst.h81
-rw-r--r--src/cpu/blaze/util/typetraits/IsConstructible.h232
-rw-r--r--src/cpu/blaze/util/typetraits/IsConvertible.h93
-rw-r--r--src/cpu/blaze/util/typetraits/IsDestructible.h102
-rw-r--r--src/cpu/blaze/util/typetraits/IsDouble.h121
-rw-r--r--src/cpu/blaze/util/typetraits/IsEmpty.h84
-rw-r--r--src/cpu/blaze/util/typetraits/IsFloat.h121
-rw-r--r--src/cpu/blaze/util/typetraits/IsFloatingPoint.h81
-rw-r--r--src/cpu/blaze/util/typetraits/IsInteger.h166
-rw-r--r--src/cpu/blaze/util/typetraits/IsIntegral.h81
-rw-r--r--src/cpu/blaze/util/typetraits/IsLong.h162
-rw-r--r--src/cpu/blaze/util/typetraits/IsLongDouble.h121
-rw-r--r--src/cpu/blaze/util/typetraits/IsNumeric.h125
-rw-r--r--src/cpu/blaze/util/typetraits/IsObject.h82
-rw-r--r--src/cpu/blaze/util/typetraits/IsPod.h93
-rw-r--r--src/cpu/blaze/util/typetraits/IsPointer.h81
-rw-r--r--src/cpu/blaze/util/typetraits/IsReference.h81
-rw-r--r--src/cpu/blaze/util/typetraits/IsSame.h144
-rw-r--r--src/cpu/blaze/util/typetraits/IsShort.h162
-rw-r--r--src/cpu/blaze/util/typetraits/IsSigned.h83
-rw-r--r--src/cpu/blaze/util/typetraits/IsUnion.h84
-rw-r--r--src/cpu/blaze/util/typetraits/IsUnsigned.h83
-rw-r--r--src/cpu/blaze/util/typetraits/IsValid.h122
-rw-r--r--src/cpu/blaze/util/typetraits/IsVectorizable.h139
-rw-r--r--src/cpu/blaze/util/typetraits/IsVoid.h81
-rw-r--r--src/cpu/blaze/util/typetraits/IsVolatile.h81
-rw-r--r--src/cpu/blaze/util/typetraits/MakeSigned.h104
-rw-r--r--src/cpu/blaze/util/typetraits/MakeUnsigned.h104
-rw-r--r--src/cpu/blaze/util/typetraits/Rank.h98
-rw-r--r--src/cpu/blaze/util/typetraits/RemoveAllExtents.h101
-rw-r--r--src/cpu/blaze/util/typetraits/RemoveCV.h102
-rw-r--r--src/cpu/blaze/util/typetraits/RemoveConst.h101
-rw-r--r--src/cpu/blaze/util/typetraits/RemoveExtent.h100
-rw-r--r--src/cpu/blaze/util/typetraits/RemovePointer.h100
-rw-r--r--src/cpu/blaze/util/typetraits/RemoveReference.h100
-rw-r--r--src/cpu/blaze/util/typetraits/RemoveVolatile.h102
-rw-r--r--src/cpu/blaze/util/typetraits/TypeTraits.h51
-rw-r--r--src/cpu/blaze/util/valuetraits/IsEven.h79
-rw-r--r--src/cpu/blaze/util/valuetraits/IsMultipleOf.h109
-rw-r--r--src/cpu/blaze/util/valuetraits/IsOdd.h79
-rw-r--r--src/cpu/blaze/util/valuetraits/IsPowerOf.h221
-rw-r--r--src/cpu/blaze/util/valuetraits/ValueTraits.h51
-rw-r--r--src/cpu/dl4mt/decoder.h287
-rw-r--r--src/cpu/dl4mt/dl4mt.h5
-rw-r--r--src/cpu/dl4mt/encoder.cpp24
-rw-r--r--src/cpu/dl4mt/encoder.h93
-rw-r--r--src/cpu/dl4mt/gru.h76
-rw-r--r--src/cpu/dl4mt/model.cpp74
-rw-r--r--src/cpu/dl4mt/model.h184
-rw-r--r--src/cpu/mblas/matrix.cpp40
-rw-r--r--src/cpu/mblas/matrix.h269
-rw-r--r--src/cpu/mblas/phoenix_functions.cpp9
-rw-r--r--src/cpu/mblas/phoenix_functions.h107
-rw-r--r--src/cpu/mblas/simd_math_prims.h117
-rw-r--r--src/cpu/npz_converter.h88
1235 files changed, 553444 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 53bd7275..cf5e9684 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5.1)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
project(amunn CXX)
-SET(CMAKE_CXX_FLAGS " -std=c++11 -g -O3 -pthread -funroll-loops -Wno-unused-result -Wno-deprecated")
+SET(CMAKE_CXX_FLAGS " -std=c++14 -g -O3 -pthread -funroll-loops -Wno-unused-result -Wno-deprecated")
LIST(APPEND CUDA_NVCC_FLAGS --default-stream per-thread; -std=c++11; -g; -O3; -arch=sm_35; -lineinfo; --use_fast_math;)
add_definitions(-DCUDA_API_PER_THREAD_DEFAULT_STREAM)
SET(CUDA_PROPAGATE_HOST_FLAGS OFF)
diff --git a/amunmt/.cproject b/amunmt/.cproject
index 40be08c8..21d3d509 100644
--- a/amunmt/.cproject
+++ b/amunmt/.cproject
@@ -67,8 +67,9 @@
</tool>
</toolChain>
</folderInfo>
+ <fileInfo id="com.nvidia.cuda.ide.seven_five.configuration.debug.2085852150.1621792310" name="kenlm.h" rcbsApplicability="disable" resourcePath="gpu/decoder/kenlm.h" toolsToInvoke=""/>
<sourceEntries>
- <entry excluding="decoder/kenlm.h|decoder/kenlm.cpp" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+ <entry excluding="gpu/decoder/kenlm.h|gpu/decoder/kenlm.cpp|decoder/kenlm.h|decoder/kenlm.cpp" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
@@ -153,10 +154,10 @@
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
- <configuration configurationName="Release">
+ <configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/amunmt"/>
</configuration>
- <configuration configurationName="Debug">
+ <configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/amunmt"/>
</configuration>
</storageModule>
diff --git a/amunmt/.project b/amunmt/.project
index 6ce9f5d6..9bcd1175 100644
--- a/amunmt/.project
+++ b/amunmt/.project
@@ -36,6 +36,11 @@
<locationURI>PARENT-1-PROJECT_LOC/src/common</locationURI>
</link>
<link>
+ <name>cpu</name>
+ <type>2</type>
+ <locationURI>PARENT-1-PROJECT_LOC/src/cpu</locationURI>
+ </link>
+ <link>
<name>gpu</name>
<type>2</type>
<locationURI>PARENT-1-PROJECT_LOC/src/gpu</locationURI>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 00f59e77..a3bd342d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,5 +1,6 @@
include_directories(.)
+include_directories(cpu)
add_subdirectory(yaml-cpp)
@@ -37,6 +38,9 @@ cuda_add_executable(
common/sentence.cpp
gpu/mblas/matrix.cu
gpu/dl4mt/gru.cu
+ cpu/mblas/matrix.cpp
+ cpu/mblas/phoenix_functions.cpp
+ cpu/dl4mt/encoder.cpp
$<TARGET_OBJECTS:libamun>
$<TARGET_OBJECTS:libcommon>
$<TARGET_OBJECTS:libyaml-cpp>
diff --git a/src/cpu/blaze/Blaze.h b/src/cpu/blaze/Blaze.h
new file mode 100644
index 00000000..1bd0874e
--- /dev/null
+++ b/src/cpu/blaze/Blaze.h
@@ -0,0 +1,60 @@
+//=================================================================================================
+/*!
+// \file blaze/Blaze.h
+// \brief Primary include file of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_BLAZE_H_
+#define _BLAZE_BLAZE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/Math.h>
+#include <blaze/Util.h>
+
+
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+//! Namespace of the \b Blaze C++ math library.
+namespace blaze {}
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/Math.h b/src/cpu/blaze/Math.h
new file mode 100644
index 00000000..c9135a4f
--- /dev/null
+++ b/src/cpu/blaze/Math.h
@@ -0,0 +1,84 @@
+//=================================================================================================
+/*!
+// \file blaze/math.h
+// \brief Header file for the inclusion of the math module of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_MODULE_H_
+#define _BLAZE_MATH_MODULE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Accuracy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/BLAS.h>
+#include <blaze/math/CompressedMatrix.h>
+#include <blaze/math/CompressedVector.h>
+#include <blaze/math/Constants.h>
+#include <blaze/math/Constraints.h>
+#include <blaze/math/CustomMatrix.h>
+#include <blaze/math/CustomVector.h>
+#include <blaze/math/DiagonalMatrix.h>
+#include <blaze/math/DynamicMatrix.h>
+#include <blaze/math/DynamicVector.h>
+#include <blaze/math/Epsilon.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/Functors.h>
+#include <blaze/math/Infinity.h>
+#include <blaze/math/InversionFlag.h>
+#include <blaze/math/HermitianMatrix.h>
+#include <blaze/math/HybridMatrix.h>
+#include <blaze/math/HybridVector.h>
+#include <blaze/math/LAPACK.h>
+#include <blaze/math/LowerMatrix.h>
+#include <blaze/math/PaddingFlag.h>
+#include <blaze/math/Serialization.h>
+#include <blaze/math/Shims.h>
+#include <blaze/math/SMP.h>
+#include <blaze/math/StaticMatrix.h>
+#include <blaze/math/StaticVector.h>
+#include <blaze/math/StorageOrder.h>
+#include <blaze/math/StrictlyLowerMatrix.h>
+#include <blaze/math/StrictlyUpperMatrix.h>
+#include <blaze/math/SymmetricMatrix.h>
+#include <blaze/math/Traits.h>
+#include <blaze/math/TransposeFlag.h>
+#include <blaze/math/TypeTraits.h>
+#include <blaze/math/UniLowerMatrix.h>
+#include <blaze/math/UniUpperMatrix.h>
+#include <blaze/math/UpperMatrix.h>
+#include <blaze/math/Views.h>
+
+#endif
diff --git a/src/cpu/blaze/Tutorial.h b/src/cpu/blaze/Tutorial.h
new file mode 100644
index 00000000..5590fb7b
--- /dev/null
+++ b/src/cpu/blaze/Tutorial.h
@@ -0,0 +1,10694 @@
+//=================================================================================================
+/*!
+// \file blaze/Tutorial.h
+// \brief Tutorial of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_TUTORIAL_H_
+#define _BLAZE_TUTORIAL_H_
+
+
+//=================================================================================================
+//
+// BLAZE TUTORIAL
+//
+//=================================================================================================
+
+//**Mainpage***************************************************************************************
+/*!\mainpage
+//
+// \image html blaze300x150.jpg
+//
+// This is the API for the \b Blaze high performance C++ math library. It gives a complete
+// overview of the individual features and sublibraries of \b Blaze. To get a first impression
+// on \b Blaze, the short \ref getting_started tutorial is a good place to start. Afterwards,
+// the following long tutorial covers the most important aspects of the \b Blaze math library.
+// The tabs at the top of the page allow a direct access to the individual modules, namespaces,
+// classes, and files of the \b Blaze library.\n\n
+//
+// \section table_of_content Table of Contents
+//
+// <ul>
+// <li> \ref configuration_and_installation </li>
+// <li> \ref getting_started </li>
+// <li> \ref vectors
+// <ul>
+// <li> \ref vector_types </li>
+// <li> \ref vector_operations </li>
+// </ul>
+// </li>
+// <li> \ref matrices
+// <ul>
+// <li> \ref matrix_types </li>
+// <li> \ref matrix_operations </li>
+// </ul>
+// </li>
+// <li> \ref adaptors
+// <ul>
+// <li> \ref adaptors_symmetric_matrices </li>
+// <li> \ref adaptors_hermitian_matrices </li>
+// <li> \ref adaptors_triangular_matrices </li>
+// </ul>
+// </li>
+// <li> \ref views
+// <ul>
+// <li> \ref views_subvectors </li>
+// <li> \ref views_submatrices </li>
+// <li> \ref views_rows </li>
+// <li> \ref views_columns </li>
+// </ul>
+// </li>
+// <li> \ref arithmetic_operations
+// <ul>
+// <li> \ref addition </li>
+// <li> \ref subtraction </li>
+// <li> \ref scalar_multiplication </li>
+// <li> \ref vector_vector_multiplication
+// <ul>
+// <li> \ref componentwise_multiplication </li>
+// <li> \ref inner_product </li>
+// <li> \ref outer_product </li>
+// <li> \ref cross_product </li>
+// </ul>
+// </li>
+// <li> \ref vector_vector_division </li>
+// <li> \ref matrix_vector_multiplication </li>
+// <li> \ref matrix_matrix_multiplication </li>
+// </ul>
+// </li>
+// <li> \ref custom_operations </li>
+// <li> \ref shared_memory_parallelization
+// <ul>
+// <li> \ref openmp_parallelization </li>
+// <li> \ref cpp_threads_parallelization </li>
+// <li> \ref boost_threads_parallelization </li>
+// <li> \ref serial_execution </li>
+// </ul>
+// </li>
+// <li> \ref serialization
+// <ul>
+// <li> \ref vector_serialization </li>
+// <li> \ref matrix_serialization </li>
+// </ul>
+// </li>
+// <li> \ref blas_functions </li>
+// <li> \ref lapack_functions </li>
+// <li> \ref configuration_files </li>
+// <li> \ref custom_data_types </li>
+// <li> \ref error_reporting_customization </li>
+// <li> \ref intra_statement_optimization </li>
+// </ul>
+*/
+//*************************************************************************************************
+
+
+//**Configuration and Installation*****************************************************************
+/*!\page configuration_and_installation Configuration and Installation
+//
+// Since \b Blaze is a header-only library, setting up the \b Blaze library on a particular system
+// is a fairly easy two step process. In the following, this two step process is explained in
+// detail, preceded only by a short summary of the requirements.
+//
+//
+// \n \section requirements Requirements
+// <hr>
+//
+// In order for \b Blaze to work properly, the Boost library must be installed on the system. It
+// is recommended to use the newest Boost library available, but \b Blaze requires at minimum the
+// Boost version 1.54.0. If you don't have Boost installed on your system, you can download it for
+// free from 'http://www.boost.org'.
+//
+// Additionally, for maximum performance \b Blaze expects you to have a BLAS library installed
+// (<a href="http://software.intel.com/en-us/articles/intel-mkl/">Intel MKL</a>,
+// <a href="http://developer.amd.com/libraries/acml/">ACML</a>,
+// <a href="http://math-atlas.sourceforge.net">Atlas</a>,
+// <a href="http://www.tacc.utexas.edu/tacc-projects/gotoblas2">Goto</a>, ...). If you don't
+// have a BLAS library installed on your system, \b Blaze will still work and will not be reduced
+// in functionality, but performance may be limited. Thus it is strongly recommended to install a
+// BLAS library.
+//
+// Furthermore, for computing the determinant of a dense matrix and for the dense matrix inversion
+// \b Blaze requires <a href="https://en.wikipedia.org/wiki/LAPACK">LAPACK</a>. When either of
+// these features is used it is necessary to link the LAPACK library to the final executable. If
+// no LAPACK library is available the use of these features will result in a linker error.
+//
+//
+// \n \section step_1_installation Step 1: Installation
+// <hr>
+//
+// \subsection step_1_installation_unix Linux/MacOSX User
+//
+// The first step is the installation of the header files. Since \b Blaze only consists of header
+// files, the <tt>./blaze</tt> subdirectory can be simply copied to a standard include directory
+// (note that this requires root privileges):
+
+ \code
+ cp -r ./blaze /usr/local/include
+ \endcode
+
+// Alternatively, on Unix-based machines (which includes Linux and Mac OS X) the
+// \c CPLUS_INCLUDE_PATH environment variable can be set. The specified directory will be
+// searched after any directories specified on the command line with the option \c -I and
+// before the standard default directories (such as \c /usr/local/include and \c /usr/include).
+// Assuming a user named 'Jon', the environment variable can be set as follows:
+
+ \code
+ CPLUS_INCLUDE_PATH=/usr/home/jon/blaze
+ export CPLUS_INCLUDE_PATH
+ \endcode
+
+// Last but not least, the <tt>./blaze</tt> subdirectory can be explicitly specified on the
+// command line. The following example demonstrates this by means of the GNU C++ compiler:
+
+ \code
+ g++ -I/usr/home/jon/blaze -o BlazeTest BlazeTest.cpp
+ \endcode
+
+// \n \subsection step_1_installation_windows Windows User
+//
+// Windows doesn't have a standard include directory. Therefore the \b Blaze header files can be
+// copied to any other directory or simply left in the default \b Blaze directory. However, the
+// chosen include directory has to be explicitly specified as include path. In Visual Studio,
+// this is done via the project property pages, configuration properties, C/C++, General settings.
+// Here the additional include directories can be specified.
+//
+//
+// \n \section step_2_configuration Step 2: Configuration
+// <hr>
+//
+// The second step is the configuration and customization of the \b Blaze library. Many aspects of
+// \b Blaze can be adapted to specific requirements, environments and architectures by customizing
+// the header files in the <tt>./blaze/config/</tt> subdirectory. Since the default settings are
+// reasonable for most systems this step can also be skipped. However, in order to achieve maximum
+// performance a customization of at least the following configuration files is required:
+//
+// - <b><tt>./blaze/config/BLAS.h</tt></b>: Via this configuration file \b Blaze can be enabled
+// to use a third-party BLAS library for several basic linear algebra functions (such as for
+// instance dense matrix multiplications). In case no BLAS library is used, all linear algebra
+// functions use the default implementations of the \b Blaze library and therefore BLAS is not a
+// requirement for the compilation process. However, please note that performance may be limited.
+// - <b><tt>./blaze/config/CacheSize.h</tt></b>: This file contains the hardware specific cache
+// settings. \b Blaze uses this information to optimize its cache usage. For maximum performance
+// it is recommended to adapt these setting to a specific target architecture.
+// - <b><tt>./blaze/config/Thresholds.h</tt></b>: This file contains all thresholds for the
+// customization of the \b Blaze compute kernels. In order to tune the kernels for a specific
+// architecture and to maximize performance it can be necessary to adjust the thresholds,
+// especially for a parallel execution (see \ref shared_memory_parallelization).
+//
+// For an overview of other customization options and more details, please see the section
+// \ref configuration_files.
+//
+// \n Next: \ref getting_started
+*/
+//*************************************************************************************************
+
+
+//**Getting Started********************************************************************************
+/*!\page getting_started Getting Started
+//
+// This short tutorial serves the purpose to give a quick overview of the way mathematical
+// expressions have to be formulated in \b Blaze. Starting with \ref vector_types, the following
+// long tutorial covers the most important aspects of the \b Blaze math library.
+//
+//
+// \n \section getting_started_vector_example A First Example
+//
+// \b Blaze is written such that using mathematical expressions is as close to mathematical
+// textbooks as possible and therefore as intuitive as possible. In nearly all cases the seemingly
+// easiest solution is the right solution and most users experience no problems when trying to
+// use \b Blaze in the most natural way. The following example gives a first impression of the
+// formulation of a vector addition in \b Blaze:
+
+ \code
+ #include <iostream>
+ #include <blaze/Math.h>
+
+ using blaze::StaticVector;
+ using blaze::DynamicVector;
+
+ // Instantiation of a static 3D column vector. The vector is directly initialized as
+ // ( 4 -2 5 )
+ StaticVector<int,3UL> a{ 4, -2, 5 };
+
+ // Instantiation of a dynamic 3D column vector. Via the subscript operator the values are set to
+ // ( 2 5 -3 )
+ DynamicVector<int> b( 3UL );
+ b[0] = 2;
+ b[1] = 5;
+ b[2] = -3;
+
+ // Adding the vectors a and b
+ DynamicVector<int> c = a + b;
+
+ // Printing the result of the vector addition
+ std::cout << "c =\n" << c << "\n";
+ \endcode
+
+// Note that the entire \b Blaze math library can be included via the \c blaze/Math.h header
+// file. Alternatively, the entire \b Blaze library, including both the math and the entire
+// utility module, can be included via the \c blaze/Blaze.h header file. Also note that all
+// classes and functions of \b Blaze are contained in the blaze namespace.\n\n
+//
+// Assuming that this program resides in a source file called \c FirstExample.cpp, it can be
+// compiled for instance via the GNU C++ compiler:
+
+ \code
+ g++ -ansi -O3 -DNDEBUG -mavx -o FirstExample FirstExample.cpp
+ \endcode
+
+// Note the definition of the \c NDEBUG preprocessor symbol. In order to achieve maximum
+// performance, it is necessary to compile the program in release mode, which deactivates
+// all debugging functionality inside \b Blaze. It is also strongly recommended to specify
+// the available architecture specific instruction set (as for instance the AVX instruction
+// set, which if available can be activated via the \c -mavx flag). This allows \b Blaze
+// to optimize computations via vectorization.\n\n
+//
+// When running the resulting executable \c FirstExample, the output of the last line of
+// this small program is
+
+ \code
+ c =
+ 6
+ 3
+ 2
+ \endcode
+
+// \n \section getting_started_matrix_example An Example Involving Matrices
+//
+// Similarly easy and intuitive are expressions involving matrices:
+
+ \code
+ #include <blaze/Math.h>
+
+ using namespace blaze;
+
+ // Instantiating a dynamic 3D column vector
+ DynamicVector<int> x{ 4, -1, 3 };
+
+ // Instantiating a dynamic 2x3 row-major matrix, preinitialized with 0. Via the function call
+ // operator three values of the matrix are explicitly set to get the matrix
+ // ( 1 0 4 )
+ // ( 0 -2 0 )
+ DynamicMatrix<int> A( 2UL, 3UL, 0 );
+ A(0,0) = 1;
+ A(0,2) = 4;
+ A(1,1) = -2;
+
+ // Performing a matrix/vector multiplication
+ DynamicVector<int> y = A * x;
+
+ // Printing the resulting vector
+ std::cout << "y =\n" << y << "\n";
+
+ // Instantiating a static column-major matrix. The matrix is directly initialized as
+ // ( 3 -1 )
+ // ( 0 2 )
+ // ( -1 0 )
+ StaticMatrix<int,3UL,2UL,columnMajor> B{ { 3, -1 }, { 0, 2 }, { -1, 0 } };
+
+ // Performing a matrix/matrix multiplication
+ DynamicMatrix<int> C = A * B;
+
+ // Printing the resulting matrix
+ std::cout << "C =\n" << C << "\n";
+ \endcode
+
+// The output of this program is
+
+ \code
+ y =
+ 16
+ 2
+
+ C =
+ ( -1 -1 )
+ ( 0 4 )
+ \endcode
+
+// \n \section getting_started_complex_example A Complex Example
+//
+// The following example is much more sophisticated. It shows the implementation of the Conjugate
+// Gradient (CG) algorithm (http://en.wikipedia.org/wiki/Conjugate_gradient) by means of the
+// \b Blaze library:
+//
+// \image html cg.jpg
+//
+// In this example it is not important to understand the CG algorithm itself, but to see the
+// advantage of the API of the \b Blaze library. In the \b Blaze implementation we will use a
+// sparse matrix/dense vector multiplication for a 2D Poisson equation using \f$ N \times N \f$
+// unknowns. It becomes apparent that the core of the algorithm is very close to the mathematical
+// formulation and therefore has huge advantages in terms of readability and maintainability,
+// while the performance of the code is close to the expected theoretical peak performance:
+
+ \code
+ const size_t NN( N*N );
+
+ blaze::CompressedMatrix<double,rowMajor> A( NN, NN );
+ blaze::DynamicVector<double,columnVector> x( NN, 1.0 ), b( NN, 0.0 ), r( NN ), p( NN ), Ap( NN );
+ double alpha, beta, delta;
+
+ // ... Initializing the sparse matrix A
+
+ // Performing the CG algorithm
+ r = b - A * x;
+ p = r;
+ delta = (r,r);
+
+ for( size_t iteration=0UL; iteration<iterations; ++iteration )
+ {
+ Ap = A * p;
+ alpha = delta / (p,Ap);
+ x += alpha * p;
+ r -= alpha * Ap;
+ beta = (r,r);
+ if( std::sqrt( beta ) < 1E-8 ) break;
+ p = r + ( beta / delta ) * p;
+ delta = beta;
+ }
+ \endcode
+
+// \n Hopefully this short tutorial gives a good first impression of how mathematical expressions
+// are formulated with \b Blaze. The following long tutorial, starting with \ref vector_types,
+// will cover all aspects of the \b Blaze math library, i.e. it will introduce all vector and
+// matrix types, all possible operations on vectors and matrices, and of course all possible
+// mathematical expressions.
+//
+// \n Previous: \ref configuration_and_installation &nbsp; &nbsp; Next: \ref vectors
+*/
+//*************************************************************************************************
+
+
+//**Vectors****************************************************************************************
+/*!\page vectors Vectors
+//
+// \tableofcontents
+//
+//
+// \n \section vectors_general General Concepts
+// <hr>
+//
+// The \b Blaze library currently offers four dense vector types (\ref vector_types_static_vector,
+// \ref vector_types_dynamic_vector, \ref vector_types_hybrid_vector, and \ref vector_types_custom_vector)
+// and one sparse vector type (\ref vector_types_compressed_vector). All vectors can be specified
+// as either column vectors or row vectors:
+
+ \code
+ using blaze::DynamicVector;
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ // Setup of the 3-dimensional dense column vector
+ //
+ // ( 1 )
+ // ( 2 )
+ // ( 3 )
+ //
+ DynamicVector<int,columnVector> a{ 1, 2, 3 };
+
+ // Setup of the 3-dimensional dense row vector
+ //
+ // ( 4 5 6 )
+ //
+ DynamicVector<int,rowVector> b{ 4, 5, 6 };
+ \endcode
+
+// Per default, all vectors in \b Blaze are column vectors:
+
+ \code
+ // Instantiation of a 3-dimensional column vector
+ blaze::DynamicVector<int> c( 3UL );
+ \endcode
+
+// \n \section vectors_details Vector Details
+// <hr>
+//
+// - \ref vector_types
+// - \ref vector_operations
+//
+//
+// \n \section vectors_examples Examples
+// <hr>
+
+ \code
+ using blaze::StaticVector;
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+ using blaze::rowVector;
+ using blaze::columnVector;
+
+ StaticVector<int,6UL> a; // Instantiation of a 6-dimensional static column vector
+ CompressedVector<int,rowVector> b; // Instantiation of a compressed row vector
+ DynamicVector<int,columnVector> c; // Instantiation of a dynamic column vector
+
+ // ... Resizing and initialization
+
+ c = a + trans( b );
+ \endcode
+
+// \n Previous: \ref getting_started &nbsp; &nbsp; Next: \ref vector_types
+*/
+//*************************************************************************************************
+
+
+//**Vector Types***********************************************************************************
+/*!\page vector_types Vector Types
+//
+// \tableofcontents
+//
+//
+// \n \section vector_types_static_vector StaticVector
+// <hr>
+//
+// The blaze::StaticVector class template is the representation of a fixed size vector with
+// statically allocated elements of arbitrary type. It can be included via the header file
+
+ \code
+ #include <blaze/math/StaticVector.h>
+ \endcode
+
+// The type of the elements, the number of elements, and the transpose flag of the vector can
+// be specified via the three template parameters:
+
+ \code
+ template< typename Type, size_t N, bool TF >
+ class StaticVector;
+ \endcode
+
+// - \c Type: specifies the type of the vector elements. StaticVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - \c N : specifies the total number of vector elements. It is expected that StaticVector is
+// only used for tiny and small vectors.
+// - \c TF : specifies whether the vector is a row vector (\c blaze::rowVector) or a column
+// vector (\c blaze::columnVector). The default value is \c blaze::columnVector.
+//
+// The blaze::StaticVector is perfectly suited for small to medium vectors whose size is known at
+// compile time:
+
+ \code
+ // Definition of a 3-dimensional integral column vector
+ blaze::StaticVector<int,3UL> a;
+
+ // Definition of a 4-dimensional single precision column vector
+ blaze::StaticVector<float,4UL,blaze::columnVector> b;
+
+ // Definition of a 6-dimensional double precision row vector
+ blaze::StaticVector<double,6UL,blaze::rowVector> c;
+ \endcode
+
+// \n \section vector_types_dynamic_vector DynamicVector
+// <hr>
+//
+// The blaze::DynamicVector class template is the representation of an arbitrary sized vector
+// with dynamically allocated elements of arbitrary type. It can be included via the header file
+
+ \code
+ #include <blaze/math/DynamicVector.h>
+ \endcode
+
+// The type of the elements and the transpose flag of the vector can be specified via the two
+// template parameters:
+
+ \code
+ template< typename Type, bool TF >
+ class DynamicVector;
+ \endcode
+
+// - \c Type: specifies the type of the vector elements. DynamicVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - \c TF : specifies whether the vector is a row vector (\c blaze::rowVector) or a column
+// vector (\c blaze::columnVector). The default value is \c blaze::columnVector.
+//
+// The blaze::DynamicVector is the default choice for all kinds of dense vectors and the best
+// choice for medium to large vectors. Its size can be modified at runtime:
+
+ \code
+ // Definition of a 3-dimensional integral column vector
+ blaze::DynamicVector<int> a( 3UL );
+
+ // Definition of a 4-dimensional single precision column vector
+ blaze::DynamicVector<float,blaze::columnVector> b( 4UL );
+
+ // Definition of a double precision row vector with size 0
+ blaze::DynamicVector<double,blaze::rowVector> c;
+ \endcode
+
+// \n \section vector_types_hybrid_vector HybridVector
+// <hr>
+//
+// The blaze::HybridVector class template combines the advantages of the blaze::StaticVector and
+// the blaze::DynamicVector class templates. It represents a fixed size vector with statically
+// allocated elements, but still can be dynamically resized (within the bounds of the available
+// memory). It can be included via the header file
+
+ \code
+ #include <blaze/math/HybridVector.h>
+ \endcode
+
+// The type of the elements, the number of elements, and the transpose flag of the vector can
+// be specified via the three template parameters:
+
+ \code
+ template< typename Type, size_t N, bool TF >
+ class HybridVector;
+ \endcode
+
+// - \c Type: specifies the type of the vector elements. HybridVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - \c N : specifies the maximum number of vector elements. It is expected that HybridVector
+// is only used for tiny and small vectors.
+// - \c TF : specifies whether the vector is a row vector (\c blaze::rowVector) or a column
+// vector (\c blaze::columnVector). The default value is \c blaze::columnVector.
+//
+// The blaze::HybridVector is a suitable choice for small to medium vectors, whose size is not
+// known at compile time or not fixed at runtime, but whose maximum size is known at compile
+// time:
+
+ \code
+ // Definition of a 3-dimensional integral column vector with a maximum size of 6
+ blaze::HybridVector<int,6UL> a( 3UL );
+
+ // Definition of a 4-dimensional single precision column vector with a maximum size of 16
+ blaze::HybridVector<float,16UL,blaze::columnVector> b( 4UL );
+
+ // Definition of a double precision row vector with size 0 and a maximum size of 6
+ blaze::HybridVector<double,6UL,blaze::rowVector> c;
+ \endcode
+
+// \n \section vector_types_custom_vector CustomVector
+// <hr>
+//
+// The blaze::CustomVector class template provides the functionality to represent an external
+// array of elements of arbitrary type and a fixed size as a native \b Blaze dense vector data
+// structure. Thus in contrast to all other dense vector types a custom vector does not perform
+// any kind of memory allocation by itself, but it is provided with an existing array of element
+// during construction. A custom vector can therefore be considered an alias to the existing
+// array. It can be included via the header file
+
+ \code
+ #include <blaze/math/CustomVector.h>
+ \endcode
+
+// The type of the elements, the properties of the given array of elements and the transpose
+// flag of the vector can be specified via the following four template parameters:
+
+ \code
+ template< typename Type, bool AF, bool PF, bool TF >
+ class CustomVector;
+ \endcode
+
+// - Type: specifies the type of the vector elements. blaze::CustomVector can be used with
+// any non-cv-qualified, non-reference, non-pointer element type.
+// - AF : specifies whether the represented, external arrays are properly aligned with
+// respect to the available instruction set (SSE, AVX, ...) or not.
+// - PF : specified whether the represented, external arrays are properly padded with
+// respect to the available instruction set (SSE, AVX, ...) or not.
+// - TF : specifies whether the vector is a row vector (\c blaze::rowVector) or a column
+// vector (\c blaze::columnVector). The default value is \c blaze::columnVector.
+//
+// The blaze::CustomVector is the right choice if any external array needs to be represented as
+// a \b Blaze dense vector data structure or if a custom memory allocation strategy needs to be
+// realized:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+
+ // Definition of an unmanaged custom column vector for unaligned, unpadded integer arrays
+ typedef CustomVector<int,unaligned,unpadded,columnVector> UnalignedUnpadded;
+ std::vector<int> vec( 7UL );
+ UnalignedUnpadded a( &vec[0], 7UL );
+
+ // Definition of a managed custom column vector for unaligned but padded 'float' arrays
+ typedef CustomVector<float,unaligned,padded,columnVector> UnalignedPadded;
+ UnalignedPadded b( new float[16], 9UL, 16UL, blaze::ArrayDelete() );
+
+ // Definition of a managed custom row vector for aligned, unpadded 'double' arrays
+ typedef CustomVector<double,aligned,unpadded,rowVector> AlignedUnpadded;
+ AlignedUnpadded c( blaze::allocate<double>( 7UL ), 7UL, blaze::Deallocate() );
+
+ // Definition of a managed custom row vector for aligned, padded 'complex<double>' arrays
+ typedef CustomVector<complex<double>,aligned,padded,columnVector> AlignedPadded;
+ AlignedPadded d( allocate< complex<double> >( 8UL ), 5UL, 8UL, blaze::Deallocate() );
+ \endcode
+
+// In comparison with the remaining \b Blaze dense vector types blaze::CustomVector has several
+// special characteristics. All of these result from the fact that a custom vector is not
+// performing any kind of memory allocation, but instead is given an existing array of elements.
+// The following sections discuss all of these characteristics:
+//
+// -# <b>\ref vector_types_custom_vector_memory_management</b>
+// -# <b>\ref vector_types_custom_vector_copy_operations</b>
+// -# <b>\ref vector_types_custom_vector_alignment</b>
+// -# <b>\ref vector_types_custom_vector_padding</b>
+//
+// \n \subsection vector_types_custom_vector_memory_management Memory Management
+//
+// The blaze::CustomVector class template acts as an adaptor for an existing array of elements. As
+// such it provides everything that is required to use the array just like a native \b Blaze dense
+// vector data structure. However, this flexibility comes with the price that the user of a custom
+// vector is responsible for the resource management.
+//
+// When constructing a custom vector there are two choices: Either a user manually manages the
+// array of elements outside the custom vector, or alternatively passes the responsibility for
+// the memory management to an instance of CustomVector. In the second case the CustomVector
+// class employs shared ownership between all copies of the custom vector, which reference the
+// same array.
+//
+// The following examples give an impression of several possible types of custom vectors:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::ArrayDelete;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ // Definition of a 3-dimensional custom vector with unaligned, unpadded and externally
+ // managed integer array. Note that the std::vector must be guaranteed to outlive the
+ // custom vector!
+ std::vector<int> vec( 3UL );
+ CustomVector<int,unaligned,unpadded> a( &vec[0], 3UL );
+
+ // Definition of a custom row vector with size 3 for unaligned, unpadded integer arrays.
+ // The responsibility for the memory management is passed to the custom vector by
+ // providing a deleter of type 'blaze::ArrayDelete' that is used during the destruction
+ // of the custom vector.
+ CustomVector<int,unaligned,unpadded,rowVector> b( new int[3], 3UL, ArrayDelete() );
+
+ // Definition of a custom vector with size 3 and capacity 16 with aligned and padded
+ // integer array. The memory management is passed to the custom vector by providing a
+ // deleter of type 'blaze::Deallocate'.
+ CustomVector<int,aligned,padded> c( allocate<int>( 16UL ), 3UL, 16UL, Deallocate() );
+ \endcode
+
+// It is possible to pass any type of deleter to the constructor. The deleter is only required
+// to provide a function call operator that can be passed the pointer to the managed array. As
+// an example the following code snipped shows the implementation of two native \b Blaze deleters
+// blaze::ArrayDelete and blaze::Deallocate:
+
+ \code
+ namespace blaze {
+
+ struct ArrayDelete
+ {
+ template< typename Type >
+ inline void operator()( Type ptr ) const { boost::checked_array_delete( ptr ); }
+ };
+
+ struct Deallocate
+ {
+ template< typename Type >
+ inline void operator()( Type ptr ) const { deallocate( ptr ); }
+ };
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection vector_types_custom_vector_copy_operations Copy Operations
+//
+// As with all dense vectors it is possible to copy construct a custom vector:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::unaligned;
+ using blaze::unpadded;
+
+ typedef CustomVector<int,unaligned,unpadded> CustomType;
+
+ std::vector<int> vec( 5UL, 10 ); // Vector of 5 integers of the value 10
+ CustomType a( &vec[0], 5UL ); // Represent the std::vector as Blaze dense vector
+ a[1] = 20; // Also modifies the std::vector
+
+ CustomType b( a ); // Creating a copy of vector a
+ b[2] = 20; // Also affect vector a and the std::vector
+ \endcode
+
+// It is important to note that a custom vector acts as a reference to the specified array. Thus
+// the result of the copy constructor is a new custom vector that is referencing and representing
+// the same array as the original custom vector. In case a deleter has been provided to the first
+// custom vector, both vectors share the responsibility to destroy the array when the last vector
+// goes out of scope.
+//
+// In contrast to copy construction, just as with references, copy assignment does not change
+// which array is referenced by the custom vector, but modifies the values of the array:
+
+ \code
+ std::vector<int> vec2( 5UL, 4 ); // Vector of 5 integers of the value 4
+ CustomType c( &vec2[0], 5UL ); // Represent the std::vector as Blaze dense vector
+
+ a = c; // Copy assignment: Set all values of vector a and b to 4.
+ \endcode
+
+// \n \subsection vector_types_custom_vector_alignment Alignment
+//
+// In case the custom vector is specified as \c aligned the passed array must be guaranteed to
+// be aligned according to the requirements of the used instruction set (SSE, AVX, ...). For
+// instance, if AVX is active an array of integers must be 32-bit aligned:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::Deallocate;
+ using blaze::aligned;
+ using blaze::unpadded;
+
+ int* array = blaze::allocate<int>( 5UL ); // Needs to be 32-bit aligned
+ CustomVector<int,aligned,unpadded> a( array, 5UL, Deallocate() );
+ \endcode
+
+// In case the alignment requirements are violated, a \c std::invalid_argument exception is
+// thrown.
+//
+// \n \subsection vector_types_custom_vector_padding Padding
+//
+// Adding padding elements to the end of an array can have a significant impact on the performance.
+// For instance, assuming that AVX is available, then two aligned, padded, 3-dimensional vectors
+// of double precision values can be added via a single SIMD addition operation:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::padded;
+
+ typedef CustomVector<double,aligned,padded> CustomType;
+
+ // Creating padded custom vectors of size 3 and a capacity of 4
+ CustomType a( allocate<double>( 4UL ), 3UL, 4UL, Deallocate() );
+ CustomType b( allocate<double>( 4UL ), 3UL, 4UL, Deallocate() );
+ CustomType c( allocate<double>( 4UL ), 3UL, 4UL, Deallocate() );
+
+ // ... Initialization
+
+ c = a + b; // AVX-based vector addition
+ \endcode
+
+// In this example, maximum performance is possible. However, in case no padding elements are
+// inserted, a scalar addition has to be used:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unpadded;
+
+ typedef CustomVector<double,aligned,unpadded> CustomType;
+
+ // Creating unpadded custom vector of size 3
+ CustomType a( allocate<double>( 3UL ), 3UL, Deallocate() );
+ CustomType b( allocate<double>( 3UL ), 3UL, Deallocate() );
+ CustomType c( allocate<double>( 3UL ), 3UL, Deallocate() );
+
+ // ... Initialization
+
+ c = a + b; // Scalar vector addition
+ \endcode
+
+// Note the different number of constructor parameters for unpadded and padded custom vectors:
+// In contrast to unpadded vectors, where during the construction only the size of the array
+// has to be specified, during the construction of a padded custom vector it is additionally
+// necessary to explicitly specify the capacity of the array.
+//
+// The number of padding elements is required to be sufficient with respect to the available
+// instruction set: In case of an aligned padded custom vector the added padding elements must
+// guarantee that the capacity is a multiple of the SIMD vector width. In case of unaligned
+// padded vectors \f$ N-1 \f$ additional padding elements are required, where \f$ N \f$ is
+// the SIMD vector width. In case the padding is insufficient with respect to the available
+// instruction set, a \c std::invalid_argument exception is thrown.
+//
+// Please also note that \b Blaze will zero initialize the padding elements in order to achieve
+// maximum performance!
+//
+//
+// \n \section vector_types_compressed_vector CompressedVector
+// <hr>
+//
+// The blaze::CompressedVector class is the representation of an arbitrarily sized sparse
+// vector, which stores only non-zero elements of arbitrary type. It can be included via the
+// header file
+
+ \code
+ #include <blaze/math/CompressedVector.h>
+ \endcode
+
+// The type of the elements and the transpose flag of the vector can be specified via the two
+// template parameters:
+
+ \code
+ template< typename Type, bool TF >
+ class CompressedVector;
+ \endcode
+
+// - \c Type: specifies the type of the vector elements. CompressedVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - \c TF : specifies whether the vector is a row vector (\c blaze::rowVector) or a column
+// vector (\c blaze::columnVector). The default value is \c blaze::columnVector.
+//
+// The blaze::CompressedVector is the right choice for all kinds of sparse vectors:
+
+ \code
+ // Definition of a 3-dimensional integral column vector
+ blaze::CompressedVector<int> a( 3UL );
+
+ // Definition of a 4-dimensional single precision column vector with capacity for 3 non-zero elements
+ blaze::CompressedVector<float,blaze::columnVector> b( 4UL, 3UL );
+
+ // Definition of a double precision row vector with size 0
+ blaze::CompressedVector<double,blaze::rowVector> c;
+ \endcode
+
+// \n Previous: \ref vectors &nbsp; &nbsp; Next: \ref vector_operations
+*/
+//*************************************************************************************************
+
+
+//**Vector Operations******************************************************************************
+/*!\page vector_operations Vector Operations
+//
+// \tableofcontents
+//
+//
+// \n \section vector_operations_constructors Constructors
+// <hr>
+//
+// Instantiating and setting up a vector is very easy and intuitive. However, there are a few
+// rules to take care of:
+// - In case the last template parameter (the transpose flag) is omitted, the vector is per
+// default a column vector.
+// - The elements of a \c StaticVector or \c HybridVector are default initialized (i.e. built-in
+// data types are initialized to 0, class types are initialized via the default constructor).
+// - Newly allocated elements of a \c DynamicVector or \c CompressedVector remain uninitialized
+// if they are of built-in type and are default constructed if they are of class type.
+//
+// \n \subsection vector_operations_default_construction Default Construction
+
+ \code
+ using blaze::StaticVector;
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+
+ // All vectors can be default constructed. Whereas the size
+ // of StaticVectors is fixed via the second template parameter,
+ // the initial size of a default constructed DynamicVector or
+ // CompressedVector is 0.
+ StaticVector<int,2UL> v1; // Instantiation of a 2D integer column vector.
+ // All elements are initialized to 0.
+ StaticVector<long,3UL,columnVector> v2; // Instantiation of a 3D long integer column vector.
+ // Again, all elements are initialized to 0L.
+ DynamicVector<float> v3; // Instantiation of a dynamic single precision column
+ // vector of size 0.
+ DynamicVector<double,rowVector> v4; // Instantiation of a dynamic double precision row
+ // vector of size 0.
+ CompressedVector<int> v5; // Instantiation of a compressed integer column
+ // vector of size 0.
+ CompressedVector<double,rowVector> v6; // Instantiation of a compressed double precision row
+ // vector of size 0.
+ \endcode
+
+// \n \subsection vector_operations_size_construction Construction with Specific Size
+//
+// The \c DynamicVector, \c HybridVector and \c CompressedVector classes offer a constructor that
+// allows to immediately give the vector the required size. Whereas both dense vectors (i.e.
+// \c DynamicVector and \c HybridVector) use this information to allocate memory for all vector
+// elements, \c CompressedVector merely acquires the size but remains empty.
+
+ \code
+ DynamicVector<int,columnVector> v7( 9UL ); // Instantiation of an integer dynamic column vector
+ // of size 9. The elements are NOT initialized!
+ HybridVector< complex<float>, 5UL > v8( 2UL ); // Instantiation of a column vector with two single
+ // precision complex values. The elements are
+ // default constructed.
+ CompressedVector<int,rowVector> v9( 10UL ); // Instantiation of a compressed row vector with
+ // size 10. Initially, the vector provides no
+ // capacity for non-zero elements.
+ \endcode
+
+// \n \subsection vector_operations_initialization_constructors Initialization Constructors
+//
+// All dense vector classes offer a constructor that allows for a direct, homogeneous initialization
+// of all vector elements. In contrast, for sparse vectors the predicted number of non-zero elements
+// can be specified
+
+ \code
+ StaticVector<int,3UL,rowVector> v10( 2 ); // Instantiation of a 3D integer row vector.
+ // All elements are initialized to 2.
+ DynamicVector<float> v11( 3UL, 7.0F ); // Instantiation of a dynamic single precision
+ // column vector of size 3. All elements are
+ // set to 7.0F.
+ CompressedVector<float,rowVector> v12( 15UL, 3UL ); // Instantiation of a single precision column
+ // vector of size 15, which provides enough
+ // space for at least 3 non-zero elements.
+ \endcode
+
+// \n \subsection vector_operations_array_construction Array Construction
+//
+// Alternatively, all dense vector classes offer a constructor for an initialization with a dynamic
+// or static array. If the vector is initialized from a dynamic array, the constructor expects the
+// actual size of the array as first argument, the array as second argument. In case of a static
+// array, the fixed size of the array is used:
+
+ \code
+ const unique_ptr<double[]> array1( new double[2] );
+ // ... Initialization of the dynamic array
+ blaze::StaticVector<double,2UL> v13( 2UL, array1.get() );
+
+ int array2[4] = { 4, -5, -6, 7 };
+ blaze::StaticVector<int,4UL> v14( array2 );
+ \endcode
+
+// \n \subsection vector_operations_initializer_list_construction Initializer List Construction
+//
+// In addition, all dense vector classes can be directly initialized by means of an initializer
+// list:
+
+ \code
+ blaze::DynamicVector<float> v15{ 1.0F, 2.0F, 3.0F, 4.0F };
+ \endcode
+
+// \n \subsection vector_operations_copy_construction Copy Construction
+//
+// All dense and sparse vectors can be created as the copy of any other dense or sparse vector
+// with the same transpose flag (i.e. blaze::rowVector or blaze::columnVector).
+
+ \code
+ StaticVector<int,9UL,columnVector> v16( v7 ); // Instantiation of the dense column vector v16
+ // as copy of the dense column vector v7.
+ DynamicVector<int,rowVector> v17( v9 ); // Instantiation of the dense row vector v17 as
+ // copy of the sparse row vector v9.
+ CompressedVector<int,columnVector> v18( v1 ); // Instantiation of the sparse column vector v18
+ // as copy of the dense column vector v1.
+ CompressedVector<float,rowVector> v19( v12 ); // Instantiation of the sparse row vector v19 as
+ // copy of the row vector v12.
+ \endcode
+
+// Note that it is not possible to create a \c StaticVector as a copy of a vector with a different
+// size:
+
+ \code
+ StaticVector<int,5UL,columnVector> v23( v7 ); // Runtime error: Size does not match!
+ StaticVector<int,4UL,rowVector> v24( v10 ); // Compile time error: Size does not match!
+ \endcode
+
+// \n \section vector_operations_assignment Assignment
+// <hr>
+//
+// There are several types of assignment to dense and sparse vectors:
+// \ref vector_operations_homogeneous_assignment, \ref vector_operations_array_assignment,
+// \ref vector_operations_copy_assignment, and \ref vector_operations_compound_assignment.
+//
+// \n \subsection vector_operations_homogeneous_assignment Homogeneous Assignment
+//
+// Sometimes it may be necessary to assign the same value to all elements of a dense vector.
+// For this purpose, the assignment operator can be used:
+
+ \code
+ blaze::StaticVector<int,3UL> v1;
+ blaze::DynamicVector<double> v2;
+
+ // Setting all integer elements of the StaticVector to 2
+ v1 = 2;
+
+ // Setting all double precision elements of the DynamicVector to 5.0
+ v2 = 5.0;
+ \endcode
+
+// \n \subsection vector_operations_array_assignment Array Assignment
+//
+// Dense vectors can also be assigned a static array:
+
+ \code
+ blaze::StaticVector<float,2UL> v1;
+ blaze::DynamicVector<double,rowVector> v2;
+
+ float array1[2] = { 1.0F, 2.0F };
+ double array2[5] = { 2.1, 4.0, -1.7, 8.6, -7.2 };
+
+ v1 = array1;
+ v2 = array2;
+ \endcode
+
+// \n \subsection vector_operations_initializer_list_assignment Initializer List Assignment
+//
+// Alternatively, it is possible to directly assign an initializer list to a dense vector:
+
+ \code
+ blaze::StaticVector<float,2UL> v1;
+ blaze::DynamicVector<double,rowVector> v2;
+
+ v1 = { 1.0F, 2.0F };
+ v2 = { 2.1, 4.0, -1.7, 8.6, -7.2 };
+ \endcode
+
+// \n \subsection vector_operations_copy_assignment Copy Assignment
+//
+// For all vector types it is generally possible to assign another vector with the same transpose
+// flag (i.e. blaze::columnVector or blaze::rowVector). Note that in case of \c StaticVectors, the
+// assigned vector is required to have the same size as the \c StaticVector since the size of a
+// \c StaticVector cannot be adapted!
+
+ \code
+ blaze::StaticVector<int,3UL,columnVector> v1;
+ blaze::DynamicVector<int,columnVector> v2( 3UL );
+ blaze::DynamicVector<float,columnVector> v3( 5UL );
+ blaze::CompressedVector<int,columnVector> v4( 3UL );
+ blaze::CompressedVector<float,rowVector> v5( 3UL );
+
+ // ... Initialization of the vectors
+
+ v1 = v2; // OK: Assignment of a 3D dense column vector to another 3D dense column vector
+ v1 = v4; // OK: Assignment of a 3D sparse column vector to a 3D dense column vector
+ v1 = v3; // Runtime error: Cannot assign a 5D vector to a 3D static vector
+ v1 = v5; // Compilation error: Cannot assign a row vector to a column vector
+ \endcode
+
+// \n \subsection vector_operations_compound_assignment Compound Assignment
+//
+// Next to plain assignment, it is also possible to use addition assignment, subtraction
+// assignment, and multiplication assignment. Note however, that in contrast to plain assignment
+// the size and the transpose flag of the vectors has be to equal in order to able to perform a
+// compound assignment.
+
+ \code
+ blaze::StaticVector<int,5UL,columnVector> v1;
+ blaze::DynamicVector<int,columnVector> v2( 5UL );
+ blaze::CompressedVector<float,columnVector> v3( 7UL );
+ blaze::DynamicVector<float,rowVector> v4( 7UL );
+ blaze::CompressedVector<float,rowVector> v5( 7UL );
+
+ // ... Initialization of the vectors
+
+ v1 += v2; // OK: Addition assignment between two column vectors of the same size
+ v1 += v3; // Runtime error: No compound assignment between vectors of different size
+ v1 -= v4; // Compilation error: No compound assignment between vectors of different transpose flag
+ v4 *= v5; // OK: Multiplication assignment between two row vectors of the same size
+ \endcode
+
+// \n \section vector_operations_element_access Element Access
+// <hr>
+//
+// The easiest and most intuitive way to access a dense or sparse vector is via the subscript
+// operator. The indices to access a vector are zero-based:
+
+ \code
+ blaze::DynamicVector<int> v1( 5UL );
+ v1[0] = 1;
+ v1[1] = 3;
+ // ...
+
+ blaze::CompressedVector<float> v2( 5UL );
+ v2[2] = 7.3F;
+ v2[4] = -1.4F;
+ \endcode
+
+// Whereas using the subscript operator on a dense vector only accesses the already existing
+// element, accessing an element of a sparse vector via the subscript operator potentially
+// inserts the element into the vector and may therefore be more expensive. Consider the
+// following example:
+
+ \code
+ blaze::CompressedVector<int> v1( 10UL );
+
+ for( size_t i=0UL; i<v1.size(); ++i ) {
+ ... = v1[i];
+ }
+ \endcode
+
+// Although the compressed vector is only used for read access within the for loop, using the
+// subscript operator temporarily inserts 10 non-zero elements into the vector. Therefore, all
+// vectors (sparse as well as dense) offer an alternate way via the \c begin(), \c cbegin(),
+// \c end(), and \c cend() functions to traverse the currently contained elements by iterators.
+// In case of non-const vectors, \c begin() and \c end() return an \c Iterator, which allows a
+// manipulation of the non-zero value, in case of a constant vector or in case \c cbegin() or
+// \c cend() are used a \c ConstIterator is returned:
+
+ \code
+ using blaze::CompressedVector;
+
+ CompressedVector<int> v1( 10UL );
+
+ // ... Initialization of the vector
+
+ // Traversing the vector by Iterator
+ for( CompressedVector<int>::Iterator it=v1.begin(); it!=v1.end(); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the non-zero element.
+ }
+
+ // Traversing the vector by ConstIterator
+ for( CompressedVector<int>::ConstIterator it=v1.cbegin(); it!=v1.cend(); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the non-zero element.
+ }
+ \endcode
+
+// Note that \c begin(), \c cbegin(), \c end(), and \c cend() are also available as free functions:
+
+ \code
+ for( CompressedVector<int>::Iterator it=begin( v1 ); it!=end( v1 ); ++it ) {
+ // ...
+ }
+
+ for( CompressedVector<int>::ConstIterator it=cbegin( v1 ); it!=cend( v1 ); ++it ) {
+ // ...
+ }
+ \endcode
+
+// \n \section vector_operations_element_insertion Element Insertion
+// <hr>
+//
+// In contrast to dense vectors, that store all elements independent of their value and that
+// offer direct access to all elements, spares vectors only store the non-zero elements contained
+// in the vector. Therefore it is necessary to explicitly add elements to the vector. The first
+// option to add elements to a sparse vector is the subscript operator:
+
+ \code
+ using blaze::CompressedVector;
+
+ CompressedVector<int> v1( 3UL );
+ v1[1] = 2;
+ \endcode
+
+// In case the element at the given index is not yet contained in the vector, it is automatically
+// inserted. Otherwise the old value is replaced by the new value 2. The operator returns a
+// reference to the sparse vector element.\n
+// An alternative is the \c set() function: In case the element is not yet contained in the vector
+// the element is inserted, else the element's value is modified:
+
+ \code
+ // Insert or modify the value at index 3
+ v1.set( 3, 1 );
+ \endcode
+
+// However, insertion of elements can be better controlled via the \c insert() function. In contrast
+// to the subscript operator and the \c set() function it emits an exception in case the element is
+// already contained in the vector. In order to check for this case, the \c find() function can be
+// used:
+
+ \code
+ // In case the element at index 4 is not yet contained in the matrix it is inserted
+ // with a value of 6.
+ if( v1.find( 4 ) == v1.end() )
+ v1.insert( 4, 6 );
+ \endcode
+
+// Although the \c insert() function is very flexible, due to performance reasons it is not suited
+// for the setup of large sparse vectors. A very efficient, yet also very low-level way to fill
+// a sparse vector is the \c append() function. It requires the sparse vector to provide enough
+// capacity to insert a new element. Additionally, the index of the new element must be larger
+// than the index of the previous element. Violating these conditions results in undefined
+// behavior!
+
+ \code
+ v1.reserve( 10 ); // Reserving space for 10 non-zero elements
+ v1.append( 5, -2 ); // Appending the element -2 at index 5
+ v1.append( 6, 4 ); // Appending the element 4 at index 6
+ // ...
+ \endcode
+
+// \n \section vector_operations_member_functions Member Functions
+// <hr>
+//
+// \subsection vector_operations_size .size()
+//
+// Via the \c size() member function, the current size of a dense or sparse vector can be queried:
+
+ \code
+ // Instantiating a dynamic vector with size 10
+ blaze::DynamicVector<int> v1( 10UL );
+ v1.size(); // Returns 10
+
+ // Instantiating a compressed vector with size 12 and capacity for 3 non-zero elements
+ blaze::CompressedVector<double> v2( 12UL, 3UL );
+ v2.size(); // Returns 12
+ \endcode
+
+// Alternatively, the free function \c size() can be used to query to current size of a vector.
+// In contrast to the member function, the free function can also be used to query the size of
+// vector expressions:
+
+ \code
+ size( v1 ); // Returns 10, i.e. has the same effect as the member function
+ size( v2 ); // Returns 12, i.e. has the same effect as the member function
+
+ blaze::DynamicMatrix<int> A( 15UL, 12UL );
+ size( A * v2 ); // Returns 15, i.e. the size of the resulting vector
+ \endcode
+
+// \n \subsection vector_operations_capacity .capacity()
+//
+// Via the \c capacity() (member) function the internal capacity of a dense or sparse vector
+// can be queried. Note that the capacity of a vector doesn't have to be equal to the size
+// of a vector. In case of a dense vector the capacity will always be greater or equal than
+// the size of the vector, in case of a sparse vector the capacity may even be less than
+// the size.
+
+ \code
+ v1.capacity(); // Returns at least 10
+ \endcode
+
+// For symmetry reasons, there is also a free function /c capacity() available that can be used
+// to query the capacity:
+
+ \code
+ capacity( v1 ); // Returns at least 10, i.e. has the same effect as the member function
+ \endcode
+
+// Note, however, that it is not possible to query the capacity of a vector expression:
+
+ \code
+ capacity( A * v1 ); // Compilation error!
+ \endcode
+
+// \n \subsection vector_operations_nonzeros .nonZeros()
+//
+// For both dense and sparse vectors the number of non-zero elements can be determined via the
+// \c nonZeros() member function. Sparse vectors directly return their number of non-zero
+// elements, dense vectors traverse their elements and count the number of non-zero elements.
+
+ \code
+ v1.nonZeros(); // Returns the number of non-zero elements in the dense vector
+ v2.nonZeros(); // Returns the number of non-zero elements in the sparse vector
+ \endcode
+
+// There is also a free function \c nonZeros() available to query the current number of non-zero
+// elements:
+
+ \code
+ nonZeros( v1 ); // Returns the number of non-zero elements in the dense vector
+ nonZeros( v2 ); // Returns the number of non-zero elements in the sparse vector
+ \endcode
+
+// The free \c nonZeros() function can also be used to query the number of non-zero elements in
+// a vector expression. However, the result is not the exact number of non-zero elements, but
+// may be a rough estimation:
+
+ \code
+ nonZeros( A * v1 ); // Estimates the number of non-zero elements in the vector expression
+ \endcode
+
+// \n \subsection vector_operations_resize_reserve .resize() / .reserve()
+//
+// The size of a \c StaticVector is fixed by the second template parameter and a \c CustomVector
+// cannot be resized. In contrast, the size of \c DynamicVectors, \c HybridVectors as well as
+// \c CompressedVectors can be changed via the \c resize() function:
+
+ \code
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+
+ DynamicVector<int,columnVector> v1;
+ CompressedVector<int,rowVector> v2( 4 );
+ v2[1] = -2;
+ v2[3] = 11;
+
+ // Adapting the size of the dynamic and compressed vectors. The (optional) second parameter
+ // specifies whether the existing elements should be preserved. Per default, the existing
+ // elements are not preserved.
+ v1.resize( 5UL ); // Resizing vector v1 to 5 elements. Elements of built-in type remain
+ // uninitialized, elements of class type are default constructed.
+ v1.resize( 3UL, false ); // Resizing vector v1 to 3 elements. The old elements are lost, the
+ // new elements are NOT initialized!
+ v2.resize( 8UL, true ); // Resizing vector v2 to 8 elements. The old elements are preserved.
+ v2.resize( 5UL, false ); // Resizing vector v2 to 5 elements. The old elements are lost.
+ \endcode
+
+// Note that resizing a vector invalidates all existing views (see e.g. \ref views_subvectors)
+// on the vector:
+
+ \code
+ typedef blaze::DynamicVector<int,rowVector> VectorType;
+ typedef blaze::Subvector<VectorType> SubvectorType;
+
+ VectorType v1( 10UL ); // Creating a dynamic vector of size 10
+ SubvectorType sv = subvector( v1, 2UL, 5UL ); // Creating a view on the range [2..6]
+ v1.resize( 6UL ); // Resizing the vector invalidates the view
+ \endcode
+
+// When the internal capacity of a vector is no longer sufficient, the allocation of a larger
+// junk of memory is triggered. In order to avoid frequent reallocations, the \c reserve()
+// function can be used up front to set the internal capacity:
+
+ \code
+ blaze::DynamicVector<int> v1;
+ v1.reserve( 100 );
+ v1.size(); // Returns 0
+ v1.capacity(); // Returns at least 100
+ \endcode
+
+// Note that the size of the vector remains unchanged, but only the internal capacity is set
+// according to the specified value!
+//
+//
+// \n \section vector_operations_free_functions Free Functions
+// <hr>
+//
+// \subsection vector_operations_reset_clear reset() / clear()
+//
+// In order to reset all elements of a vector, the \c reset() function can be used:
+
+ \code
+ // Setup of a single precision column vector, whose elements are initialized with 2.0F.
+ blaze::DynamicVector<float> v1( 3UL, 2.0F );
+
+ // Resetting all elements to 0.0F. Only the elements are reset, the size of the vector is unchanged.
+ reset( v1 ); // Resetting all elements
+ v1.size(); // Returns 3: size and capacity remain unchanged
+ \endcode
+
+// In order to return a vector to its default state (i.e. the state of a default constructed
+// vector), the \c clear() function can be used:
+
+ \code
+ // Setup of a single precision column vector, whose elements are initialized with -1.0F.
+ blaze::DynamicVector<float> v1( 5, -1.0F );
+
+ // Resetting the entire vector.
+ clear( v1 ); // Resetting the entire vector
+ v1.size(); // Returns 0: size is reset, but capacity remains unchanged
+ \endcode
+
+// Note that resetting or clearing both dense and sparse vectors does not change the capacity
+// of the vectors.
+//
+//
+// \n \subsection vector_operations_isnan isnan()
+//
+// The \c isnan() function provides the means to check a dense or sparse vector for non-a-number
+// elements:
+
+ \code
+ blaze::DynamicVector<double> a;
+ // ... Resizing and initialization
+ if( isnan( a ) ) { ... }
+ \endcode
+
+ \code
+ blaze::CompressedVector<double> a;
+ // ... Resizing and initialization
+ if( isnan( a ) ) { ... }
+ \endcode
+
+// If at least one element of the vector is not-a-number, the function returns \c true, otherwise
+// it returns \c false. Please note that this function only works for vectors with floating point
+// elements. The attempt to use it for a vector with a non-floating point element type results in
+// a compile time error.
+//
+//
+// \n \subsection vector_operations_isdefault isDefault()
+//
+// The \c isDefault() function returns whether the given dense or sparse vector is in default state:
+
+ \code
+ blaze::HybridVector<int,20UL> a;
+ // ... Resizing and initialization
+ if( isDefault( a ) ) { ... }
+ \endcode
+
+// A vector is in default state if it appears to just have been default constructed. All resizable
+// vectors (\c HybridVector, \c DynamicVector, or \c CompressedVector) and \c CustomVector are
+// in default state if its size is equal to zero. A non-resizable vector (\c StaticVector, all
+// subvectors, rows, and columns) is in default state if all its elements are in default state.
+// For instance, in case the vector is instantiated for a built-in integral or floating point data
+// type, the function returns \c true in case all vector elements are 0 and \c false in case any
+// vector element is not 0.
+//
+//
+// \n \subsection vector_operations_isUniform isUniform()
+//
+// In order to check if all vector elements are identical, the \c isUniform function can be used:
+
+ \code
+ blaze::DynamicVector<int> a;
+ // ... Resizing and initialization
+ if( isUniform( a ) ) { ... }
+ \endcode
+
+// Note that in case of sparse vectors also the zero elements are also taken into account!
+//
+//
+// \n \subsection vector_operations_min_max min() / max()
+//
+// The \c min() and the \c max() functions return the smallest and largest element of the given
+// dense or sparse vector, respectively:
+
+ \code
+ blaze::StaticVector<int,4UL,rowVector> a{ -5, 2, 7, 4 };
+ blaze::StaticVector<int,4UL,rowVector> b{ -5, 2, -7, -4 };
+
+ min( a ); // Returns -5
+ min( b ); // Returns -7
+
+ max( a ); // Returns 7
+ max( b ); // Returns 2
+ \endcode
+
+// In case the vector currently has a size of 0, both functions return 0. Additionally, in case
+// a given sparse vector is not completely filled, the zero elements are taken into account. For
+// example: the following compressed vector has only 2 non-zero elements. However, the minimum
+// of this vector is 0:
+
+ \code
+ blaze::CompressedVector<int> c( 4UL, 2UL );
+ c[0] = 1;
+ c[2] = 3;
+
+ min( c ); // Returns 0
+ \endcode
+
+// Also note that the \c min() and \c max() functions can be used to compute the smallest and
+// largest element of a vector expression:
+
+ \code
+ min( a + b + c ); // Returns -9, i.e. the smallest value of the resulting vector
+ max( a - b - c ); // Returns 11, i.e. the largest value of the resulting vector
+ \endcode
+
+// \n \subsection vector_operators_abs abs()
+//
+// The \c abs() function can be used to compute the absolute values of each element of a vector.
+// For instance, the following computation
+
+ \code
+ blaze::StaticVector<int,3UL,rowVector> a{ -1, 2, -3 };
+ blaze::StaticVector<int,3UL,rowVector> b( abs( a ) );
+ \endcode
+
+// results in the vector
+
+ \f$ b = \left(\begin{array}{*{1}{c}}
+ 1 \\
+ 2 \\
+ 3 \\
+ \end{array}\right)\f$
+
+// \n \subsection vector_operators_floor_ceil floor() / ceil()
+//
+// The \c floor() and \c ceil() functions can be used to round down/up each element of a vector,
+// respectively:
+
+ \code
+ blaze::StaticVector<double,3UL,rowVector> a, b;
+
+ b = floor( a ); // Rounding down each element of the vector
+ b = ceil( a ); // Rounding up each element of the vector
+ \endcode
+
+// \n \subsection vector_operators_conj conj()
+//
+// The \c conj() function can be applied on a dense or sparse vector to compute the complex
+// conjugate of each element of the vector:
+
+ \code
+ using blaze::StaticVector;
+
+ typedef std::complex<double> cplx;
+
+ // Creating the vector
+ // ( (-2,-1) )
+ // ( ( 1, 1) )
+ StaticVector<cplx,2UL> a{ cplx(-2.0,-1.0), cplx(1.0,1.0) };
+
+ // Computing the vector of complex conjugates
+ // ( (-2, 1) )
+ // ( ( 1,-1) )
+ StaticVector<cplx,2UL> b;
+ b = conj( a );
+ \endcode
+
+// Additionally, vectors can be conjugated in-place via the \c conjugate() function:
+
+ \code
+ blaze::DynamicVector<cplx> c( 5UL );
+
+ conjugate( c ); // In-place conjugate operation.
+ c = conj( c ); // Same as above
+ \endcode
+
+// \n \subsection vector_operators_real real()
+//
+// The \c real() function can be used on a dense or sparse vector to extract the real part of
+// each element of the vector:
+
+ \code
+ using blaze::StaticVector;
+
+ typedef std::complex<double> cplx;
+
+ // Creating the vector
+ // ( (-2,-1) )
+ // ( ( 1, 1) )
+ StaticVector<cplx,2UL> a{ cplx(-2.0,-1.0), cplx(1.0,1.0) };
+
+ // Extracting the real part of each vector element
+ // ( -2 )
+ // ( 1 )
+ StaticVector<double,2UL> b;
+ b = real( a );
+ \endcode
+
+// \n \subsection vector_operators_imag imag()
+//
+// The \c imag() function can be used on a dense or sparse vector to extract the imaginary part
+// of each element of the vector:
+
+ \code
+ using blaze::StaticVector;
+
+ typedef std::complex<double> cplx;
+
+ // Creating the vector
+ // ( (-2,-1) )
+ // ( ( 1, 1) )
+ StaticVector<cplx,2UL> a{ cplx(-2.0,-1.0), cplx(1.0,1.0) };
+
+ // Extracting the imaginary part of each vector element
+ // ( -1 )
+ // ( 1 )
+ StaticVector<double,2UL> b;
+ b = imag( a );
+ \endcode
+
+// \n \subsection vector_operations_sqrt sqrt() / invsqrt()
+//
+// Via the \c sqrt() and \c invsqrt() functions the (inverse) square root of each element of a
+// vector can be computed:
+
+ \code
+ blaze::DynamicVector<double> a, b, c;
+
+ b = sqrt( a ); // Computes the square root of each element
+ c = invsqrt( a ); // Computes the inverse square root of each element
+ \endcode
+
+// Note that in case of sparse vectors only the non-zero elements are taken into account!
+//
+//
+// \n \subsection vector_operations_cbrt cbrt() / invcbrt()
+//
+// The \c cbrt() and \c invcbrt() functions can be used to compute the the (inverse) cubic root
+// of each element of a vector:
+
+ \code
+ blaze::HybridVector<double,3UL> a, b, c;
+
+ b = cbrt( a ); // Computes the cubic root of each element
+ c = invcbrt( a ); // Computes the inverse cubic root of each element
+ \endcode
+
+// Note that in case of sparse vectors only the non-zero elements are taken into account!
+//
+//
+// \n \subsection vector_operations_pow pow()
+//
+// The \c pow() function can be used to compute the exponential value of each element of a vector:
+
+ \code
+ blaze::StaticVector<double,3UL> a, b;
+
+ b = pow( a, 1.2 ); // Computes the exponential value of each element
+ \endcode
+
+// \n \subsection vector_operations_exp exp()
+//
+// \c exp() computes the base e exponential of each element of a vector:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+
+ b = exp( a ); // Computes the base e exponential of each element
+ \endcode
+
+// Note that in case of sparse vectors only the non-zero elements are taken into account!
+//
+//
+// \n \subsection vector_operations_log log() / log10()
+//
+// The \c log() and \c log10() functions can be used to compute the natural and common logarithm
+// of each element of a vector:
+
+ \code
+ blaze::StaticVector<double,3UL> a, b;
+
+ b = log( a ); // Computes the natural logarithm of each element
+ b = log10( a ); // Computes the common logarithm of each element
+ \endcode
+
+// \n \subsection vector_operations_trigonometric_functions sin() / cos() / tan() / asin() / acos() / atan()
+//
+// The following trigonometric functions are available for both dense and sparse vectors:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+
+ b = sin( a ); // Computes the sine of each element of the vector
+ b = cos( a ); // Computes the cosine of each element of the vector
+ b = tan( a ); // Computes the tangent of each element of the vector
+
+ b = asin( a ); // Computes the inverse sine of each element of the vector
+ b = acos( a ); // Computes the inverse cosine of each element of the vector
+ b = atan( a ); // Computes the inverse tangent of each element of the vector
+ \endcode
+
+// Note that in case of sparse vectors only the non-zero elements are taken into account!
+//
+//
+// \n \subsection vector_operations_hyperbolic_functions sinh() / cosh() / tanh() / asinh() / acosh() / atanh()
+//
+// The following hyperbolic functions are available for both dense and sparse vectors:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+
+ b = sinh( a ); // Computes the hyperbolic sine of each element of the vector
+ b = cosh( a ); // Computes the hyperbolic cosine of each element of the vector
+ b = tanh( a ); // Computes the hyperbolic tangent of each element of the vector
+
+ b = asinh( a ); // Computes the inverse hyperbolic sine of each element of the vector
+ b = acosh( a ); // Computes the inverse hyperbolic cosine of each element of the vector
+ b = atanh( a ); // Computes the inverse hyperbolic tangent of each element of the vector
+ \endcode
+
+// Note that in case of sparse vectors only the non-zero elements are taken into account!
+//
+//
+// \n \subsection vector_operations_erf erf() / erfc()
+//
+// The \c erf() and \c erfc() functions compute the (complementary) error function of each
+// element of a vector:
+
+ \code
+ blaze::StaticVector<double,3UL,rowVector> a, b;
+
+ b = erf( a ); // Computes the error function of each element
+ b = erfc( a ); // Computes the complementary error function of each element
+ \endcode
+
+// Note that in case of sparse vectors only the non-zero elements are taken into account!
+//
+//
+// \n \subsection vector_operations_foreach forEach()
+//
+// Via the \c forEach() function it is possible to execute custom operations on dense and sparse
+// vectors. For instance, the following example demonstrates a custom square root computation via
+// a lambda:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+
+ b = forEach( a, []( double d ) { return std::sqrt( d ); } );
+ \endcode
+
+// Although the computation can be parallelized it is not vectorized and thus cannot perform at
+// peak performance. However, it is also possible to create vectorized custom operations. See
+// \ref custom_operations for a detailed overview of the possibilities of custom operations.
+//
+//
+// \n \subsection vector_operations_length length() / sqrLength()
+//
+// In order to calculate the length of a vector, both the \c length() and \c sqrLength() function
+// can be used:
+
+ \code
+ blaze::StaticVector<float,3UL,rowVector> v{ -1.2F, 2.7F, -2.3F };
+
+ const float len = length ( v ); // Computes the current length of the vector
+ const float sqrlen = sqrLength( v ); // Computes the square length of the vector
+ \endcode
+
+// Note that both functions can only be used for vectors with built-in or complex element type!
+//
+//
+// \n \subsection vector_operations_vector_transpose trans()
+//
+// As already mentioned, vectors can either be column vectors (blaze::columnVector) or row vectors
+// (blaze::rowVector). A column vector cannot be assigned to a row vector and vice versa. However,
+// vectors can be transposed via the \c trans() function:
+
+ \code
+ blaze::DynamicVector<int,columnVector> v1( 4UL );
+ blaze::CompressedVector<int,rowVector> v2( 4UL );
+
+ v1 = v2; // Compilation error: Cannot assign a row vector to a column vector
+ v1 = trans( v2 ); // OK: Transposing the row vector to a column vector and assigning it
+ // to the column vector v1
+ v2 = trans( v1 ); // OK: Transposing the column vector v1 and assigning it to the row vector v2
+ v1 += trans( v2 ); // OK: Addition assignment of two column vectors
+ \endcode
+
+// \n \subsection vector_operations_conjugate_transpose ctrans()
+//
+// It is also possible to compute the conjugate transpose of a vector. This operation is available
+// via the \c ctrans() function:
+
+ \code
+ blaze::CompressedVector< complex<float>, rowVector > v1( 4UL );
+ blaze::DynamicVector< complex<float>, columnVector > v2( 4UL );
+
+ v1 = ctrans( v2 ); // Compute the conjugate transpose vector
+ \endcode
+
+// Note that the \c ctrans() function has the same effect as manually applying the \c conj() and
+// \c trans() function in any order:
+
+ \code
+ v1 = trans( conj( v2 ) ); // Computing the conjugate transpose vector
+ v1 = conj( trans( v2 ) ); // Computing the conjugate transpose vector
+ \endcode
+
+// \n \subsection vector_operations_normalize normalize()
+//
+// The \c normalize() function can be used to scale any non-zero vector to a length of 1. In
+// case the vector does not contain a single non-zero element (i.e. is a zero vector), the
+// \c normalize() function returns a zero vector.
+
+ \code
+ blaze::DynamicVector<float,columnVector> v1( 10UL );
+ blaze::CompressedVector<double,columnVector> v2( 12UL );
+
+ v1 = normalize( v1 ); // Normalizing the dense vector v1
+ length( v1 ); // Returns 1 (or 0 in case of a zero vector)
+ v1 = normalize( v2 ); // Assigning v1 the normalized vector v2
+ length( v1 ); // Returns 1 (or 0 in case of a zero vector)
+ \endcode
+
+// Note that the \c normalize() function only works for floating point vectors. The attempt to
+// use it for an integral vector results in a compile time error.
+//
+// \n \subsection vector_operations_swap swap()
+//
+// Via the \c swap() function it is possible to completely swap the contents of two vectors of
+// the same type:
+
+ \code
+ blaze::DynamicVector<int,columnVector> v1( 10UL );
+ blaze::DynamicVector<int,columnVector> v2( 20UL );
+
+ swap( v1, v2 ); // Swapping the contents of v1 and v2
+ \endcode
+
+// \n Previous: \ref vector_types &nbsp; &nbsp; Next: \ref matrices
+*/
+//*************************************************************************************************
+
+
+//**Matrices***************************************************************************************
+/*!\page matrices Matrices
+//
+// \tableofcontents
+//
+//
+// \n \section matrices_general General Concepts
+// <hr>
+//
+// The \b Blaze library currently offers four dense matrix types (\ref matrix_types_static_matrix,
+// \ref matrix_types_dynamic_matrix, \ref matrix_types_hybrid_matrix, and \ref matrix_types_custom_matrix)
+// and one sparse matrix type (\ref matrix_types_compressed_matrix). All matrices can either be
+// stored as row-major matrices or column-major matrices:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Setup of the 2x3 row-major dense matrix
+ //
+ // ( 1 2 3 )
+ // ( 4 5 6 )
+ //
+ DynamicMatrix<int,rowMajor> A{ { 1, 2, 3 },
+ { 4, 5, 6 } };
+
+ // Setup of the 3x2 column-major dense matrix
+ //
+ // ( 1 4 )
+ // ( 2 5 )
+ // ( 3 6 )
+ //
+ DynamicMatrix<int,columnMajor> B{ { 1, 4 },
+ { 2, 5 },
+ { 3, 6 } };
+ \endcode
+
+// Per default, all matrices in \b Blaze are row-major matrices:
+
+ \code
+ // Instantiation of a 3x3 row-major matrix
+ blaze::DynamicMatrix<int> C( 3UL, 3UL );
+ \endcode
+
+// \n \section matrices_details Matrix Details
+// <hr>
+//
+// - \ref matrix_types
+// - \ref matrix_operations
+//
+//
+// \n \section matrices_examples Examples
+// <hr>
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ StaticMatrix<double,6UL,20UL> A; // Instantiation of a 6x20 row-major static matrix
+ CompressedMatrix<double,rowMajor> B; // Instantiation of a row-major compressed matrix
+ DynamicMatrix<double,columnMajor> C; // Instantiation of a column-major dynamic matrix
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// \n Previous: \ref vector_operations &nbsp; &nbsp; Next: \ref matrix_types
+*/
+//*************************************************************************************************
+
+
+//**Matrix Types***********************************************************************************
+/*!\page matrix_types Matrix Types
+//
+// \tableofcontents
+//
+//
+// \n \section matrix_types_static_matrix StaticMatrix
+// <hr>
+//
+// The blaze::StaticMatrix class template is the representation of a fixed size matrix with
+// statically allocated elements of arbitrary type. It can be included via the header file
+
+ \code
+ #include <blaze/math/StaticMatrix.h>
+ \endcode
+
+// The type of the elements, the number of rows and columns, and the storage order of the matrix
+// can be specified via the four template parameters:
+
+ \code
+ template< typename Type, size_t M, size_t N, bool SO >
+ class StaticMatrix;
+ \endcode
+
+// - \c Type: specifies the type of the matrix elements. StaticMatrix can be used with any
+// non-cv-qualified, non-reference element type.
+// - \c M : specifies the total number of rows of the matrix.
+// - \c N : specifies the total number of columns of the matrix. Note that it is expected
+// that StaticMatrix is only used for tiny and small matrices.
+// - \c SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// The blaze::StaticMatrix is perfectly suited for small to medium matrices whose dimensions are
+// known at compile time:
+
+ \code
+ // Definition of a 3x4 integral row-major matrix
+ blaze::StaticMatrix<int,3UL,4UL> A;
+
+ // Definition of a 4x6 single precision row-major matrix
+ blaze::StaticMatrix<float,4UL,6UL,blaze::rowMajor> B;
+
+ // Definition of a 6x4 double precision column-major matrix
+ blaze::StaticMatrix<double,6UL,4UL,blaze::columnMajor> C;
+ \endcode
+
+// \n \section matrix_types_dynamic_matrix DynamicMatrix
+// <hr>
+//
+// The blaze::DynamicMatrix class template is the representation of an arbitrary sized matrix
+// with \f$ M \cdot N \f$ dynamically allocated elements of arbitrary type. It can be included
+// via the header file
+
+ \code
+ #include <blaze/math/DynamicMatrix.h>
+ \endcode
+
+// The type of the elements and the storage order of the matrix can be specified via the two
+// template parameters:
+
+ \code
+ template< typename Type, bool SO >
+ class DynamicMatrix;
+ \endcode
+
+// - \c Type: specifies the type of the matrix elements. DynamicMatrix can be used with any
+// non-cv-qualified, non-reference element type.
+// - \c SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// The blaze::DynamicMatrix is the default choice for all kinds of dense matrices and the best
+// choice for medium to large matrices. The number of rows and columns can be modified at runtime:
+
+ \code
+ // Definition of a 3x4 integral row-major matrix
+ blaze::DynamicMatrix<int> A( 3UL, 4UL );
+
+ // Definition of a 4x6 single precision row-major matrix
+ blaze::DynamicMatrix<float,blaze::rowMajor> B( 4UL, 6UL );
+
+ // Definition of a double precision column-major matrix with 0 rows and columns
+ blaze::DynamicMatrix<double,blaze::columnMajor> C;
+ \endcode
+
+// \n \section matrix_types_hybrid_matrix HybridMatrix
+// <hr>
+//
+// The HybridMatrix class template combines the flexibility of a dynamically sized matrix with
+// the efficiency and performance of a fixed size matrix. It is implemented as a crossing between
+// the blaze::StaticMatrix and the blaze::DynamicMatrix class templates: Similar to the static
+// matrix it uses static stack memory instead of dynamically allocated memory and similar to the
+// dynamic matrix it can be resized (within the extend of the static memory). It can be included
+// via the header file
+
+ \code
+ #include <blaze/math/HybridMatrix.h>
+ \endcode
+
+// The type of the elements, the maximum number of rows and columns and the storage order of the
+// matrix can be specified via the four template parameters:
+
+ \code
+ template< typename Type, size_t M, size_t N, bool SO >
+ class HybridMatrix;
+ \endcode
+
+// - Type: specifies the type of the matrix elements. HybridMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - M : specifies the maximum number of rows of the matrix.
+// - N : specifies the maximum number of columns of the matrix. Note that it is expected
+// that HybridMatrix is only used for tiny and small matrices.
+// - SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// The blaze::HybridMatrix is a suitable choice for small to medium matrices, whose dimensions
+// are not known at compile time or not fixed at runtime, but whose maximum dimensions are known
+// at compile time:
+
+ \code
+ // Definition of a 3x4 integral row-major matrix with maximum dimensions of 6x8
+ blaze::HybridMatrix<int,6UL,8UL> A( 3UL, 4UL );
+
+ // Definition of a 4x6 single precision row-major matrix with maximum dimensions of 12x16
+ blaze::HybridMatrix<float,12UL,16UL,blaze::rowMajor> B( 4UL, 6UL );
+
+ // Definition of a 0x0 double precision column-major matrix and maximum dimensions of 6x6
+ blaze::HybridMatrix<double,6UL,6UL,blaze::columnMajor> C;
+ \endcode
+
+// \n \section matrix_types_custom_matrix CustomMatrix
+// <hr>
+//
+// The blaze::CustomMatrix class template provides the functionality to represent an external
+// array of elements of arbitrary type and a fixed size as a native \b Blaze dense matrix data
+// structure. Thus in contrast to all other dense matrix types a custom matrix does not perform
+// any kind of memory allocation by itself, but it is provided with an existing array of element
+// during construction. A custom matrix can therefore be considered an alias to the existing
+// array. It can be included via the header file
+
+ \code
+ #include <blaze/math/CustomMatrix.h>
+ \endcode
+
+// The type of the elements, the properties of the given array of elements and the storage order
+// of the matrix can be specified via the following four template parameters:
+
+ \code
+ template< typename Type, bool AF, bool PF, bool SO >
+ class CustomMatrix;
+ \endcode
+
+// - Type: specifies the type of the matrix elements. blaze::CustomMatrix can be used with
+// any non-cv-qualified, non-reference, non-pointer element type.
+// - AF : specifies whether the represented, external arrays are properly aligned with
+// respect to the available instruction set (SSE, AVX, ...) or not.
+// - PF : specified whether the represented, external arrays are properly padded with
+// respect to the available instruction set (SSE, AVX, ...) or not.
+// - SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// The blaze::CustomMatrix is the right choice if any external array needs to be represented as
+// a \b Blaze dense matrix data structure or if a custom memory allocation strategy needs to be
+// realized:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+
+ // Definition of an unmanaged 3x4 custom matrix for unaligned, unpadded integer arrays
+ typedef CustomMatrix<int,unaligned,unpadded,rowMajor> UnalignedUnpadded;
+ std::vector<int> vec( 12UL )
+ UnalignedUnpadded A( &vec[0], 3UL, 4UL );
+
+ // Definition of a managed 5x6 custom matrix for unaligned but padded 'float' arrays
+ typedef CustomMatrix<float,unaligned,padded,columnMajor> UnalignedPadded;
+ UnalignedPadded B( new float[40], 5UL, 6UL, 8UL, blaze::ArrayDelete() );
+
+ // Definition of a managed 12x13 custom matrix for aligned, unpadded 'double' arrays
+ typedef CustomMatrix<double,aligned,unpadded,rowMajor> AlignedUnpadded;
+ AlignedUnpadded C( blaze::allocate<double>( 192UL ), 12UL, 13UL, 16UL, blaze::Deallocate );
+
+ // Definition of a 7x14 custom matrix for aligned, padded 'complex<double>' arrays
+ typedef CustomMatrix<complex<double>,aligned,padded,columnMajor> AlignedPadded;
+ AlignedPadded D( blaze::allocate<double>( 112UL ), 7UL, 14UL, 16UL, blaze::Deallocate() );
+ \endcode
+
+// In comparison with the remaining \b Blaze dense matrix types blaze::CustomMatrix has several
+// special characteristics. All of these result from the fact that a custom matrix is not
+// performing any kind of memory allocation, but instead is given an existing array of elements.
+// The following sections discuss all of these characteristics:
+//
+// -# <b>\ref matrix_types_custom_matrix_memory_management</b>
+// -# <b>\ref matrix_types_custom_matrix_copy_operations</b>
+// -# <b>\ref matrix_types_custom_matrix_alignment</b>
+// -# <b>\ref matrix_types_custom_matrix_padding</b>
+//
+// \n \subsection matrix_types_custom_matrix_memory_management Memory Management
+//
+// The blaze::CustomMatrix class template acts as an adaptor for an existing array of elements. As
+// such it provides everything that is required to use the array just like a native \b Blaze dense
+// matrix data structure. However, this flexibility comes with the price that the user of a custom
+// matrix is responsible for the resource management.
+//
+// When constructing a custom matrix there are two choices: Either a user manually manages the
+// array of elements outside the custom matrix, or alternatively passes the responsibility for
+// the memory management to an instance of CustomMatrix. In the second case the CustomMatrix
+// class employs shared ownership between all copies of the custom matrix, which reference the
+// same array.
+//
+// The following examples give an impression of several possible types of custom matrices:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::ArrayDelete;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x4 custom row-major matrix with unaligned, unpadded and externally
+ // managed integer array. Note that the std::vector must be guaranteed to outlive the
+ // custom matrix!
+ std::vector<int> vec( 12UL );
+ CustomMatrix<int,unaligned,unpadded> A( &vec[0], 3UL, 4UL );
+
+ // Definition of a 3x4 custom row-major matrix for unaligned, unpadded integer arrays.
+ // The responsibility for the memory management is passed to the custom matrix by
+ // providing a deleter of type 'blaze::ArrayDelete' that is used during the destruction
+ // of the custom matrix.
+ CustomMatrix<int,unaligned,unpadded,rowMajor> B( new int[12], 3UL, 4UL, ArrayDelete() );
+
+ // Definition of a custom 8x12 matrix for an aligned and padded integer array of
+ // capacity 128 (including 8 padding elements per row). The memory management is passed
+ // to the custom matrix by providing a deleter of type 'blaze::Deallocate'.
+ CustomMatrix<int,aligned,padded> C( allocate<int>( 128UL ), 8UL, 12UL, 16UL, Deallocate() );
+ \endcode
+
+// It is possible to pass any type of deleter to the constructor. The deleter is only required
+// to provide a function call operator that can be passed the pointer to the managed array. As
+// an example the following code snipped shows the implementation of two native \b Blaze deleters
+// blaze::ArrayDelete and blaze::Deallocate:
+
+ \code
+ namespace blaze {
+
+ struct ArrayDelete
+ {
+ template< typename Type >
+ inline void operator()( Type ptr ) const { boost::checked_array_delete( ptr ); }
+ };
+
+ struct Deallocate
+ {
+ template< typename Type >
+ inline void operator()( Type ptr ) const { deallocate( ptr ); }
+ };
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection matrix_types_custom_matrix_copy_operations Copy Operations
+//
+// As with all dense matrices it is possible to copy construct a custom matrix:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+
+ typedef CustomMatrix<int,unaligned,unpadded> CustomType;
+
+ std::vector<int> vec( 6UL, 10 ); // Vector of 6 integers of the value 10
+ CustomType A( &vec[0], 2UL, 3UL ); // Represent the std::vector as Blaze dense matrix
+ a[1] = 20; // Also modifies the std::vector
+
+ CustomType B( a ); // Creating a copy of vector a
+ b[2] = 20; // Also affect matrix A and the std::vector
+ \endcode
+
+// It is important to note that a custom matrix acts as a reference to the specified array. Thus
+// the result of the copy constructor is a new custom matrix that is referencing and representing
+// the same array as the original custom matrix. In case a deleter has been provided to the first
+// custom matrix, both matrices share the responsibility to destroy the array when the last matrix
+// goes out of scope.
+//
+// In contrast to copy construction, just as with references, copy assignment does not change
+// which array is referenced by the custom matrices, but modifies the values of the array:
+
+ \code
+ std::vector<int> vec2( 6UL, 4 ); // Vector of 6 integers of the value 4
+ CustomType C( &vec2[0], 2UL, 3UL ); // Represent the std::vector as Blaze dense matrix
+
+ A = C; // Copy assignment: Set all values of matrix A and B to 4.
+ \endcode
+
+// \n \subsection matrix_types_custom_matrix_alignment Alignment
+//
+// In case the custom matrix is specified as \c aligned the passed array must adhere to some
+// alignment restrictions based on the alignment requirements of the used data type and the
+// used instruction set (SSE, AVX, ...). The restriction applies to the first element of each
+// row/column: In case of a row-major matrix the first element of each row must be properly
+// aligned, in case of a column-major matrix the first element of each column must be properly
+// aligned. For instance, if a row-major matrix is used and AVX is active the first element of
+// each row must be 32-bit aligned:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::Deallocate;
+ using blaze::aligned;
+ using blaze::padded;
+ using blaze::rowMajor;
+
+ int* array = blaze::allocate<int>( 40UL ); // Is guaranteed to be 32-bit aligned
+ CustomMatrix<int,aligned,padded,rowMajor> A( array, 5UL, 6UL, 8UL, Deallocate() );
+ \endcode
+
+// In the example, the row-major matrix has six columns. However, since with AVX eight integer
+// values are loaded together the matrix is padded with two additional elements. This guarantees
+// that the first element of each row is 32-bit aligned. In case the alignment requirements are
+// violated, a \c std::invalid_argument exception is thrown.
+//
+// \n \subsection matrix_types_custom_matrix_padding Padding
+//
+// Adding padding elements to the end of each row/column can have a significant impact on the
+// performance. For instance, assuming that AVX is available, then two aligned, padded, 3x3 double
+// precision matrices can be added via three SIMD addition operations:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::padded;
+
+ typedef CustomMatrix<double,aligned,padded> CustomType;
+
+ // Creating padded custom 3x3 matrix with an additional padding element in each row
+ CustomType A( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+ CustomType B( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+ CustomType C( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+
+ // ... Initialization
+
+ C = A + B; // AVX-based matrix addition
+ \endcode
+
+// In this example, maximum performance is possible. However, in case no padding elements are
+// inserted a scalar addition has to be used:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unpadded;
+
+ typedef CustomMatrix<double,aligned,unpadded> CustomType;
+
+ // Creating unpadded custom 3x3 matrix
+ CustomType A( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+ CustomType B( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+ CustomType C( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+
+ // ... Initialization
+
+ C = A + B; // Scalar matrix addition
+ \endcode
+
+// Note that the construction of padded and unpadded aligned matrices looks identical. However,
+// in case of padded matrices, \b Blaze will zero initialize the padding element and use them
+// in all computations in order to achieve maximum performance. In case of an unpadded matrix
+// \b Blaze will ignore the elements with the downside that it is not possible to load a complete
+// row to an AVX register, which makes it necessary to fall back to a scalar addition.
+//
+// The number of padding elements is required to be sufficient with respect to the available
+// instruction set: In case of an aligned padded custom matrix the added padding elements must
+// guarantee that the total number of elements in each row/column is a multiple of the SIMD
+// vector width. In case of an unaligned padded matrix the number of padding elements can be
+// greater or equal the number of padding elements of an aligned padded custom matrix. In case
+// the padding is insufficient with respect to the available instruction set, a
+// \c std::invalid_argument exception is thrown.
+//
+//
+// \n \section matrix_types_compressed_matrix CompressedMatrix
+// <hr>
+//
+// The blaze::CompressedMatrix class template is the representation of an arbitrary sized sparse
+// matrix with \f$ M \cdot N \f$ dynamically allocated elements of arbitrary type. It can be
+// included via the header file
+
+ \code
+ #include <blaze/math/CompressedMatrix.h>
+ \endcode
+
+// The type of the elements and the storage order of the matrix can be specified via the two
+// template parameters:
+
+ \code
+ template< typename Type, bool SO >
+ class CompressedMatrix;
+ \endcode
+
+// - \c Type: specifies the type of the matrix elements. CompressedMatrix can be used with
+// any non-cv-qualified, non-reference, non-pointer element type.
+// - \c SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// The blaze::CompressedMatrix is the right choice for all kinds of sparse matrices:
+
+ \code
+ // Definition of a 3x4 integral row-major matrix
+ blaze::CompressedMatrix<int> A( 3UL, 4UL );
+
+ // Definition of a 4x6 single precision row-major matrix
+ blaze::CompressedMatrix<float,blaze::rowMajor> B( 4UL, 6UL );
+
+ // Definition of a double precision column-major matrix with 0 rows and columns
+ blaze::CompressedMatrix<double,blaze::columnMajor> C;
+ \endcode
+
+// \n Previous: \ref matrices &nbsp; &nbsp; Next: \ref matrix_operations
+*/
+//*************************************************************************************************
+
+
+//**Matrix Operations******************************************************************************
+/*!\page matrix_operations Matrix Operations
+//
+// \tableofcontents
+//
+//
+// \n \section matrix_operations_constructors Constructors
+// <hr>
+//
+// Matrices are just as easy and intuitive to create as vectors. Still, there are a few rules
+// to be aware of:
+// - In case the last template parameter (the storage order) is omitted, the matrix is per
+// default stored in row-major order.
+// - The elements of a \c StaticMatrix or \c HybridMatrix are default initialized (i.e. built-in
+// data types are initialized to 0, class types are initialized via the default constructor).
+// - Newly allocated elements of a \c DynamicMatrix or \c CompressedMatrix remain uninitialized
+// if they are of built-in type and are default constructed if they are of class type.
+//
+// \n \subsection matrix_operations_default_construction Default Construction
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::CompressedMatrix;
+
+ // All matrices can be default constructed. Whereas the size of
+ // a StaticMatrix is fixed via the second and third template
+ // parameter, the initial size of a constructed DynamicMatrix
+ // or CompressedMatrix is 0.
+ StaticMatrix<int,2UL,2UL> M1; // Instantiation of a 2x2 integer row-major
+ // matrix. All elements are initialized to 0.
+ DynamicMatrix<float> M2; // Instantiation of a single precision dynamic
+ // row-major matrix with 0 rows and 0 columns.
+ DynamicMatrix<double,columnMajor> M3; // Instantiation of a double precision dynamic
+ // column-major matrix with 0 rows and 0 columns.
+ CompressedMatrix<int> M4; // Instantiation of a compressed integer
+ // row-major matrix of size 0x0.
+ CompressedMatrix<double,columnMajor> M5; // Instantiation of a compressed double precision
+ // column-major matrix of size 0x0.
+ \endcode
+
+// \n \subsection matrix_operations_size_construction Construction with Specific Size
+//
+// The \c DynamicMatrix, \c HybridMatrix, and \c CompressedMatrix classes offer a constructor
+// that allows to immediately give the matrices a specific number of rows and columns:
+
+ \code
+ DynamicMatrix<int> M6( 5UL, 4UL ); // Instantiation of a 5x4 dynamic row-major
+ // matrix. The elements are not initialized.
+ HybridMatrix<double,5UL,9UL> M7( 3UL, 7UL ); // Instantiation of a 3x7 hybrid row-major
+ // matrix. The elements are not initialized.
+ CompressedMatrix<float,columnMajor> M8( 8UL, 6UL ); // Instantiation of an empty 8x6 compressed
+ // column-major matrix.
+ \endcode
+
+// Note that dense matrices (in this case \c DynamicMatrix and \c HybridMatrix) immediately
+// allocate enough capacity for all matrix elements. Sparse matrices on the other hand (in this
+// example \c CompressedMatrix) merely acquire the size, but don't necessarily allocate memory.
+//
+//
+// \n \subsection matrix_operations_initialization_constructors Initialization Constructors
+//
+// All dense matrix classes offer a constructor for a direct, homogeneous initialization of all
+// matrix elements. In contrast, for sparse matrices the predicted number of non-zero elements
+// can be specified.
+
+ \code
+ StaticMatrix<int,4UL,3UL,columnMajor> M9( 7 ); // Instantiation of a 4x3 integer column-major
+ // matrix. All elements are initialized to 7.
+ DynamicMatrix<float> M10( 2UL, 5UL, 2.0F ); // Instantiation of a 2x5 single precision row-major
+ // matrix. All elements are initialized to 2.0F.
+ CompressedMatrix<int> M11( 3UL, 4UL, 4 ); // Instantiation of a 3x4 integer row-major
+ // matrix with capacity for 4 non-zero elements.
+ \endcode
+
+// \n \subsection matrix_operations_array_construction Array Construction
+//
+// Alternatively, all dense matrix classes offer a constructor for an initialization with a
+// dynamic or static array. If the matrix is initialized from a dynamic array, the constructor
+// expects the dimensions of values provided by the array as first and second argument, the
+// array as third argument. In case of a static array, the fixed size of the array is used:
+
+ \code
+ const std::unique_ptr<double[]> array1( new double[6] );
+ // ... Initialization of the dynamic array
+ blaze::StaticMatrix<double,2UL,3UL> M12( 2UL, 3UL, array1.get() );
+
+ int array2[2][2] = { { 4, -5 }, { -6, 7 } };
+ blaze::StaticMatrix<int,2UL,2UL,rowMajor> M13( array2 );
+ \endcode
+
+// \n \subsection matrix_operations_initializer_list_construction
+//
+// In addition, all dense matrix classes can be directly initialized by means of an initializer
+// list:
+
+ \code
+ blaze::DynamicMatrix<float,columnMajor> M14{ { 3.1F, 6.4F },
+ { -0.9F, -1.2F },
+ { 4.8F, 0.6F } };
+ \endcode
+
+// \n \subsection matrix_operations_copy_construction Copy Construction
+//
+// All dense and sparse matrices can be created as a copy of another dense or sparse matrix.
+
+ \code
+ StaticMatrix<int,5UL,4UL,rowMajor> M15( M6 ); // Instantiation of the dense row-major matrix M15
+ // as copy of the dense row-major matrix M6.
+ DynamicMatrix<float,columnMajor> M16( M8 ); // Instantiation of the dense column-major matrix M16
+ // as copy of the sparse column-major matrix M8.
+ CompressedMatrix<double,columnMajor> M17( M7 ); // Instantiation of the compressed column-major matrix
+ // M17 as copy of the dense row-major matrix M7.
+ CompressedMatrix<float,rowMajor> M18( M8 ); // Instantiation of the compressed row-major matrix
+ // M18 as copy of the compressed column-major matrix M8.
+ \endcode
+
+// Note that it is not possible to create a \c StaticMatrix as a copy of a matrix with a different
+// number of rows and/or columns:
+
+ \code
+ StaticMatrix<int,4UL,5UL,rowMajor> M19( M6 ); // Runtime error: Number of rows and columns
+ // does not match!
+ StaticMatrix<int,4UL,4UL,columnMajor> M20( M9 ); // Compile time error: Number of columns does
+ // not match!
+ \endcode
+
+// \n \section matrix_operations_assignment Assignment
+// <hr>
+//
+// There are several types of assignment to dense and sparse matrices:
+// \ref matrix_operations_homogeneous_assignment, \ref matrix_operations_array_assignment,
+// \ref matrix_operations_copy_assignment, and \ref matrix_operations_compound_assignment.
+//
+//
+// \n \subsection matrix_operations_homogeneous_assignment Homogeneous Assignment
+//
+// It is possible to assign the same value to all elements of a dense matrix. All dense matrix
+// classes provide an according assignment operator:
+
+ \code
+ blaze::StaticMatrix<int,3UL,2UL> M1;
+ blaze::DynamicMatrix<double> M2;
+
+ // Setting all integer elements of the StaticMatrix to 4
+ M1 = 4;
+
+ // Setting all double precision elements of the DynamicMatrix to 3.5
+ M2 = 3.5
+ \endcode
+
+// \n \subsection matrix_operations_array_assignment Array Assignment
+//
+// Dense matrices can also be assigned a static array:
+
+ \code
+ blaze::StaticMatrix<int,2UL,2UL,rowMajor> M1;
+ blaze::StaticMatrix<int,2UL,2UL,columnMajor> M2;
+ blaze::DynamicMatrix<double> M3;
+
+ int array1[2][2] = { { 1, 2 }, { 3, 4 } };
+ double array2[3][2] = { { 3.1, 6.4 }, { -0.9, -1.2 }, { 4.8, 0.6 } };
+
+ M1 = array1;
+ M2 = array1;
+ M3 = array2;
+ \endcode
+
+// Note that the dimensions of the static array have to match the size of a \c StaticMatrix,
+// whereas a \c DynamicMatrix is resized according to the array dimensions:
+
+ \f$ M3 = \left(\begin{array}{*{2}{c}}
+ 3.1 & 6.4 \\
+ -0.9 & -1.2 \\
+ 4.8 & 0.6 \\
+ \end{array}\right)\f$
+
+// \n \subsection matrix_operations_initializer_list_assignment Initializer List Assignment
+//
+// Alternatively, it is possible to directly assign an initializer list to a dense matrix:
+
+ \code
+ blaze::DynamicMatrix<double> M;
+ M = { { 3.1, 6.4 }, { -0.9, -1.2 }, { 4.8, 0.6 } };
+ \endcode
+
+// \n \subsection matrix_operations_copy_assignment Copy Assignment
+//
+// All kinds of matrices can be assigned to each other. The only restriction is that since a
+// \c StaticMatrix cannot change its size, the assigned matrix must match both in the number of
+// rows and in the number of columns.
+
+ \code
+ blaze::StaticMatrix<int,3UL,2UL,rowMajor> M1;
+ blaze::DynamicMatrix<int,rowMajor> M2( 3UL, 2UL );
+ blaze::DynamicMatrix<float,rowMajor> M3( 5UL, 2UL );
+ blaze::CompressedMatrix<int,rowMajor> M4( 3UL, 2UL );
+ blaze::CompressedMatrix<float,columnMajor> M5( 3UL, 2UL );
+
+ // ... Initialization of the matrices
+
+ M1 = M2; // OK: Assignment of a 3x2 dense row-major matrix to another 3x2 dense row-major matrix
+ M1 = M4; // OK: Assignment of a 3x2 sparse row-major matrix to a 3x2 dense row-major matrix
+ M1 = M3; // Runtime error: Cannot assign a 5x2 matrix to a 3x2 static matrix
+ M1 = M5; // OK: Assignment of a 3x2 sparse column-major matrix to a 3x2 dense row-major matrix
+ \endcode
+
+// \n \subsection matrix_operations_compound_assignment Compound Assignment
+//
+// Compound assignment is also available for matrices: addition assignment, subtraction assignment,
+// and multiplication assignment. In contrast to plain assignment, however, the number of rows
+// and columns of the two operands have to match according to the arithmetic operation.
+
+ \code
+ blaze::StaticMatrix<int,2UL,3UL,rowMajor> M1;
+ blaze::DynamicMatrix<int,rowMajor> M2( 2UL, 3UL );
+ blaze::CompressedMatrix<float,columnMajor> M3( 2UL, 3UL );
+ blaze::CompressedMatrix<float,rowMajor> M4( 2UL, 4UL );
+ blaze::StaticMatrix<float,2UL,4UL,rowMajor> M5;
+ blaze::CompressedMatrix<float,rowMajor> M6( 3UL, 2UL );
+
+ // ... Initialization of the matrices
+
+ M1 += M2; // OK: Addition assignment between two row-major matrices of the same dimensions
+ M1 -= M3; // OK: Subtraction assignment between between a row-major and a column-major matrix
+ M1 += M4; // Runtime error: No compound assignment between matrices of different size
+ M1 -= M5; // Compilation error: No compound assignment between matrices of different size
+ M2 *= M6; // OK: Multiplication assignment between two row-major matrices
+ \endcode
+
+// Note that the multiplication assignment potentially changes the number of columns of the
+// target matrix:
+
+ \f$\left(\begin{array}{*{3}{c}}
+ 2 & 0 & 1 \\
+ 0 & 3 & 2 \\
+ \end{array}\right) \times
+ \left(\begin{array}{*{2}{c}}
+ 4 & 0 \\
+ 1 & 0 \\
+ 0 & 3 \\
+ \end{array}\right) =
+ \left(\begin{array}{*{2}{c}}
+ 8 & 3 \\
+ 3 & 6 \\
+ \end{array}\right)\f$
+
+// Since a \c StaticMatrix cannot change its size, only a square StaticMatrix can be used in a
+// multiplication assignment with other square matrices of the same dimensions.
+//
+//
+// \n \section matrix_operations_element_access Element Access
+// <hr>
+//
+// The easiest way to access a specific dense or sparse matrix element is via the function call
+// operator. The indices to access a matrix are zero-based:
+
+ \code
+ blaze::DynamicMatrix<int> M1( 4UL, 6UL );
+ M1(0,0) = 1;
+ M1(0,1) = 3;
+ // ...
+
+ blaze::CompressedMatrix<double> M2( 5UL, 3UL );
+ M2(0,2) = 4.1;
+ M2(1,1) = -6.3;
+ \endcode
+
+// Since dense matrices allocate enough memory for all contained elements, using the function
+// call operator on a dense matrix directly returns a reference to the accessed value. In case
+// of a sparse matrix, if the accessed value is currently not contained in the matrix, the
+// value is inserted into the matrix prior to returning a reference to the value, which can
+// be much more expensive than the direct access to a dense matrix. Consider the following
+// example:
+
+ \code
+ blaze::CompressedMatrix<int> M1( 4UL, 4UL );
+
+ for( size_t i=0UL; i<M1.rows(); ++i ) {
+ for( size_t j=0UL; j<M1.columns(); ++j ) {
+ ... = M1(i,j);
+ }
+ }
+ \endcode
+
+// Although the compressed matrix is only used for read access within the for loop, using the
+// function call operator temporarily inserts 16 non-zero elements into the matrix. Therefore,
+// all matrices (sparse as well as dense) offer an alternate way via the \c begin(), \c cbegin(),
+// \c end() and \c cend() functions to traverse all contained elements by iterator. Note that
+// it is not possible to traverse all elements of the matrix, but that it is only possible to
+// traverse elements in a row/column-wise fashion. In case of a non-const matrix, \c begin() and
+// \c end() return an \c Iterator, which allows a manipulation of the non-zero value, in case of
+// a constant matrix or in case \c cbegin() or \c cend() are used a \c ConstIterator is returned:
+
+ \code
+ using blaze::CompressedMatrix;
+
+ CompressedMatrix<int,rowMajor> M1( 4UL, 6UL );
+
+ // Traversing the matrix by Iterator
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( CompressedMatrix<int,rowMajor>::Iterator it=A.begin(i); it!=A.end(i); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the non-zero element.
+ }
+ }
+
+ // Traversing the matrix by ConstIterator
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( CompressedMatrix<int,rowMajor>::ConstIterator it=A.cbegin(i); it!=A.cend(i); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the non-zero element.
+ }
+ }
+ \endcode
+
+// Note that \c begin(), \c cbegin(), \c end(), and \c cend() are also available as free functions:
+
+ \code
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( CompressedMatrix<int,rowMajor>::Iterator it=begin( A, i ); it!=end( A, i ); ++it ) {
+ // ...
+ }
+ }
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( CompressedMatrix<int,rowMajor>::ConstIterator it=cbegin( A, i ); it!=cend( A, i ); ++it ) {
+ // ...
+ }
+ }
+ \endcode
+
+// \n \section matrix_operations_element_insertion Element Insertion
+// <hr>
+//
+// Whereas a dense matrix always provides enough capacity to store all matrix elements, a sparse
+// matrix only stores the non-zero elements. Therefore it is necessary to explicitly add elements
+// to the matrix. The first possibility to add elements to a sparse matrix is the function call
+// operator:
+
+ \code
+ using blaze::CompressedMatrix;
+
+ CompressedMatrix<int> M1( 3UL, 4UL );
+ M1(1,2) = 9;
+ \endcode
+
+// In case the element at the given position is not yet contained in the sparse matrix, it is
+// automatically inserted. Otherwise the old value is replaced by the new value 2. The operator
+// returns a reference to the sparse vector element.\n
+// An alternative is the \c set() function: In case the element is not yet contained in the matrix
+// the element is inserted, else the element's value is modified:
+
+ \code
+ // Insert or modify the value at position (2,0)
+ M1.set( 2, 0, 1 );
+ \endcode
+
+// However, insertion of elements can be better controlled via the \c insert() function. In
+// contrast to the function call operator and the \c set() function it emits an exception in case
+// the element is already contained in the matrix. In order to check for this case, the \c find()
+// function can be used:
+
+ \code
+ // In case the element at position (2,3) is not yet contained in the matrix it is inserted
+ // with a value of 4.
+ if( M1.find( 2, 3 ) == M1.end( 2 ) )
+ M1.insert( 2, 3, 4 );
+ \endcode
+
+// Although the \c insert() function is very flexible, due to performance reasons it is not
+// suited for the setup of large sparse matrices. A very efficient, yet also very low-level
+// way to fill a sparse matrix is the \c append() function. It requires the sparse matrix to
+// provide enough capacity to insert a new element in the specified row. Additionally, the
+// index of the new element must be larger than the index of the previous element in the same
+// row. Violating these conditions results in undefined behavior!
+
+ \code
+ M1.reserve( 0, 3 ); // Reserving space for three non-zero elements in row 0
+ M1.append( 0, 1, 2 ); // Appending the element 2 in row 0 at column index 1
+ M1.append( 0, 2, -4 ); // Appending the element -4 in row 0 at column index 2
+ // ...
+ \endcode
+
+// The most efficient way to fill a sparse matrix with elements, however, is a combination of
+// \c reserve(), \c append(), and the \c finalize() function:
+
+ \code
+ blaze::CompressedMatrix<int> M1( 3UL, 5UL );
+ M1.reserve( 3 ); // Reserving enough space for 3 non-zero elements
+ M1.append( 0, 1, 1 ); // Appending the value 1 in row 0 with column index 1
+ M1.finalize( 0 ); // Finalizing row 0
+ M1.append( 1, 1, 2 ); // Appending the value 2 in row 1 with column index 1
+ M1.finalize( 1 ); // Finalizing row 1
+ M1.append( 2, 0, 3 ); // Appending the value 3 in row 2 with column index 0
+ M1.finalize( 2 ); // Finalizing row 2
+ \endcode
+
+// \n \section matrix_operations_member_functions Member Functions
+// <hr>
+//
+// \subsection matrix_operations_rows .rows()
+//
+// The current number of rows of a matrix can be acquired via the \c rows() member function:
+
+ \code
+ // Instantiating a dynamic matrix with 10 rows and 8 columns
+ blaze::DynamicMatrix<int> M1( 10UL, 8UL );
+ M1.rows(); // Returns 10
+
+ // Instantiating a compressed matrix with 8 rows and 12 columns
+ blaze::CompressedMatrix<double> M2( 8UL, 12UL );
+ M2.rows(); // Returns 8
+ \endcode
+
+// Alternatively, the free functions \c rows() can be used to query the current number of rows of
+// a matrix. In contrast to the member function, the free function can also be used to query the
+// number of rows of a matrix expression:
+
+ \code
+ rows( M1 ); // Returns 10, i.e. has the same effect as the member function
+ rows( M2 ); // Returns 8, i.e. has the same effect as the member function
+
+ rows( M1 * M2 ); // Returns 10, i.e. the number of rows of the resulting matrix
+ \endcode
+
+// \n \subsection matrix_operations_columns .columns()
+//
+// The current number of columns of a matrix can be acquired via the \c columns() member function:
+
+ \code
+ // Instantiating a dynamic matrix with 6 rows and 8 columns
+ blaze::DynamicMatrix<int> M1( 6UL, 8UL );
+ M1.columns(); // Returns 8
+
+ // Instantiating a compressed matrix with 8 rows and 7 columns
+ blaze::CompressedMatrix<double> M2( 8UL, 7UL );
+ M2.columns(); // Returns 7
+ \endcode
+
+// There is also a free function \c columns() available, which can also be used to query the number
+// of columns of a matrix expression:
+
+ \code
+ columns( M1 ); // Returns 8, i.e. has the same effect as the member function
+ columns( M2 ); // Returns 7, i.e. has the same effect as the member function
+
+ columns( M1 * M2 ); // Returns 7, i.e. the number of columns of the resulting matrix
+ \endcode
+
+// \n \subsection matrix_operations_capacity .capacity()
+//
+// The \c capacity() member function returns the internal capacity of a dense or sparse matrix.
+// Note that the capacity of a matrix doesn't have to be equal to the size of a matrix. In case of
+// a dense matrix the capacity will always be greater or equal than the total number of elements
+// of the matrix. In case of a sparse matrix, the capacity will usually be much less than the
+// total number of elements.
+
+ \code
+ blaze::DynamicMatrix<float> M1( 5UL, 7UL );
+ blaze::StaticMatrix<float,7UL,4UL> M2;
+ M1.capacity(); // Returns at least 35
+ M2.capacity(); // Returns at least 28
+ \endcode
+
+// There is also a free function \c capacity() available to query the capacity. However, please
+// note that this function cannot be used to query the capacity of a matrix expression:
+
+ \code
+ capacity( M1 ); // Returns at least 35, i.e. has the same effect as the member function
+ capacity( M2 ); // Returns at least 28, i.e. has the same effect as the member function
+
+ capacity( M1 * M2 ); // Compilation error!
+ \endcode
+
+// \n \subsection matrix_operations_nonzeros .nonZeros()
+//
+// For both dense and sparse matrices the current number of non-zero elements can be queried
+// via the \c nonZeros() member function. In case of matrices there are two flavors of the
+// \c nonZeros() function: One returns the total number of non-zero elements in the matrix,
+// the second returns the number of non-zero elements in a specific row (in case of a row-major
+// matrix) or column (in case of a column-major matrix). Sparse matrices directly return their
+// number of non-zero elements, dense matrices traverse their elements and count the number of
+// non-zero elements.
+
+ \code
+ blaze::DynamicMatrix<int,rowMajor> M1( 3UL, 5UL );
+
+ // ... Initializing the dense matrix
+
+ M1.nonZeros(); // Returns the total number of non-zero elements in the dense matrix
+ M1.nonZeros( 2 ); // Returns the number of non-zero elements in row 2
+ \endcode
+
+ \code
+ blaze::CompressedMatrix<double,columnMajor> M2( 4UL, 7UL );
+
+ // ... Initializing the sparse matrix
+
+ M2.nonZeros(); // Returns the total number of non-zero elements in the sparse matrix
+ M2.nonZeros( 3 ); // Returns the number of non-zero elements in column 3
+ \endcode
+
+// The free \c nonZeros() function can also be used to query the number of non-zero elements in a
+// matrix expression. However, the result is not the exact number of non-zero elements, but may be
+// a rough estimation:
+
+ \code
+ nonZeros( M1 ); // Has the same effect as the member function
+ nonZeros( M1, 2 ); // Has the same effect as the member function
+
+ nonZeros( M2 ); // Has the same effect as the member function
+ nonZeros( M2, 3 ); // Has the same effect as the member function
+
+ nonZeros( M1 * M2 ); // Estimates the number of non-zero elements in the matrix expression
+ \endcode
+
+// \n \subsection matrix_operations_resize_reserve .resize() / .reserve()
+//
+// The dimensions of a \c StaticMatrix are fixed at compile time by the second and third template
+// parameter and a \c CustomMatrix cannot be resized. In contrast, the number or rows and columns
+// of \c DynamicMatrix, \c HybridMatrix, and \c CompressedMatrix can be changed at runtime:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::CompressedMatrix;
+
+ DynamicMatrix<int,rowMajor> M1;
+ CompressedMatrix<int,columnMajor> M2( 3UL, 2UL );
+
+ // Adapting the number of rows and columns via the resize() function. The (optional)
+ // third parameter specifies whether the existing elements should be preserved.
+ M1.resize( 2UL, 2UL ); // Resizing matrix M1 to 2x2 elements. Elements of built-in type
+ // remain uninitialized, elements of class type are default
+ // constructed.
+ M1.resize( 3UL, 1UL, false ); // Resizing M1 to 3x1 elements. The old elements are lost, the
+ // new elements are NOT initialized!
+ M2.resize( 5UL, 7UL, true ); // Resizing M2 to 5x7 elements. The old elements are preserved.
+ M2.resize( 3UL, 2UL, false ); // Resizing M2 to 3x2 elements. The old elements are lost.
+ \endcode
+
+// Note that resizing a matrix invalidates all existing views (see e.g. \ref views_submatrices)
+// on the matrix:
+
+ \code
+ typedef blaze::DynamicMatrix<int,rowMajor> MatrixType;
+ typedef blaze::Row<MatrixType> RowType;
+
+ MatrixType M1( 10UL, 20UL ); // Creating a 10x20 matrix
+ RowType row8 = row( M1, 8UL ); // Creating a view on the 8th row of the matrix
+ M1.resize( 6UL, 20UL ); // Resizing the matrix invalidates the view
+ \endcode
+
+// When the internal capacity of a matrix is no longer sufficient, the allocation of a larger
+// junk of memory is triggered. In order to avoid frequent reallocations, the \c reserve()
+// function can be used up front to set the internal capacity:
+
+ \code
+ blaze::DynamicMatrix<int> M1;
+ M1.reserve( 100 );
+ M1.rows(); // Returns 0
+ M1.capacity(); // Returns at least 100
+ \endcode
+
+// Additionally it is possible to reserve memory in a specific row (for a row-major matrix) or
+// column (for a column-major matrix):
+
+ \code
+ blaze::CompressedMatrix<int> M1( 4UL, 6UL );
+ M1.reserve( 1, 4 ); // Reserving enough space for four non-zero elements in row 1
+ \endcode
+
+// \n \section matrix_operations_free_functions Free Functions
+// <hr>
+//
+// \subsection matrix_operations_reset_clear reset() / clear
+//
+// In order to reset all elements of a dense or sparse matrix, the \c reset() function can be
+// used. The number of rows and columns of the matrix are preserved:
+
+ \code
+ // Setting up a single precision row-major matrix, whose elements are initialized with 2.0F.
+ blaze::DynamicMatrix<float> M1( 4UL, 5UL, 2.0F );
+
+ // Resetting all elements to 0.0F.
+ reset( M1 ); // Resetting all elements
+ M1.rows(); // Returns 4: size and capacity remain unchanged
+ \endcode
+
+// Alternatively, only a single row or column of the matrix can be resetted:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> M1( 7UL, 6UL, 5 ); // Setup of a row-major matrix
+ blaze::DynamicMatrix<int,blaze::columnMajor> M2( 4UL, 5UL, 4 ); // Setup of a column-major matrix
+
+ reset( M1, 2UL ); // Resetting the 2nd row of the row-major matrix
+ reset( M2, 3UL ); // Resetting the 3rd column of the column-major matrix
+ \endcode
+
+// In order to reset a row of a column-major matrix or a column of a row-major matrix, use a
+// row or column view (see \ref views_rows and views_colums).
+//
+// In order to return a matrix to its default state (i.e. the state of a default constructed
+// matrix), the \c clear() function can be used:
+
+ \code
+ // Setting up a single precision row-major matrix, whose elements are initialized with 2.0F.
+ blaze::DynamicMatrix<float> M1( 4UL, 5UL, 2.0F );
+
+ // Resetting all elements to 0.0F.
+ clear( M1 ); // Resetting the entire matrix
+ M1.rows(); // Returns 0: size is reset, but capacity remains unchanged
+ \endcode
+
+// \n \subsection matrix_operations_isnan isnan()
+//
+// The \c isnan() function provides the means to check a dense or sparse matrix for non-a-number
+// elements:
+
+ \code
+ blaze::DynamicMatrix<double> A( 3UL, 4UL );
+ // ... Initialization
+ if( isnan( A ) ) { ... }
+ \endcode
+
+ \code
+ blaze::CompressedMatrix<double> A( 3UL, 4UL );
+ // ... Initialization
+ if( isnan( A ) ) { ... }
+ \endcode
+
+// If at least one element of the matrix is not-a-number, the function returns \c true, otherwise
+// it returns \c false. Please note that this function only works for matrices with floating point
+// elements. The attempt to use it for a matrix with a non-floating point element type results in
+// a compile time error.
+//
+//
+// \n \subsection matrix_operations_isdefault isDefault()
+//
+// The \c isDefault() function returns whether the given dense or sparse matrix is in default state:
+
+ \code
+ blaze::HybridMatrix<int,5UL,4UL> A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+
+// A matrix is in default state if it appears to just have been default constructed. All resizable
+// matrices (\c HybridMatrix, \c DynamicMatrix, or \c CompressedMatrix) and \c CustomMatrix are in
+// default state if its size is equal to zero. A non-resizable matrix (\c StaticMatrix and all
+// submatrices) is in default state if all its elements are in default state. For instance, in case
+// the matrix is instantiated for a built-in integral or floating point data type, the function
+// returns \c true in case all matrix elements are 0 and \c false in case any matrix element is
+// not 0.
+//
+//
+// \n \subsection matrix_operations_isSquare isSquare()
+//
+// Whether a dense or sparse matrix is a square matrix (i.e. if the number of rows is equal to the
+// number of columns) can be checked via the \c isSquare() function:
+
+ \code
+ blaze::DynamicMatrix<double> A;
+ // ... Resizing and initialization
+ if( isSquare( A ) ) { ... }
+ \endcode
+
+// \n \subsection matrix_operations_issymmetric isSymmetric()
+//
+// Via the \c isSymmetric() function it is possible to check whether a dense or sparse matrix
+// is symmetric:
+
+ \code
+ blaze::DynamicMatrix<float> A;
+ // ... Resizing and initialization
+ if( isSymmetric( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be symmetric!
+//
+//
+// \n \subsection matrix_operations_isUniform isUniform()
+//
+// In order to check if all matrix elements are identical, the \c isUniform function can be used:
+
+ \code
+ blaze::DynamicMatrix<int> A;
+ // ... Resizing and initialization
+ if( isUniform( A ) ) { ... }
+ \endcode
+
+// Note that in case of a sparse matrix also the zero elements are also taken into account!
+//
+//
+// \n \subsection matrix_operations_islower isLower()
+//
+// Via the \c isLower() function it is possible to check whether a dense or sparse matrix is
+// lower triangular:
+
+ \code
+ blaze::DynamicMatrix<float> A;
+ // ... Resizing and initialization
+ if( isLower( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be lower triangular!
+//
+//
+// \n \subsection matrix_operations_isunilower isUniLower()
+//
+// Via the \c isUniLower() function it is possible to check whether a dense or sparse matrix is
+// lower unitriangular:
+
+ \code
+ blaze::DynamicMatrix<float> A;
+ // ... Resizing and initialization
+ if( isUniLower( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be lower unitriangular!
+//
+//
+// \n \subsection matrix_operations_isstrictlylower isStrictlyLower()
+//
+// Via the \c isStrictlyLower() function it is possible to check whether a dense or sparse matrix
+// is strictly lower triangular:
+
+ \code
+ blaze::DynamicMatrix<float> A;
+ // ... Resizing and initialization
+ if( isStrictlyLower( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be strictly lower triangular!
+//
+//
+// \n \subsection matrix_operations_isUpper isUpper()
+//
+// Via the \c isUpper() function it is possible to check whether a dense or sparse matrix is
+// upper triangular:
+
+ \code
+ blaze::DynamicMatrix<float> A;
+ // ... Resizing and initialization
+ if( isUpper( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be upper triangular!
+//
+//
+// \n \subsection matrix_operations_isuniupper isUniUpper()
+//
+// Via the \c isUniUpper() function it is possible to check whether a dense or sparse matrix is
+// upper unitriangular:
+
+ \code
+ blaze::DynamicMatrix<float> A;
+ // ... Resizing and initialization
+ if( isUniUpper( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be upper unitriangular!
+//
+//
+// \n \subsection matrix_operations_isstrictlyupper isStrictlyUpper()
+//
+// Via the \c isStrictlyUpper() function it is possible to check whether a dense or sparse matrix
+// is strictly upper triangular:
+
+ \code
+ blaze::DynamicMatrix<float> A;
+ // ... Resizing and initialization
+ if( isStrictlyUpper( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be strictly upper triangular!
+//
+//
+// \n \subsection matrix_operations_isdiagonal isDiagonal()
+//
+// The \c isDiagonal() function checks if the given dense or sparse matrix is a diagonal matrix,
+// i.e. if it has only elements on its diagonal and if the non-diagonal elements are default
+// elements:
+
+ \code
+ blaze::CompressedMatrix<float> A;
+ // ... Resizing and initialization
+ if( isDiagonal( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be diagonal!
+//
+//
+// \n \subsection matrix_operations_isidentity isIdentity()
+//
+// The \c isIdentity() function checks if the given dense or sparse matrix is an identity matrix,
+// i.e. if all diagonal elements are 1 and all non-diagonal elements are 0:
+
+ \code
+ blaze::CompressedMatrix<float> A;
+ // ... Resizing and initialization
+ if( isIdentity( A ) ) { ... }
+ \endcode
+
+// Note that non-square matrices are never considered to be identity matrices!
+//
+//
+// \n \subsection matrix_operations_min_max min() / max()
+//
+// The \c min() and the \c max() functions return the smallest and largest element of the given
+// dense or sparse matrix, respectively:
+
+ \code
+ blaze::StaticMatrix<int,2UL,3UL,rowMajor> A{ { -5, 2, 7 },
+ { 4, 0, 1 } };
+ blaze::StaticMatrix<int,2UL,3UL,rowMajor> B{ { -5, 2, -7 },
+ { -4, 0, -1 } };
+
+ min( A ); // Returns -5
+ min( B ); // Returns -7
+
+ max( A ); // Returns 7
+ max( B ); // Returns 2
+ \endcode
+
+// In case the matrix currently has 0 rows or 0 columns, both functions return 0. Additionally, in
+// case a given sparse matrix is not completely filled, the zero elements are taken into account.
+// For example: the following compressed matrix has only 2 non-zero elements. However, the minimum
+// of this matrix is 0:
+
+ \code
+ blaze::CompressedMatrix<int> C( 2UL, 3UL );
+ C(0,0) = 1;
+ C(0,2) = 3;
+
+ min( C ); // Returns 0
+ \endcode
+
+// Also note that the \c min() and \c max() functions can be used to compute the smallest and
+// largest element of a matrix expression:
+
+ \code
+ min( A + B + C ); // Returns -9, i.e. the smallest value of the resulting matrix
+ max( A - B - C ); // Returns 11, i.e. the largest value of the resulting matrix
+ \endcode
+
+// \n \subsection matrix_operators_abs abs()
+//
+// The \c abs() function can be used to compute the absolute values of each element of a matrix.
+// For instance, the following computation
+
+ \code
+ blaze::StaticMatrix<int,2UL,3UL,rowMajor> A{ { -1, 2, -3 },
+ { 4, -5, 6 } };
+ blaze::StaticMatrix<int,2UL,3UL,rowMajor> B( abs( A ) );
+ \endcode
+
+// results in the matrix
+
+ \f$ B = \left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 4 & 5 & 6 \\
+ \end{array}\right)\f$
+
+// \n \subsection matrix_operators_floor_ceil floor() / ceil()
+//
+// The \c floor() and \c ceil() functions can be used to round down/up each element of a matrix,
+// respectively:
+
+ \code
+ blaze::StaticMatrix<double,3UL,3UL> A, B;
+
+ B = floor( A ); // Rounding down each element of the matrix
+ B = ceil( A ); // Rounding up each element of the matrix
+ \endcode
+
+// \n \subsection matrix_operators_conj conj()
+//
+// The \c conj() function can be applied on a dense or sparse matrix to compute the complex
+// conjugate of each element of the matrix:
+
+ \code
+ using blaze::StaticMatrix;
+
+ typedef std::complex<double> cplx;
+
+ // Creating the matrix
+ // ( (1,0) (-2,-1) )
+ // ( (1,1) ( 0, 1) )
+ StaticMatrix<cplx,2UL,2UL> A{ { cplx( 1.0, 0.0 ), cplx( -2.0, -1.0 ) },
+ { cplx( 1.0, 1.0 ), cplx( 0.0, 1.0 ) } };
+
+ // Computing the matrix of conjugate values
+ // ( (1, 0) (-2, 1) )
+ // ( (1,-1) ( 0,-1) )
+ StaticMatrix<cplx,2UL,2UL> B;
+ B = conj( A );
+ \endcode
+
+// Additionally, matrices can be conjugated in-place via the \c conjugate() function:
+
+ \code
+ blaze::DynamicMatrix<cplx> C( 5UL, 2UL );
+
+ conjugate( C ); // In-place conjugate operation.
+ C = conj( C ); // Same as above
+ \endcode
+
+// \n \subsection matrix_operators_real real()
+//
+// The \c real() function can be used on a dense or sparse matrix to extract the real part of
+// each element of the matrix:
+
+ \code
+ using blaze::StaticMatrix;
+
+ typedef std::complex<double> cplx;
+
+ // Creating the matrix
+ // ( (1,0) (-2,-1) )
+ // ( (1,1) ( 0, 1) )
+ StaticMatrix<cplx,2UL,2UL> A{ { cplx( 1.0, 0.0 ), cplx( -2.0, -1.0 ) },
+ { cplx( 1.0, 1.0 ), cplx( 0.0, 1.0 ) } };
+
+ // Extracting the real part of each matrix element
+ // ( 1 -2 )
+ // ( 1 0 )
+ StaticMatrix<double,2UL,2UL> B;
+ B = real( A );
+ \endcode
+
+// \n \subsection matrix_operators_imag imag()
+//
+// The \c imag() function can be used on a dense or sparse matrix to extract the imaginary part
+// of each element of the matrix:
+
+ \code
+ using blaze::StaticMatrix;
+
+ typedef std::complex<double> cplx;
+
+ // Creating the matrix
+ // ( (1,0) (-2,-1) )
+ // ( (1,1) ( 0, 1) )
+ StaticMatrix<cplx,2UL,2UL> A{ { cplx( 1.0, 0.0 ), cplx( -2.0, -1.0 ) },
+ { cplx( 1.0, 1.0 ), cplx( 0.0, 1.0 ) } };
+
+ // Extracting the imaginary part of each matrix element
+ // ( 0 -1 )
+ // ( 1 1 )
+ StaticMatrix<double,2UL,2UL> B;
+ B = imag( A );
+ \endcode
+
+// \n \subsection matrix_operators_sqrt sqrt() / invsqrt()
+//
+// Via the \c sqrt() and \c invsqrt() functions the (inverse) square root of each element of a
+// matrix can be computed:
+
+ \code
+ blaze::StaticMatrix<double,3UL,3UL> A, B, C;
+
+ B = sqrt( A ); // Computes the square root of each element
+ C = invsqrt( A ); // Computes the inverse square root of each element
+ \endcode
+
+// Note that in case of sparse matrices only the non-zero elements are taken into account!
+//
+//
+// \n \subsection matrix_operators_cbrt cbrt() / invcbrt()
+//
+// The \c cbrt() and \c invcbrt() functions can be used to compute the the (inverse) cubic root
+// of each element of a matrix:
+
+ \code
+ blaze::DynamicMatrix<double> A, B, C;
+
+ B = cbrt( A ); // Computes the cubic root of each element
+ C = invcbrt( A ); // Computes the inverse cubic root of each element
+ \endcode
+
+// Note that in case of sparse matrices only the non-zero elements are taken into account!
+//
+//
+// \n \subsection matrix_operators_pow pow()
+//
+// The \c pow() function can be used to compute the exponential value of each element of a matrix:
+
+ \code
+ blaze::StaticMatrix<double,3UL,3UL> A, B;
+
+ B = pow( A, 1.2 ); // Computes the exponential value of each element
+ \endcode
+
+// \n \subsection matrix_operators_exp exp()
+//
+// \c exp() computes the base e exponential of each element of a matrix:
+
+ \code
+ blaze::HybridMatrix<double,3UL,3UL> A, B;
+
+ B = exp( A ); // Computes the base e exponential of each element
+ \endcode
+
+// Note that in case of sparse matrices only the non-zero elements are taken into account!
+//
+//
+// \n \subsection matrix_operators_log log() / log10()
+//
+// The \c log() and \c log10() functions can be used to compute the natural and common logarithm
+// of each element of a matrix:
+
+ \code
+ blaze::StaticMatrix<double,3UL,3UL> A, B;
+
+ B = log( A ); // Computes the natural logarithm of each element
+ B = log10( A ); // Computes the common logarithm of each element
+ \endcode
+
+// \n \subsection matrix_operators_trigonometric_functions sin() / cos() / tan() / asin() / acos() / atan()
+//
+// The following trigonometric functions are available for both dense and sparse matrices:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+
+ B = sin( A ); // Computes the sine of each element of the matrix
+ B = cos( A ); // Computes the cosine of each element of the matrix
+ B = tan( A ); // Computes the tangent of each element of the matrix
+
+ B = asin( A ); // Computes the inverse sine of each element of the matrix
+ B = acos( A ); // Computes the inverse cosine of each element of the matrix
+ B = atan( A ); // Computes the inverse tangent of each element of the matrix
+ \endcode
+
+// Note that in case of sparse matrices only the non-zero elements are taken into account!
+//
+//
+// \n \subsection matrix_operators_hyperbolic_functions sinh() / cosh() / tanh() / asinh() / acosh() / atanh()
+//
+// The following hyperbolic functions are available for both dense and sparse matrices:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+
+ B = sinh( A ); // Computes the hyperbolic sine of each element of the matrix
+ B = cosh( A ); // Computes the hyperbolic cosine of each element of the matrix
+ B = tanh( A ); // Computes the hyperbolic tangent of each element of the matrix
+
+ B = asinh( A ); // Computes the inverse hyperbolic sine of each element of the matrix
+ B = acosh( A ); // Computes the inverse hyperbolic cosine of each element of the matrix
+ B = atanh( A ); // Computes the inverse hyperbolic tangent of each element of the matrix
+ \endcode
+
+// \n \subsection matrix_operators_erf erf() / erfc()
+//
+// The \c erf() and \c erfc() functions compute the (complementary) error function of each
+// element of a matrix:
+
+ \code
+ blaze::StaticMatrix<double,3UL,3UL> A, B;
+
+ B = erf( A ); // Computes the error function of each element
+ B = erfc( A ); // Computes the complementary error function of each element
+ \endcode
+
+// Note that in case of sparse matrices only the non-zero elements are taken into account!
+//
+//
+// \n \subsection matrix_operations_foreach forEach()
+//
+// Via the \c forEach() function it is possible to execute custom operations on dense and sparse
+// matrices. For instance, the following example demonstrates a custom square root computation via
+// a lambda:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+
+ B = forEach( A, []( double d ) { return std::sqrt( d ); } );
+ \endcode
+
+// Although the computation can be parallelized it is not vectorized and thus cannot perform at
+// peak performance. However, it is also possible to create vectorized custom operations. See
+// \ref custom_operations for a detailed overview of the possibilities of custom operations.
+//
+//
+// \n \subsection matrix_operations_matrix_transpose trans()
+//
+// Matrices can be transposed via the \c trans() function. Row-major matrices are transposed into
+// a column-major matrix and vice versa:
+
+ \code
+ blaze::DynamicMatrix<int,rowMajor> M1( 5UL, 2UL );
+ blaze::CompressedMatrix<int,columnMajor> M2( 3UL, 7UL );
+
+ M1 = M2; // Assigning a column-major matrix to a row-major matrix
+ M1 = trans( M2 ); // Assigning the transpose of M2 (i.e. a row-major matrix) to M1
+ M1 += trans( M2 ); // Addition assignment of two row-major matrices
+ \endcode
+
+// Additionally, matrices can be transposed in-place via the \c transpose() function:
+
+ \code
+ blaze::DynamicMatrix<int,rowMajor> M( 5UL, 2UL );
+
+ transpose( M ); // In-place transpose operation.
+ M = trans( M ); // Same as above
+ \endcode
+
+// Note however that the transpose operation fails if ...
+//
+// - ... the given matrix has a fixed size and is non-square;
+// - ... the given matrix is a triangular matrix;
+// - ... the given submatrix affects the restricted parts of a triangular matrix;
+// - ... the given submatrix would cause non-deterministic results in a symmetric/Hermitian matrix.
+//
+//
+// \n \subsection matrix_operations_conjugate_transpose ctrans()
+//
+// The conjugate transpose of a dense or sparse matrix (also called adjoint matrix, Hermitian
+// conjugate, or transjugate) can be computed via the \c ctrans() function:
+
+ \code
+ blaze::DynamicMatrix< complex<float>, rowMajor > M1( 5UL, 2UL );
+ blaze::CompressedMatrix< complex<float>, columnMajor > M2( 2UL, 5UL );
+
+ M1 = ctrans( M2 ); // Compute the conjugate transpose matrix
+ \endcode
+
+// Note that the \c ctrans() function has the same effect as manually applying the \c conj() and
+// \c trans() function in any order:
+
+ \code
+ M1 = trans( conj( M2 ) ); // Computing the conjugate transpose matrix
+ M1 = conj( trans( M2 ) ); // Computing the conjugate transpose matrix
+ \endcode
+
+// The \c ctranspose() function can be used to perform an in-place conjugate transpose operation:
+
+ \code
+ blaze::DynamicMatrix<int,rowMajor> M( 5UL, 2UL );
+
+ ctranspose( M ); // In-place conjugate transpose operation.
+ M = ctrans( M ); // Same as above
+ \endcode
+
+// Note however that the conjugate transpose operation fails if ...
+//
+// - ... the given matrix has a fixed size and is non-square;
+// - ... the given matrix is a triangular matrix;
+// - ... the given submatrix affects the restricted parts of a triangular matrix;
+// - ... the given submatrix would cause non-deterministic results in a symmetric/Hermitian matrix.
+//
+//
+// \n \subsection matrix_operations_matrix_determinant det()
+//
+// The determinant of a square dense matrix can be computed by means of the \c det() function:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+ double d = det( A ); // Compute the determinant of A
+ \endcode
+
+// In case the given dense matrix is not a square matrix, a \c std::invalid_argument exception is
+// thrown.
+//
+// \note The \c det() function can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type or with a sparse matrix results in a compile time error!
+//
+// \note The function is depending on LAPACK kernels. Thus the function can only be used if the
+// fitting LAPACK library is available and linked to the executable. Otherwise a linker error
+// will be created.
+//
+//
+// \n \subsection matrix_operations_swap swap()
+//
+// Via the \c \c swap() function it is possible to completely swap the contents of two matrices
+// of the same type:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> M1( 10UL, 15UL );
+ blaze::DynamicMatrix<int,blaze::rowMajor> M2( 20UL, 10UL );
+
+ swap( M1, M2 ); // Swapping the contents of M1 and M2
+ \endcode
+
+// \n \section matrix_operations_matrix_inversion Matrix Inversion
+// <hr>
+//
+// The inverse of a square dense matrix can be computed via the \c inv() function:
+
+ \code
+ blaze::DynamicMatrix<float,blaze::rowMajor> A, B;
+ // ... Resizing and initialization
+ B = inv( A ); // Compute the inverse of A
+ \endcode
+
+// Alternatively, an in-place inversion of a dense matrix can be performed via the \c invert()
+// function:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+ invert( A ); // In-place matrix inversion
+ \endcode
+
+// Both the \c inv() and the \c invert() functions will automatically select the most suited matrix
+// inversion algorithm depending on the size and type of the given matrix. For small matrices of
+// up to 6x6, both functions use manually optimized kernels for maximum performance. For matrices
+// larger than 6x6 the inversion is performed by means of the most suited matrix decomposition
+// method: In case of a general or triangular matrix the LU decomposition is used, for symmetric
+// matrices the LDLT decomposition is applied and for Hermitian matrices the LDLH decomposition is
+// performed. However, via the \c invert() function it is possible to explicitly specify the matrix
+// inversion algorithm:
+
+ \code
+ using blaze::byLU;
+ using blaze::byLDLT;
+ using blaze::byLDLH;
+ using blaze::byLLH;
+
+ // In-place inversion with automatic selection of the inversion algorithm
+ invert( A );
+
+ // In-place inversion of a general matrix by means of an LU decomposition
+ invert<byLU>( A );
+
+ // In-place inversion of a symmetric indefinite matrix by means of a Bunch-Kaufman decomposition
+ invert<byLDLT>( A );
+
+ // In-place inversion of a Hermitian indefinite matrix by means of a Bunch-Kaufman decomposition
+ invert<byLDLH>( A );
+
+ // In-place inversion of a positive definite matrix by means of a Cholesky decomposition
+ invert<byLLH>( A );
+ \endcode
+
+// Whereas the inversion by means of an LU decomposition works for every general square matrix,
+// the inversion by LDLT only works for symmetric indefinite matrices, the inversion by LDLH is
+// restricted to Hermitian indefinite matrices and the Cholesky decomposition (LLH) only works
+// for Hermitian positive definite matrices. Please note that it is in the responsibility of the
+// function caller to guarantee that the selected algorithm is suited for the given matrix. In
+// case this precondition is violated the result can be wrong and might not represent the inverse
+// of the given matrix!
+//
+// For both the \c inv() and \c invert() function the matrix inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases either a compilation error is created if the failure can be predicted at
+// compile time or a \c std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type or with a sparse matrix results in a compile time error!
+//
+// \note The functions invert the dense matrix by means of LAPACK kernels. Thus the functions can
+// only be used if the fitting LAPACK library is available and linked to the executable. Otherwise
+// a linker error will be created.
+//
+// \note It is not possible to use any kind of view on the expression object returned by the
+// \c inv() function. Also, it is not possible to access individual elements via the function call
+// operator on the expression object:
+
+ \code
+ row( inv( A ), 2UL ); // Compilation error: Views cannot be used on an inv() expression!
+ inv( A )(1,2); // Compilation error: It is not possible to access individual elements!
+ \endcode
+
+// \note The inversion functions do not provide any exception safety guarantee, i.e. in case an
+// exception is thrown the matrix may already have been modified.
+//
+//
+// \n \section matrix_operations_decomposition Matrix Decomposition
+// <hr>
+//
+// \note All decomposition functions can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type or with a sparse matrix results in a compile time error!
+//
+// \note The functions decompose a dense matrix by means of LAPACK kernels. Thus the functions can
+// only be used if the fitting LAPACK library is available and linked to the executable. Otherwise
+// a linker error will be created.
+//
+// \subsection matrix_operations_decomposition_lu LU Decomposition
+//
+// The LU decomposition of a dense matrix can be computed via the \c lu() function:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::rowMajor> L, U, P;
+
+ lu( A, L, U, P ); // LU decomposition of a row-major matrix
+
+ assert( A == L * U * P );
+ \endcode
+
+ \code
+ blaze::DynamicMatrix<double,blaze::columnMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::columnMajor> L, U, P;
+
+ lu( A, L, U, P ); // LU decomposition of a column-major matrix
+
+ assert( A == P * L * U );
+ \endcode
+
+// The function works for both \c rowMajor and \c columnMajor matrices. Note, however, that the
+// three matrices \c A, \c L and \c U are required to have the same storage order. Also, please
+// note that the way the permutation matrix \c P needs to be applied differs between row-major and
+// column-major matrices, since the algorithm uses column interchanges for row-major matrices and
+// row interchanges for column-major matrices.
+//
+// Furthermore, \c lu() can be used with adaptors. For instance, the following example demonstrates
+// the LU decomposition of a symmetric matrix into a lower and upper triangular matrix:
+
+ \code
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > A;
+ // ... Resizing and initialization
+
+ blaze::LowerMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > L;
+ blaze::UpperMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > U;
+ blaze::DynamicMatrix<double,blaze::columnMajor> P;
+
+ lu( A, L, U, P ); // LU decomposition of A
+ \endcode
+
+// \n \subsection matrix_operations_decomposition_llh Cholesky Decomposition
+//
+// The Cholesky (LLH) decomposition of a dense matrix can be computed via the \c llh() function:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::rowMajor> L;
+
+ llh( A, L ); // LLH decomposition of a row-major matrix
+
+ assert( A == L * ctrans( L ) );
+ \endcode
+
+// The function works for both \c rowMajor and \c columnMajor matrices and the two matrices \c A
+// and \c L can have any storage order.
+//
+// Furthermore, \c llh() can be used with adaptors. For instance, the following example demonstrates
+// the LLH decomposition of a symmetric matrix into a lower triangular matrix:
+
+ \code
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > A;
+ // ... Resizing and initialization
+
+ blaze::LowerMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > L;
+
+ llh( A, L ); // Cholesky decomposition of A
+ \endcode
+
+// \n \subsection matrix_operations_decomposition_qr QR Decomposition
+//
+// The QR decomposition of a dense matrix can be computed via the \c qr() function:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::columnMajor> Q;
+ blaze::DynamicMatrix<double,blaze::rowMajor> R;
+
+ qr( A, Q, R ); // QR decomposition of a row-major matrix
+
+ assert( A == Q * R );
+ \endcode
+
+// The function works for both \c rowMajor and \c columnMajor matrices and the three matrices
+// \c A, \c Q and \c R can have any storage order.
+//
+// Furthermore, \c qr() can be used with adaptors. For instance, the following example demonstrates
+// the QR decomposition of a symmetric matrix into a general matrix and an upper triangular matrix:
+
+ \code
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::rowMajor> Q;
+ blaze::UpperMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > R;
+
+ qr( A, Q, R ); // QR decomposition of A
+ \endcode
+
+// \n \subsection matrix_operations_decomposition_rq RQ Decomposition
+//
+// Similar to the QR decomposition, the RQ decomposition of a dense matrix can be computed via
+// the \c rq() function:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::rowMajor> R;
+ blaze::DynamicMatrix<double,blaze::columnMajor> Q;
+
+ rq( A, R, Q ); // RQ decomposition of a row-major matrix
+
+ assert( A == R * Q );
+ \endcode
+
+// The function works for both \c rowMajor and \c columnMajor matrices and the three matrices
+// \c A, \c R and \c Q can have any storage order.
+//
+// Also the \c rq() function can be used in combination with matrix adaptors. For instance, the
+// following example demonstrates the RQ decomposition of an Hermitian matrix into a general
+// matrix and an upper triangular matrix:
+
+ \code
+ blaze::HermitianMatrix< blaze::DynamicMatrix<complex<double>,blaze::columnMajor> > A;
+ // ... Resizing and initialization
+
+ blaze::UpperMatrix< blaze::DynamicMatrix<complex<double>,blaze::columnMajor> > R;
+ blaze::DynamicMatrix<complex<double>,blaze::rowMajor> Q;
+
+ rq( A, R, Q ); // RQ decomposition of A
+ \endcode
+
+// \n \subsection matrix_operations_decomposition_ql QL Decomposition
+//
+// The QL decomposition of a dense matrix can be computed via the \c ql() function:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::rowMajor> Q;
+ blaze::DynamicMatrix<double,blaze::columnMajor> L;
+
+ ql( A, Q, L ); // QL decomposition of a row-major matrix
+
+ assert( A == Q * L );
+ \endcode
+
+// The function works for both \c rowMajor and \c columnMajor matrices and the three matrices
+// \c A, \c Q and \c L can have any storage order.
+//
+// Also the \c ql() function can be used in combination with matrix adaptors. For instance, the
+// following example demonstrates the QL decomposition of a symmetric matrix into a general
+// matrix and a lower triangular matrix:
+
+ \code
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::rowMajor> Q;
+ blaze::LowerMatrix< blaze::DynamicMatrix<double,blaze::columnMajor> > L;
+
+ ql( A, Q, L ); // QL decomposition of A
+ \endcode
+
+// \n \subsection matrix_operations_decomposition_lq LQ Decomposition
+//
+// The LQ decomposition of a dense matrix can be computed via the \c lq() function:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::rowMajor> L;
+ blaze::DynamicMatrix<double,blaze::columnMajor> Q;
+
+ lq( A, L, Q ); // LQ decomposition of a row-major matrix
+
+ assert( A == L * Q );
+ \endcode
+
+// The function works for both \c rowMajor and \c columnMajor matrices and the three matrices
+// \c A, \c L and \c Q can have any storage order.
+//
+// Furthermore, \c lq() can be used with adaptors. For instance, the following example demonstrates
+// the LQ decomposition of an Hermitian matrix into a lower triangular matrix and a general matrix:
+
+ \code
+ blaze::HermitianMatrix< blaze::DynamicMatrix<complex<double>,blaze::columnMajor> > A;
+ // ... Resizing and initialization
+
+ blaze::LowerMatrix< blaze::DynamicMatrix<complex<double>,blaze::columnMajor> > L;
+ blaze::DynamicMatrix<complex<double>,blaze::rowMajor> Q;
+
+ lq( A, L, Q ); // LQ decomposition of A
+ \endcode
+
+// \n Previous: \ref matrix_types &nbsp; &nbsp; Next: \ref adaptors
+*/
+//*************************************************************************************************
+
+
+//**Adaptors***************************************************************************************
+/*!\page adaptors Adaptors
+//
+// \tableofcontents
+//
+//
+// \section adaptors_general General Concepts
+// <hr>
+//
+// Adaptors act as wrappers around the general \ref matrix_types. They adapt the interface of the
+// matrices such that certain invariants are preserved. Due to this adaptors can provide a compile
+// time guarantee of certain properties, which can be exploited for optimized performance.
+//
+// The \b Blaze library provides a total of 9 different adaptors:
+//
+// <ul>
+// <li> \ref adaptors_symmetric_matrices </li>
+// <li> \ref adaptors_hermitian_matrices </li>
+// <li> \ref adaptors_triangular_matrices
+// <ul>
+// <li> \ref adaptors_triangular_matrices "Lower Triangular Matrices"
+// <ul>
+// <li> \ref adaptors_triangular_matrices_lowermatrix </li>
+// <li> \ref adaptors_triangular_matrices_unilowermatrix </li>
+// <li> \ref adaptors_triangular_matrices_strictlylowermatrix </li>
+// </ul>
+// </li>
+// <li> \ref adaptors_triangular_matrices "Upper Triangular Matrices"
+// <ul>
+// <li> \ref adaptors_triangular_matrices_uppermatrix </li>
+// <li> \ref adaptors_triangular_matrices_uniuppermatrix </li>
+// <li> \ref adaptors_triangular_matrices_strictlyuppermatrix </li>
+// </ul>
+// </li>
+// <li> \ref adaptors_triangular_matrices "Diagonal Matrices"
+// <ul>
+// <li> \ref adaptors_triangular_matrices_diagonalmatrix </li>
+// </ul>
+// </li>
+// </ul>
+// </li>
+// </ul>
+//
+// In combination with the general matrix types, \b Blaze provides a total of 40 different matrix
+// types that make it possible to exactly adapt the type of matrix to every specific problem.
+//
+//
+// \n \section adaptors_examples Examples
+// <hr>
+//
+// The following code examples give an impression on the use of adaptors. The first example shows
+// the multiplication between two lower matrices:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ LowerMatrix< DynamicMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// When multiplying two matrices, at least one of which is triangular, \b Blaze can exploit the
+// fact that either the lower or upper part of the matrix contains only default elements and
+// restrict the algorithm to the non-zero elements. Thus the adaptor provides a significant
+// performance advantage in comparison to a general matrix multiplication, especially for large
+// matrices.
+//
+// The second example shows the \c SymmetricMatrix adaptor in a row-major dense matrix/sparse
+// vector multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > A;
+ CompressedVector<double,columnVector> x;
+ DynamicVector<double,columnVector> y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example it is not intuitively apparent that using a row-major matrix is not the best
+// possible choice in terms of performance since the computation cannot be vectorized. Choosing
+// a column-major matrix instead, however, would enable a vectorized computation. Therefore
+// \b Blaze exploits the fact that \c A is symmetric, selects the best suited storage order and
+// evaluates the multiplication as
+
+ \code
+ y = trans( A ) * x;
+ \endcode
+
+// which significantly increases the performance.
+//
+// \n Previous: \ref matrix_operations &nbsp; &nbsp; Next: \ref adaptors_symmetric_matrices
+*/
+//*************************************************************************************************
+
+
+//**Symmetric Matrices*****************************************************************************
+/*!\page adaptors_symmetric_matrices Symmetric Matrices
+//
+// \tableofcontents
+//
+//
+// \n \section adaptors_symmetric_matrices_general Symmetric Matrices
+// <hr>
+//
+// In contrast to general matrices, which have no restriction in their number of rows and columns
+// and whose elements can have any value, symmetric matrices provide the compile time guarantee
+// to be square matrices with pair-wise identical values. Mathematically, this means that a
+// symmetric matrix is always equal to its transpose (\f$ A = A^T \f$) and that all non-diagonal
+// values have an identical counterpart (\f$ a_{ij} == a_{ji} \f$). This symmetry property can
+// be exploited to provide higher efficiency and/or lower memory consumption. Within the \b Blaze
+// library, symmetric matrices are realized by the \ref adaptors_symmetric_matrices_symmetricmatrix
+// class template.
+//
+//
+// \n \section adaptors_symmetric_matrices_symmetricmatrix SymmetricMatrix
+// <hr>
+//
+// The SymmetricMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \c MT and extends it
+// by enforcing the additional invariant of symmetry (i.e. the matrix is always equal to its
+// transpose \f$ A = A^T \f$). It can be included via the header file
+
+ \code
+ #include <blaze/math/SymmetricMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via template parameter:
+
+ \code
+ template< typename MT >
+ class SymmetricMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. SymmetricMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix type. Note
+// that the given matrix type must be either resizable (as for instance blaze::HybridMatrix or
+// blaze::DynamicMatrix) or must be square at compile time (as for instance blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible symmetric matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense symmetric matrix with static memory
+ blaze::SymmetricMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense symmetric matrix based on HybridMatrix
+ blaze::SymmetricMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense symmetric matrix based on DynamicMatrix
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed size row-major dense symmetric matrix based on CustomMatrix
+ blaze::SymmetricMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision symmetric matrix
+ blaze::SymmetricMatrix< blaze::CompressedMatrix<float,blaze::rowMajor> > E;
+ \endcode
+
+// The storage order of a symmetric matrix is depending on the storage order of the adapted matrix
+// type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified as
+// blaze::rowMajor), the symmetric matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the symmetric matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section adaptors_symmetric_matrices_special_properties Special Properties of Symmetric Matrices
+// <hr>
+//
+// A symmetric matrix is used exactly like a matrix of the underlying, adapted matrix type \c MT.
+// It also provides (nearly) the same interface as the underlying matrix type. However, there are
+// some important exceptions resulting from the symmetry constraint:
+//
+// -# <b>\ref adaptors_symmetric_matrices_square</b>
+// -# <b>\ref adaptors_symmetric_matrices_symmetry</b>
+// -# <b>\ref adaptors_symmetric_matrices_initialization</b>
+//
+// \n \subsection adaptors_symmetric_matrices_square Symmetric Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 symmetric dynamic matrix
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 symmetric static matrix
+ SymmetricMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ SymmetricMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection adaptors_symmetric_matrices_symmetry The Symmetric Property is Always Enforced!
+//
+// This means that modifying the element \f$ a_{ij} \f$ of a symmetric matrix also modifies its
+// counterpart element \f$ a_{ji} \f$. Also, it is only possible to assign matrices that are
+// symmetric themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, row-major 3x3 symmetric compressed matrix
+ SymmetricMatrix< CompressedMatrix<double,rowMajor> > A( 3 );
+
+ // Initializing three elements via the function call operator
+ A(0,0) = 1.0; // Initialization of the diagonal element (0,0)
+ A(0,2) = 2.0; // Initialization of the elements (0,2) and (2,0)
+
+ // Inserting three more elements via the insert() function
+ A.insert( 1, 1, 3.0 ); // Inserting the diagonal element (1,1)
+ A.insert( 1, 2, 4.0 ); // Inserting the elements (1,2) and (2,1)
+
+ // Access via a non-const iterator
+ *A.begin(1UL) = 10.0; // Modifies both elements (1,0) and (0,1)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 0, 2 ); // Erasing the elements (0,2) and (2,0)
+
+ // Construction from a symmetric dense matrix
+ StaticMatrix<double,3UL,3UL> B{ { 3.0, 8.0, -2.0 },
+ { 8.0, 0.0, -1.0 },
+ { -2.0, -1.0, 4.0 } };
+
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-symmetric dense matrix
+ StaticMatrix<double,3UL,3UL> D{ { 3.0, 7.0, -2.0 },
+ { 8.0, 0.0, -1.0 },
+ { -2.0, -1.0, 4.0 } };
+
+ C = D; // Throws an exception; symmetric invariant would be violated!
+ \endcode
+
+// The same restriction also applies to the \c append() function for sparse matrices: Appending
+// the element \f$ a_{ij} \f$ additionally inserts the element \f$ a_{ji} \f$ into the matrix.
+// Despite the additional insertion, the \c append() function still provides the most efficient
+// way to set up a symmetric sparse matrix. In order to achieve the maximum efficiency, the
+// capacity of the individual rows/columns of the matrix should to be specifically prepared with
+// \c reserve() calls:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+
+ // Setup of the symmetric matrix
+ //
+ // ( 0 1 3 )
+ // A = ( 1 2 0 )
+ // ( 3 0 0 )
+ //
+ SymmetricMatrix< CompressedMatrix<double,rowMajor> > A( 3 );
+
+ A.reserve( 5 ); // Reserving enough space for 5 non-zero elements
+ A.reserve( 0, 2 ); // Reserving two non-zero elements in the first row
+ A.reserve( 1, 2 ); // Reserving two non-zero elements in the second row
+ A.reserve( 2, 1 ); // Reserving a single non-zero element in the third row
+ A.append( 0, 1, 1.0 ); // Appending the value 1 at position (0,1) and (1,0)
+ A.append( 1, 1, 2.0 ); // Appending the value 2 at position (1,1)
+ A.append( 2, 0, 3.0 ); // Appending the value 3 at position (2,0) and (0,2)
+ \endcode
+
+// The symmetry property is also enforced for symmetric custom matrices: In case the given array
+// of elements does not represent a symmetric matrix, a \c std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef SymmetricMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomSymmetric;
+
+ // Creating a 3x3 symmetric custom matrix from a properly initialized array
+ double array[9] = { 1.0, 2.0, 4.0,
+ 2.0, 3.0, 5.0,
+ 4.0, 5.0, 6.0 };
+ CustomSymmetric A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 symmetric custom matrix from an uninitialized array
+ CustomSymmetric B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the symmetry property is enforced for views (rows, columns, submatrices, ...) on the
+// symmetric matrix. The following example demonstrates that modifying the elements of an entire
+// row of the symmetric matrix also affects the counterpart elements in the according column of
+// the matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Setup of the symmetric matrix
+ //
+ // ( 0 1 0 2 )
+ // A = ( 1 3 4 0 )
+ // ( 0 4 0 5 )
+ // ( 2 0 5 0 )
+ //
+ SymmetricMatrix< DynamicMatrix<int> > A( 4 );
+ A(0,1) = 1;
+ A(0,3) = 2;
+ A(1,1) = 3;
+ A(1,2) = 4;
+ A(2,3) = 5;
+
+ // Setting all elements in the 1st row to 0 results in the matrix
+ //
+ // ( 0 0 0 2 )
+ // A = ( 0 0 0 0 )
+ // ( 0 0 0 5 )
+ // ( 2 0 5 0 )
+ //
+ row( A, 1 ) = 0;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to submatrices of symmetric matrices.
+// Since the modification of element \f$ a_{ij} \f$ of a symmetric matrix also modifies the
+// element \f$ a_{ji} \f$, the matrix to be assigned must be structured such that the symmetry
+// of the symmetric matrix is preserved. Otherwise a \c std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Setup of two default 4x4 symmetric matrices
+ SymmetricMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 1 2 )
+ // B = ( 3 4 )
+ // ( 5 6 )
+ //
+ DynamicMatrix<int> B{ { 1, 2 }, { 3, 4 }, { 5, 6 } };
+
+ // OK: Assigning B to a submatrix of A1 such that the symmetry can be preserved
+ //
+ // ( 0 0 1 2 )
+ // A1 = ( 0 0 3 4 )
+ // ( 1 3 5 6 )
+ // ( 2 4 6 0 )
+ //
+ submatrix( A1, 0UL, 2UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the symmetry cannot be preserved!
+ // The elements marked with X cannot be assigned unambiguously!
+ //
+ // ( 0 1 2 0 )
+ // A2 = ( 1 3 X 0 )
+ // ( 2 X 6 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection adaptors_symmetric_matrices_initialization The Elements of a Dense Symmetric Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency (especially in case all default values are
+// overridden afterwards), this property is important since otherwise the symmetric property of
+// dense symmetric matrices could not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // Default initialized, 5x5 row-major symmetric dynamic matrix
+ SymmetricMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \section adaptors_symmetric_matrices_arithmetic_operations Arithmetic Operations
+// <hr>
+//
+// A SymmetricMatrix matrix can participate in numerical operations in any way any other dense
+// or sparse matrix can participate. It can also be combined with any other dense or sparse vector
+// or matrix. The following code example gives an impression of the use of SymmetricMatrix within
+// arithmetic operations:
+
+ \code
+ using blaze::SymmetricMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ CompressedMatrix<float> E( 3, 3 ); // Empty row-major sparse single precision 3x3 matrix
+
+ SymmetricMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > F;
+ SymmetricMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > G;
+
+ F = A + B; // Matrix addition and assignment to a row-major symmetric matrix
+ G = A - C; // Matrix subtraction and assignment to a column-major symmetric matrix
+ G = A * E; // Matrix multiplication between a dense and a sparse matrix
+
+ A *= 2.0; // In-place scaling of matrix A
+ F = 2.0 * B; // Scaling of matrix B
+ G = E * 2.0; // Scaling of matrix E
+
+ F += A - B; // Addition assignment
+ G -= A + C; // Subtraction assignment
+ G *= A * E; // Multiplication assignment
+ \endcode
+
+// \n \section adaptors_symmetric_matrices_block_structured Block-Structured Symmetric Matrices
+// <hr>
+//
+// It is also possible to use block-structured symmetric matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Definition of a 3x3 block-structured symmetric matrix based on CompressedMatrix
+ SymmetricMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > A( 3 );
+ \endcode
+
+// Also in this case, the SymmetricMatrix class template enforces the invariant of symmetry and
+// guarantees that a modifications of element \f$ a_{ij} \f$ of the adapted matrix is also
+// applied to element \f$ a_{ji} \f$:
+
+ \code
+ // Inserting the elements (2,4) and (4,2)
+ A.insert( 2, 4, StaticMatrix<int,3UL,3UL>{ { 1, -4, 5 },
+ { 6, 8, -3 },
+ { 2, -1, 2 } } );
+
+ // Manipulating the elements (2,4) and (4,2)
+ A(2,4)(1,1) = -5;
+ \endcode
+
+// \n \section adaptors_symmetric_matrices_performance Performance Considerations
+// <hr>
+//
+// When the symmetric property of a matrix is known beforehands using the SymmetricMatrix adaptor
+// instead of a general matrix can be a considerable performance advantage. The \b Blaze library
+// tries to exploit the properties of symmetric matrices whenever possible. However, there are
+// also situations when using a symmetric matrix introduces some overhead. The following examples
+// demonstrate several situations where symmetric matrices can positively or negatively impact
+// performance.
+//
+// \n \subsection adaptors_symmetric_matrices_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is symmetric, \b Blaze can exploit the fact
+// that \f$ A = A^T \f$ and choose the fastest and most suited combination of storage orders for the
+// multiplication. The following example demonstrates this by means of a dense matrix/sparse matrix
+// multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > A;
+ SymmetricMatrix< CompressedMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// Intuitively, the chosen combination of a row-major and a column-major matrix is the most suited
+// for maximum performance. However, \b Blaze evaluates the multiplication as
+
+ \code
+ C = A * trans( B );
+ \endcode
+
+// which significantly increases the performance since in contrast to the original formulation the
+// optimized form can be vectorized. Therefore, in the context of matrix multiplications, using the
+// SymmetricMatrix adapter is obviously an advantage.
+//
+// \n \subsection adaptors_symmetric_matrices_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar optimization is possible in case of matrix/vector multiplications:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > A;
+ CompressedVector<double,columnVector> x;
+ DynamicVector<double,columnVector> y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example it is not intuitively apparent that using a row-major matrix is not the best
+// possible choice in terms of performance since the computation cannot be vectorized. Choosing
+// a column-major matrix instead, however, would enable a vectorized computation. Therefore
+// \b Blaze exploits the fact that \c A is symmetric, selects the best suited storage order and
+// evaluates the multiplication as
+
+ \code
+ y = trans( A ) * x;
+ \endcode
+
+// which also significantly increases the performance.
+//
+// \n \subsection adaptors_symmetric_matrices_views Positive Impact: Row/Column Views on Column/Row-Major Matrices
+//
+// Another example is the optimization of a row view on a column-major symmetric matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::Row;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef SymmetricMatrix< DynamicMatrix<double,columnMajor> > DynamicSymmetric;
+
+ DynamicSymmetric A( 10UL );
+ Row<DynamicSymmetric> row5 = row( A, 5UL );
+ \endcode
+
+// Usually, a row view on a column-major matrix results in a considerable performance decrease in
+// comparison to a row view on a row-major matrix due to the non-contiguous storage of the matrix
+// elements. However, in case of symmetric matrices, \b Blaze instead uses the according column of
+// the matrix, which provides the same performance as if the matrix would be row-major. Note that
+// this also works for column views on row-major matrices, where \b Blaze can use the according
+// row instead of a column in order to provide maximum performance.
+//
+// \n \subsection adaptors_symmetric_matrices_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a symmetric matrix on the right-hand side of an assignment (i.e. for read
+// access), which introduces absolutely no performance penalty, using a symmetric matrix on the
+// left-hand side of an assignment (i.e. for write access) may introduce additional overhead when
+// it is assigned a general matrix, which is not symmetric at compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ SymmetricMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the symmetric matrix; no performance penalty
+ C = A; // Assignment of a symmetric matrix to another symmetric matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a symmetric matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not symmetric matrix to a symmetric matrix it is necessary
+// to check whether the matrix is symmetric at runtime in order to guarantee the symmetry property
+// of the symmetric matrix. In case it turns out to be symmetric, it is assigned as efficiently as
+// possible, if it is not, an exception is thrown. In order to prevent this runtime overhead it is
+// therefore generally advisable to assign symmetric matrices to other symmetric matrices.\n
+// In this context it is especially noteworthy that in contrast to additions and subtractions the
+// multiplication of two symmetric matrices does not necessarily result in another symmetric matrix:
+
+ \code
+ SymmetricMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a symmetric matrix; no runtime overhead
+ C = A - B; // Results in a symmetric matrix; no runtime overhead
+ C = A * B; // Is not guaranteed to result in a symmetric matrix; some runtime overhead
+ \endcode
+
+// \n Previous: \ref adaptors &nbsp; &nbsp; Next: \ref adaptors_hermitian_matrices
+*/
+//*************************************************************************************************
+
+
+//**Hermitian Matrices*****************************************************************************
+/*!\page adaptors_hermitian_matrices Hermitian Matrices
+//
+// \tableofcontents
+//
+//
+// \n \section adaptors_hermitian_matrices_general Hermitian Matrices
+// <hr>
+//
+// In addition to symmetric matrices, \b Blaze also provides an adaptor for Hermitian matrices.
+// Hermitian matrices provide the compile time guarantee to be square matrices with pair-wise
+// conjugate complex values. Mathematically, this means that an Hermitian matrix is always equal
+// to its conjugate transpose (\f$ A = \overline{A^T} \f$) and that all non-diagonal values have
+// a complex conjugate counterpart (\f$ a_{ij} == \overline{a_{ji}} \f$). Within the \b Blaze
+// library, Hermitian matrices are realized by the \ref adaptors_hermitian_matrices_hermitianmatrix
+// class template.
+//
+//
+// \n \section adaptors_hermitian_matrices_hermitianmatrix HermitianMatrix
+// <hr>
+//
+// The HermitianMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \c MT and extends it by
+// enforcing the additional invariant of Hermitian symmetry (i.e. the matrix is always equal to
+// its conjugate transpose \f$ A = \overline{A^T} \f$). It can be included via the header file
+
+ \code
+ #include <blaze/math/HermitianMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via template parameter:
+
+ \code
+ template< typename MT >
+ class HermitianMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. HermitianMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix type. Also,
+// the given matrix type must have numeric element types (i.e. all integral types except \c bool,
+// floating point and complex types). Note that the given matrix type must be either resizable (as
+// for instance blaze::HybridMatrix or blaze::DynamicMatrix) or must be square at compile time (as
+// for instance blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible Hermitian matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense Hermitian matrix with static memory
+ blaze::HermitianMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense Hermitian matrix based on HybridMatrix
+ blaze::HermitianMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense Hermitian matrix based on DynamicMatrix
+ blaze::HermitianMatrix< blaze::DynamicMatrix<std::complex<double>,rowMajor> > C;
+
+ // Definition of a fixed size row-major dense Hermitian matrix based on CustomMatrix
+ blaze::HermitianMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision complex Hermitian matrix
+ blaze::HermitianMatrix< blaze::CompressedMatrix<std::complex<float>,rowMajor> > E;
+ \endcode
+
+// The storage order of a Hermitian matrix is depending on the storage order of the adapted matrix
+// type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified as
+// blaze::rowMajor), the Hermitian matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the Hermitian matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section adaptors_hermitian_matrices_vs_symmetric_matrices Hermitian Matrices vs. Symmetric Matrices
+//
+// The blaze::HermitianMatrix adaptor and the blaze::SymmetricMatrix adaptor share several traits.
+// However, there are a couple of differences, both from a mathematical point of view as well as
+// from an implementation point of view.
+//
+// From a mathematical point of view, a matrix is called symmetric when it is equal to its
+// transpose (\f$ A = A^T \f$) and it is called Hermitian when it is equal to its conjugate
+// transpose (\f$ A = \overline{A^T} \f$). For matrices of real values, however, these two
+// conditions coincide, which means that symmetric matrices of real values are also Hermitian
+// and Hermitian matrices of real values are also symmetric.
+//
+// From an implementation point of view, \b Blaze restricts Hermitian matrices to numeric data
+// types (i.e. all integral types except \c bool, floating point and complex types), whereas
+// symmetric matrices can also be block structured (i.e. can have vector or matrix elements).
+// For built-in element types, the HermitianMatrix adaptor behaves exactly like the according
+// SymmetricMatrix implementation. For complex element types, however, the Hermitian property
+// is enforced (see also \ref adaptors_hermitian_matrices_hermitian).
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::HermitianMatrix;
+ using blaze::SymmetricMatrix;
+
+ // The following two matrices provide an identical experience (including performance)
+ HermitianMatrix< DynamicMatrix<double> > A; // Both Hermitian and symmetric
+ SymmetricMatrix< DynamicMatrix<double> > B; // Both Hermitian and symmetric
+
+ // The following two matrices will behave differently
+ HermitianMatrix< DynamicMatrix< complex<double> > > C; // Only Hermitian
+ SymmetricMatrix< DynamicMatrix< complex<double> > > D; // Only symmetric
+
+ // Block-structured Hermitian matrices are not allowed
+ HermitianMatrix< DynamicMatrix< DynamicVector<double> > > E; // Compilation error!
+ SymmetricMatrix< DynamicMatrix< DynamicVector<double> > > F; // Block-structured symmetric matrix
+ \endcode
+
+// \n \section adaptors_hermitian_matrices_special_properties Special Properties of Hermitian Matrices
+// <hr>
+//
+// A Hermitian matrix is used exactly like a matrix of the underlying, adapted matrix type \c MT.
+// It also provides (nearly) the same interface as the underlying matrix type. However, there are
+// some important exceptions resulting from the Hermitian symmetry constraint:
+//
+// -# <b>\ref adaptors_hermitian_matrices_square</b>
+// -# <b>\ref adaptors_hermitian_matrices_hermitian</b>
+// -# <b>\ref adaptors_hermitian_matrices_initialization</b>
+//
+// \n \subsection adaptors_hermitian_matrices_square Hermitian Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 Hermitian dynamic matrix
+ HermitianMatrix< DynamicMatrix<std::complex<double>,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 Hermitian static matrix
+ HermitianMatrix< StaticMatrix<std::complex<float>,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ HermitianMatrix< StaticMatrix<std::complex<float>,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection adaptors_hermitian_matrices_hermitian The Hermitian Property is Always Enforced!
+//
+// This means that the following properties of a Hermitian matrix are always guaranteed:
+//
+// - The diagonal elements are real numbers, i.e. the imaginary part is zero
+// - Element \f$ a_{ij} \f$ is always the complex conjugate of element \f$ a_{ji} \f$
+//
+// Thus modifying the element \f$ a_{ij} \f$ of a Hermitian matrix also modifies its
+// counterpart element \f$ a_{ji} \f$. Also, it is only possible to assign matrices that
+// are Hermitian themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+
+ typedef std::complex<double> cplx;
+
+ // Default constructed, row-major 3x3 Hermitian compressed matrix
+ HermitianMatrix< CompressedMatrix<cplx,rowMajor> > A( 3 );
+
+ // Initializing the matrix via the function call operator
+ //
+ // ( (1, 0) (0,0) (2,1) )
+ // ( (0, 0) (0,0) (0,0) )
+ // ( (2,-1) (0,0) (0,0) )
+ //
+ A(0,0) = cplx( 1.0, 0.0 ); // Initialization of the diagonal element (0,0)
+ A(0,2) = cplx( 2.0, 1.0 ); // Initialization of the elements (0,2) and (2,0)
+
+ // Inserting three more elements via the insert() function
+ //
+ // ( (1,-3) (0,0) (2, 1) )
+ // ( (0, 0) (2,0) (4,-2) )
+ // ( (2,-1) (4,2) (0, 0) )
+ //
+ A.insert( 1, 1, cplx( 2.0, 0.0 ) ); // Inserting the diagonal element (1,1)
+ A.insert( 1, 2, cplx( 4.0, -2.0 ) ); // Inserting the elements (1,2) and (2,1)
+
+ // Access via a non-const iterator
+ //
+ // ( (1,-3) (8,1) (2, 1) )
+ // ( (8,-1) (2,0) (4,-2) )
+ // ( (2,-1) (4,2) (0, 0) )
+ //
+ *A.begin(1UL) = cplx( 8.0, -1.0 ); // Modifies both elements (1,0) and (0,1)
+
+ // Erasing elements via the erase() function
+ //
+ // ( (0, 0) (8,1) (0, 0) )
+ // ( (8,-1) (2,0) (4,-2) )
+ // ( (0, 0) (4,2) (0, 0) )
+ //
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 0, 2 ); // Erasing the elements (0,2) and (2,0)
+
+ // Construction from a Hermitian dense matrix
+ StaticMatrix<cplx,3UL,3UL> B{ { cplx( 3.0, 0.0 ), cplx( 8.0, 2.0 ), cplx( -2.0, 2.0 ) },
+ { cplx( 8.0, 1.0 ), cplx( 0.0, 0.0 ), cplx( -1.0, -1.0 ) },
+ { cplx( -2.0, -2.0 ), cplx( -1.0, 1.0 ), cplx( 4.0, 0.0 ) } };
+
+ HermitianMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-Hermitian dense matrix
+ StaticMatrix<cplx,3UL,3UL> D{ { cplx( 3.0, 0.0 ), cplx( 7.0, 2.0 ), cplx( 3.0, 2.0 ) },
+ { cplx( 8.0, 1.0 ), cplx( 0.0, 0.0 ), cplx( 6.0, 4.0 ) },
+ { cplx( -2.0, 2.0 ), cplx( -1.0, 1.0 ), cplx( 4.0, 0.0 ) } };
+
+ C = D; // Throws an exception; Hermitian invariant would be violated!
+ \endcode
+
+// The same restriction also applies to the \c append() function for sparse matrices: Appending
+// the element \f$ a_{ij} \f$ additionally inserts the element \f$ a_{ji} \f$ into the matrix.
+// Despite the additional insertion, the \c append() function still provides the most efficient
+// way to set up a Hermitian sparse matrix. In order to achieve the maximum efficiency, the
+// capacity of the individual rows/columns of the matrix should to be specifically prepared with
+// \c reserve() calls:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+
+ typedef std::complex<double> cplx;
+
+ // Setup of the Hermitian matrix
+ //
+ // ( (0, 0) (1,2) (3,-4) )
+ // A = ( (1,-2) (2,0) (0, 0) )
+ // ( (3, 4) (0,0) (0, 0) )
+ //
+ HermitianMatrix< CompressedMatrix<cplx,rowMajor> > A( 3 );
+
+ A.reserve( 5 ); // Reserving enough space for 5 non-zero elements
+ A.reserve( 0, 2 ); // Reserving two non-zero elements in the first row
+ A.reserve( 1, 2 ); // Reserving two non-zero elements in the second row
+ A.reserve( 2, 1 ); // Reserving a single non-zero element in the third row
+
+ A.append( 0, 1, cplx( 1.0, 2.0 ) ); // Appending an element at position (0,1) and (1,0)
+ A.append( 1, 1, cplx( 2.0, 0.0 ) ); // Appending an element at position (1,1)
+ A.append( 2, 0, cplx( 3.0, 4.0 ) ); // Appending an element at position (2,0) and (0,2)
+ \endcode
+
+// The Hermitian property is also enforced for Hermitian custom matrices: In case the given array
+// of elements does not represent a Hermitian matrix, a \c std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef HermitianMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomHermitian;
+
+ // Creating a 3x3 Hermitian custom matrix from a properly initialized array
+ double array[9] = { 1.0, 2.0, 4.0,
+ 2.0, 3.0, 5.0,
+ 4.0, 5.0, 6.0 };
+ CustomHermitian A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 Hermitian custom matrix from an uninitialized array
+ CustomHermitian B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the Hermitian property is enforced for views (rows, columns, submatrices, ...) on the
+// Hermitian matrix. The following example demonstrates that modifying the elements of an entire
+// row of the Hermitian matrix also affects the counterpart elements in the according column of
+// the matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermtianMatrix;
+
+ typedef std::complex<double> cplx;
+
+ // Setup of the Hermitian matrix
+ //
+ // ( (0, 0) (1,-1) (0,0) (2, 1) )
+ // A = ( (1, 1) (3, 0) (4,2) (0, 0) )
+ // ( (0, 0) (4,-2) (0,0) (5,-3) )
+ // ( (2,-1) (0, 0) (5,3) (0, 0) )
+ //
+ HermitianMatrix< DynamicMatrix<int> > A( 4 );
+ A(0,1) = cplx( 1.0, -1.0 );
+ A(0,3) = cplx( 2.0, 1.0 );
+ A(1,1) = cplx( 3.0, 0.0 );
+ A(1,2) = cplx( 4.0, 2.0 );
+ A(2,3) = cplx( 5.0, 3.0 );
+
+ // Setting all elements in the 1st row to 0 results in the matrix
+ //
+ // ( (0, 0) (0,0) (0,0) (2, 1) )
+ // A = ( (0, 0) (0,0) (0,0) (0, 0) )
+ // ( (0, 0) (0,0) (0,0) (5,-3) )
+ // ( (2,-1) (0,0) (5,3) (0, 0) )
+ //
+ row( A, 1 ) = cplx( 0.0, 0.0 );
+ \endcode
+
+// The next example demonstrates the (compound) assignment to submatrices of Hermitian matrices.
+// Since the modification of element \f$ a_{ij} \f$ of a Hermitian matrix also modifies the
+// element \f$ a_{ji} \f$, the matrix to be assigned must be structured such that the Hermitian
+// symmetry of the matrix is preserved. Otherwise a \c std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+
+ std::complex<double> cplx;
+
+ // Setup of two default 4x4 Hermitian matrices
+ HermitianMatrix< DynamicMatrix<cplx> > A1( 4 ), A2( 4 );
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( (1,-1) (2, 5) )
+ // B = ( (3, 0) (4,-6) )
+ // ( (5, 0) (6, 0) )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL );
+ B(0,0) = cplx( 1.0, -1.0 );
+ B(0,1) = cplx( 2.0, 5.0 );
+ B(1,0) = cplx( 3.0, 0.0 );
+ B(1,1) = cplx( 4.0, -6.0 );
+ B(2,1) = cplx( 5.0, 0.0 );
+ B(2,2) = cplx( 6.0, 7.0 );
+
+ // OK: Assigning B to a submatrix of A1 such that the Hermitian property is preserved
+ //
+ // ( (0, 0) (0, 0) (1,-1) (2, 5) )
+ // A1 = ( (0, 0) (0, 0) (3, 0) (4,-6) )
+ // ( (1, 1) (3, 0) (5, 0) (6, 0) )
+ // ( (2,-5) (4, 6) (6, 0) (0, 0) )
+ //
+ submatrix( A1, 0UL, 2UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the Hermitian property isn't preserved!
+ // The elements marked with X cannot be assigned unambiguously!
+ //
+ // ( (0, 0) (1,-1) (2,5) (0,0) )
+ // A2 = ( (1, 1) (3, 0) (X,X) (0,0) )
+ // ( (2,-5) (X, X) (6,0) (0,0) )
+ // ( (0, 0) (0, 0) (0,0) (0,0) )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection adaptors_hermitian_matrices_initialization The Elements of a Dense Hermitian Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency (especially in case all default values are
+// overridden afterwards), this property is important since otherwise the Hermitian property of
+// dense Hermitian matrices could not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // Default initialized, 5x5 row-major Hermitian dynamic matrix
+ HermitianMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \section adaptors_hermitian_matrices_arithmetic_operations Arithmetic Operations
+// <hr>
+//
+// A HermitianMatrix can be used within all numerical operations in any way any other dense or
+// sparse matrix can be used. It can also be combined with any other dense or sparse vector or
+// matrix. The following code example gives an impression of the use of HermitianMatrix within
+// arithmetic operations:
+
+ \code
+ using blaze::HermitianMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef complex<float> cplx;
+
+ DynamicMatrix<cplx,rowMajor> A( 3, 3 );
+ CompressedMatrix<cplx,rowMajor> B( 3, 3 );
+
+ HermitianMatrix< DynamicMatrix<cplx,rowMajor> > C( 3 );
+ HermitianMatrix< CompressedMatrix<cplx,rowMajor> > D( 3 );
+
+ HermitianMatrix< HybridMatrix<cplx,3UL,3UL,rowMajor> > E;
+ HermitianMatrix< StaticMatrix<cplx,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major Hermitian matrix
+ F = C - D; // Matrix subtraction and assignment to a column-major Hermitian matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section adaptors_hermitian_matrices_performance Performance Considerations
+// <hr>
+//
+// When the Hermitian property of a matrix is known beforehands using the HermitianMatrix adaptor
+// instead of a general matrix can be a considerable performance advantage. This is particularly
+// true in case the Hermitian matrix is also symmetric (i.e. has built-in element types). The
+// \b Blaze library tries to exploit the properties of Hermitian (symmetric) matrices whenever
+// possible. However, there are also situations when using a Hermitian matrix introduces some
+// overhead. The following examples demonstrate several situations where Hermitian matrices can
+// positively or negatively impact performance.
+//
+// \n \subsection adaptors_hermitian_matrices_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is symmetric, \b Blaze can exploit the fact
+// that \f$ A = A^T \f$ and choose the fastest and most suited combination of storage orders for the
+// multiplication. The following example demonstrates this by means of a dense matrix/sparse matrix
+// multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ HermitianMatrix< DynamicMatrix<double,rowMajor> > A; // Both Hermitian and symmetric
+ HermitianMatrix< CompressedMatrix<double,columnMajor> > B; // Both Hermitian and symmetric
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// Intuitively, the chosen combination of a row-major and a column-major matrix is the most suited
+// for maximum performance. However, \b Blaze evaluates the multiplication as
+
+ \code
+ C = A * trans( B );
+ \endcode
+
+// which significantly increases the performance since in contrast to the original formulation the
+// optimized form can be vectorized. Therefore, in the context of matrix multiplications, using a
+// symmetric matrix is obviously an advantage.
+//
+// \n \subsection adaptors_hermitian_matrices_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar optimization is possible in case of matrix/vector multiplications:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ HermitianMatrix< DynamicMatrix<double,rowMajor> > A; // Hermitian and symmetric
+ CompressedVector<double,columnVector> x;
+ DynamicVector<double,columnVector> y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example it is not intuitively apparent that using a row-major matrix is not the best
+// possible choice in terms of performance since the computation cannot be vectorized. Choosing
+// a column-major matrix instead, however, would enable a vectorized computation. Therefore
+// \b Blaze exploits the fact that \c A is symmetric, selects the best suited storage order and
+// evaluates the multiplication as
+
+ \code
+ y = trans( A ) * x;
+ \endcode
+
+// which also significantly increases the performance.
+//
+// \n \subsection adaptors_hermitian_matrices_views Positive Impact: Row/Column Views on Column/Row-Major Matrices
+//
+// Another example is the optimization of a row view on a column-major symmetric matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::Row;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef HermitianMatrix< DynamicMatrix<double,columnMajor> > DynamicHermitian;
+
+ DynamicHermitian A( 10UL ); // Both Hermitian and symmetric
+ Row<DynamicHermitian> row5 = row( A, 5UL );
+ \endcode
+
+// Usually, a row view on a column-major matrix results in a considerable performance decrease in
+// comparison to a row view on a row-major matrix due to the non-contiguous storage of the matrix
+// elements. However, in case of symmetric matrices, \b Blaze instead uses the according column of
+// the matrix, which provides the same performance as if the matrix would be row-major. Note that
+// this also works for column views on row-major matrices, where \b Blaze can use the according
+// row instead of a column in order to provide maximum performance.
+//
+// \n \subsection adaptors_hermitian_matrices_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a Hermitian matrix on the right-hand side of an assignment (i.e. for read
+// access), which introduces absolutely no performance penalty, using a Hermitian matrix on the
+// left-hand side of an assignment (i.e. for write access) may introduce additional overhead when
+// it is assigned a general matrix, which is not Hermitian at compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+
+ HermitianMatrix< DynamicMatrix< complex<double> > > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the Hermitian matrix; no performance penalty
+ C = A; // Assignment of a Hermitian matrix to another Hermitian matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a Hermitian matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not Hermitian matrix to a Hermitian matrix it is necessary
+// to check whether the matrix is Hermitian at runtime in order to guarantee the Hermitian property
+// of the Hermitian matrix. In case it turns out to be Hermitian, it is assigned as efficiently as
+// possible, if it is not, an exception is thrown. In order to prevent this runtime overhead it is
+// therefore generally advisable to assign Hermitian matrices to other Hermitian matrices.\n
+// In this context it is especially noteworthy that in contrast to additions and subtractions the
+// multiplication of two Hermitian matrices does not necessarily result in another Hermitian matrix:
+
+ \code
+ HermitianMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a Hermitian matrix; no runtime overhead
+ C = A - B; // Results in a Hermitian matrix; no runtime overhead
+ C = A * B; // Is not guaranteed to result in a Hermitian matrix; some runtime overhead
+ \endcode
+
+// \n Previous: \ref adaptors_symmetric_matrices &nbsp; &nbsp; Next: \ref adaptors_triangular_matrices
+*/
+//*************************************************************************************************
+
+
+//**Triangular Matrices****************************************************************************
+/*!\page adaptors_triangular_matrices Triangular Matrices
+//
+// \tableofcontents
+//
+//
+// \n \section adaptors_triangular_matrices_general Triangular Matrices
+// <hr>
+//
+// Triangular matrices come in three flavors: Lower triangular matrices provide the compile time
+// guarantee to be square matrices and that the upper part of the matrix contains only default
+// elements that cannot be modified. Upper triangular matrices on the other hand provide the
+// compile time guarantee to be square and that the lower part of the matrix contains only fixed
+// default elements. Finally, diagonal matrices provide the compile time guarantee to be square
+// and that both the lower and upper part of the matrix contain only immutable default elements.
+// These properties can be exploited to gain higher performance and/or to save memory. Within the
+// \b Blaze library, several kinds of lower and upper triangular and diagonal matrices are realized
+// by the following class templates:
+//
+// Lower triangular matrices:
+// - <b>\ref adaptors_triangular_matrices_lowermatrix</b>
+// - <b>\ref adaptors_triangular_matrices_unilowermatrix</b>
+// - <b>\ref adaptors_triangular_matrices_strictlylowermatrix</b>
+//
+// Upper triangular matrices:
+// - <b>\ref adaptors_triangular_matrices_uppermatrix</b>
+// - <b>\ref adaptors_triangular_matrices_uniuppermatrix</b>
+// - <b>\ref adaptors_triangular_matrices_strictlyuppermatrix</b>
+//
+// Diagonal matrices
+// - <b>\ref adaptors_triangular_matrices_diagonalmatrix</b>
+//
+//
+// \n \section adaptors_triangular_matrices_lowermatrix LowerMatrix
+// <hr>
+//
+// The blaze::LowerMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \c MT and extends it by
+// enforcing the additional invariant that all matrix elements above the diagonal are 0 (lower
+// triangular matrix):
+
+ \f[\left(\begin{array}{*{5}{c}}
+ l_{0,0} & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & l_{1,1} & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & l_{2,2} & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & l_{N,N} \\
+ \end{array}\right).\f]
+
+// It can be included via the header file
+
+ \code
+ #include <blaze/math/LowerMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT >
+ class LowerMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. blaze::LowerMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix type. Note
+// that the given matrix type must be either resizable (as for instance blaze::HybridMatrix or
+// blaze::DynamicMatrix) or must be square at compile time (as for instance blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible lower matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense lower matrix with static memory
+ blaze::LowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense lower matrix based on HybridMatrix
+ blaze::LowerMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense lower matrix based on DynamicMatrix
+ blaze::LowerMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed size row-major dense lower matrix based on CustomMatrix
+ blaze::LowerMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision lower matrix
+ blaze::LowerMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of a lower matrix is depending on the storage order of the adapted matrix
+// type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified
+// as blaze::rowMajor), the lower matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the lower matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section adaptors_triangular_matrices_unilowermatrix UniLowerMatrix
+// <hr>
+//
+// The blaze::UniLowerMatrix class template is an adapter for existing dense and sparse matrix
+// types. It inherits the properties and the interface of the given matrix type \c MT and extends
+// it by enforcing the additional invariant that all diagonal matrix elements are 1 and all matrix
+// elements above the diagonal are 0 (lower unitriangular matrix):
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & 1 & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & 1 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & 1 \\
+ \end{array}\right).\f]
+
+// It can be included via the header file
+
+ \code
+ #include <blaze/math/UniLowerMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT >
+ class UniLowerMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. blaze::UniLowerMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix type. Also,
+// the given matrix type must have numeric element types (i.e. all integral types except \c bool,
+// floating point and complex types). Note that the given matrix type must be either resizable (as
+// for instance blaze::HybridMatrix or blaze::DynamicMatrix) or must be square at compile time (as
+// for instance blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible lower unitriangular matrices:
+
+ \code
+ // Definition of a 3x3 row-major dense unilower matrix with static memory
+ blaze::UniLowerMatrix< blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> > A;
+
+ // Definition of a resizable column-major dense unilower matrix based on HybridMatrix
+ blaze::UniLowerMatrix< blaze::HybridMatrix<float,4UL,4UL,blaze::columnMajor> B;
+
+ // Definition of a resizable row-major dense unilower matrix based on DynamicMatrix
+ blaze::UniLowerMatrix< blaze::DynamicMatrix<double,blaze::rowMajor> > C;
+
+ // Definition of a compressed row-major single precision unilower matrix
+ blaze::UniLowerMatrix< blaze::CompressedMatrix<float,blaze::rowMajor> > D;
+ \endcode
+
+// The storage order of a lower unitriangular matrix is depending on the storage order of the
+// adapted matrix type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e.
+// is specified as blaze::rowMajor), the unilower matrix will also be a row-major matrix.
+// Otherwise if the adapted matrix is column-major (i.e. is specified as blaze::columnMajor),
+// the unilower matrix will also be a column-major matrix.
+//
+//
+// \n \section adaptors_triangular_matrices_strictlylowermatrix StrictlyLowerMatrix
+// <hr>
+//
+// The blaze::StrictlyLowerMatrix class template is an adapter for existing dense and sparse matrix
+// types. It inherits the properties and the interface of the given matrix type \c MT and extends
+// it by enforcing the additional invariant that all diagonal matrix elements and all matrix
+// elements above the diagonal are 0 (strictly lower triangular matrix):
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & 0 & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & 0 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & 0 \\
+ \end{array}\right).\f]
+
+// It can be included via the header file
+
+ \code
+ #include <blaze/math/StrictlyLowerMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT >
+ class StrictlyLowerMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. blaze::StrictlyLowerMatrix can be used
+// with any non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Note that the given matrix type must be either resizable (as for instance
+// blaze::HybridMatrix or blaze::DynamicMatrix) or must be square at compile time (as for instance
+// blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible strictly lower triangular matrices:
+
+ \code
+ // Definition of a 3x3 row-major dense strictly lower matrix with static memory
+ blaze::StrictlyLowerMatrix< blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> > A;
+
+ // Definition of a resizable column-major dense strictly lower matrix based on HybridMatrix
+ blaze::StrictlyLowerMatrix< blaze::HybridMatrix<float,4UL,4UL,blaze::columnMajor> B;
+
+ // Definition of a resizable row-major dense strictly lower matrix based on DynamicMatrix
+ blaze::StrictlyLowerMatrix< blaze::DynamicMatrix<double,blaze::rowMajor> > C;
+
+ // Definition of a compressed row-major single precision strictly lower matrix
+ blaze::StrictlyLowerMatrix< blaze::CompressedMatrix<float,blaze::rowMajor> > D;
+ \endcode
+
+// The storage order of a strictly lower triangular matrix is depending on the storage order of
+// the adapted matrix type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e.
+// is specified as blaze::rowMajor), the strictly lower matrix will also be a row-major matrix.
+// Otherwise if the adapted matrix is column-major (i.e. is specified as blaze::columnMajor),
+// the strictly lower matrix will also be a column-major matrix.
+//
+//
+// \n \section adaptors_triangular_matrices_uppermatrix UpperMatrix
+// <hr>
+//
+// The blaze::UpperMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \c MT and extends it by
+// enforcing the additional invariant that all matrix elements below the diagonal are 0 (upper
+// triangular matrix):
+
+ \f[\left(\begin{array}{*{5}{c}}
+ u_{0,0} & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & u_{1,1} & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & u_{2,2} & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & u_{N,N} \\
+ \end{array}\right).\f]
+
+// It can be included via the header file
+
+ \code
+ #include <blaze/math/UpperMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT >
+ class UpperMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. blaze::UpperMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix type. Note
+// that the given matrix type must be either resizable (as for instance blaze::HybridMatrix or
+// blaze::DynamicMatrix) or must be square at compile time (as for instance blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible upper matrices:
+
+ \code
+ // Definition of a 3x3 row-major dense upper matrix with static memory
+ blaze::UpperMatrix< blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> > A;
+
+ // Definition of a resizable column-major dense upper matrix based on HybridMatrix
+ blaze::UpperMatrix< blaze::HybridMatrix<float,4UL,4UL,blaze::columnMajor> B;
+
+ // Definition of a resizable row-major dense upper matrix based on DynamicMatrix
+ blaze::UpperMatrix< blaze::DynamicMatrix<double,blaze::rowMajor> > C;
+
+ // Definition of a compressed row-major single precision upper matrix
+ blaze::UpperMatrix< blaze::CompressedMatrix<float,blaze::rowMajor> > D;
+ \endcode
+
+// The storage order of an upper matrix is depending on the storage order of the adapted matrix
+// type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified
+// as blaze::rowMajor), the upper matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the upper matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section adaptors_triangular_matrices_uniuppermatrix UniUpperMatrix
+// <hr>
+//
+// The blaze::UniUpperMatrix class template is an adapter for existing dense and sparse matrix
+// types. It inherits the properties and the interface of the given matrix type \c MT and extends
+// it by enforcing the additional invariant that all diagonal matrix elements are 1 and all matrix
+// elements below the diagonal are 0 (upper unitriangular matrix):
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & 1 & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & 1 & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & 1 \\
+ \end{array}\right).\f]
+
+// It can be included via the header file
+
+ \code
+ #include <blaze/math/UniUpperMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT >
+ class UniUpperMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. blaze::UniUpperMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix type. Also,
+// the given matrix type must have numeric element types (i.e. all integral types except \c bool,
+// floating point and complex types). Note that the given matrix type must be either resizable (as
+// for instance blaze::HybridMatrix or blaze::DynamicMatrix) or must be square at compile time (as
+// for instance blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible upper unitriangular matrices:
+
+ \code
+ // Definition of a 3x3 row-major dense uniupper matrix with static memory
+ blaze::UniUpperMatrix< blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> > A;
+
+ // Definition of a resizable column-major dense uniupper matrix based on HybridMatrix
+ blaze::UniUpperMatrix< blaze::HybridMatrix<float,4UL,4UL,blaze::columnMajor> B;
+
+ // Definition of a resizable row-major dense uniupper matrix based on DynamicMatrix
+ blaze::UniUpperMatrix< blaze::DynamicMatrix<double,blaze::rowMajor> > C;
+
+ // Definition of a compressed row-major single precision uniupper matrix
+ blaze::UniUpperMatrix< blaze::CompressedMatrix<float,blaze::rowMajor> > D;
+ \endcode
+
+// The storage order of an upper unitriangular matrix is depending on the storage order of the
+// adapted matrix type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e.
+// is specified as blaze::rowMajor), the uniupper matrix will also be a row-major matrix.
+// Otherwise, if the adapted matrix is column-major (i.e. is specified as blaze::columnMajor),
+// the uniupper matrix will also be a column-major matrix.
+//
+//
+// \n \section adaptors_triangular_matrices_strictlyuppermatrix StrictlyUpperMatrix
+// <hr>
+//
+// The blaze::StrictlyUpperMatrix class template is an adapter for existing dense and sparse matrix
+// types. It inherits the properties and the interface of the given matrix type \c MT and extends
+// it by enforcing the additional invariant that all diagonal matrix elements and all matrix
+// elements below the diagonal are 0 (strictly upper triangular matrix):
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & 0 & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & 0 & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & 0 \\
+ \end{array}\right).\f]
+
+// It can be included via the header file
+
+ \code
+ #include <blaze/math/StrictlyUpperMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT >
+ class StrictlyUpperMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. blaze::StrictlyUpperMatrix can be used
+// with any non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Note that the given matrix type must be either resizable (as for instance
+// blaze::HybridMatrix or blaze::DynamicMatrix) or must be square at compile time (as for instance
+// blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible strictly upper triangular matrices:
+
+ \code
+ // Definition of a 3x3 row-major dense strictly upper matrix with static memory
+ blaze::StrictlyUpperMatrix< blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> > A;
+
+ // Definition of a resizable column-major dense strictly upper matrix based on HybridMatrix
+ blaze::StrictlyUpperMatrix< blaze::HybridMatrix<float,4UL,4UL,blaze::columnMajor> B;
+
+ // Definition of a resizable row-major dense strictly upper matrix based on DynamicMatrix
+ blaze::StrictlyUpperMatrix< blaze::DynamicMatrix<double,blaze::rowMajor> > C;
+
+ // Definition of a compressed row-major single precision strictly upper matrix
+ blaze::StrictlyUpperMatrix< blaze::CompressedMatrix<float,blaze::rowMajor> > D;
+ \endcode
+
+// The storage order of a strictly upper triangular matrix is depending on the storage order of
+// the adapted matrix type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e.
+// is specified as blaze::rowMajor), the strictly upper matrix will also be a row-major matrix.
+// Otherwise, if the adapted matrix is column-major (i.e. is specified as blaze::columnMajor),
+// the strictly upper matrix will also be a column-major matrix.
+//
+//
+// \n \section adaptors_triangular_matrices_diagonalmatrix DiagonalMatrix
+// <hr>
+//
+// The blaze::DiagonalMatrix class template is an adapter for existing dense and sparse matrix
+// types. It inherits the properties and the interface of the given matrix type \c MT and extends
+// it by enforcing the additional invariant that all matrix elements above and below the diagonal
+// are 0 (diagonal matrix):
+
+ \f[\left(\begin{array}{*{5}{c}}
+ l_{0,0} & 0 & 0 & \cdots & 0 \\
+ 0 & l_{1,1} & 0 & \cdots & 0 \\
+ 0 & 0 & l_{2,2} & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & l_{N,N} \\
+ \end{array}\right).\f]
+
+// It can be included via the header file
+
+ \code
+ #include <blaze/math/DiagonalMatrix.h>
+ \endcode
+
+// The type of the adapted matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT >
+ class DiagonalMatrix;
+ \endcode
+
+// \c MT specifies the type of the matrix to be adapted. blaze::DiagonalMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix type. Note
+// that the given matrix type must be either resizable (as for instance blaze::HybridMatrix or
+// blaze::DynamicMatrix) or must be square at compile time (as for instance blaze::StaticMatrix).
+//
+// The following examples give an impression of several possible diagonal matrices:
+
+ \code
+ // Definition of a 3x3 row-major dense diagonal matrix with static memory
+ blaze::DiagonalMatrix< blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> > A;
+
+ // Definition of a resizable column-major dense diagonal matrix based on HybridMatrix
+ blaze::DiagonalMatrix< blaze::HybridMatrix<float,4UL,4UL,blaze::columnMajor> B;
+
+ // Definition of a resizable row-major dense diagonal matrix based on DynamicMatrix
+ blaze::DiagonalMatrix< blaze::DynamicMatrix<double,blaze::rowMajor> > C;
+
+ // Definition of a compressed row-major single precision diagonal matrix
+ blaze::DiagonalMatrix< blaze::CompressedMatrix<float,blaze::rowMajor> > D;
+ \endcode
+
+// The storage order of a diagonal matrix is depending on the storage order of the adapted matrix
+// type \c MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified
+// as blaze::rowMajor), the diagonal matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the diagonal matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section adaptors_triangular_matrices_special_properties Special Properties of Triangular Matrices
+// <hr>
+//
+// A triangular matrix is used exactly like a matrix of the underlying, adapted matrix type \c MT.
+// It also provides (nearly) the same interface as the underlying matrix type. However, there are
+// some important exceptions resulting from the triangular matrix constraint:
+//
+// -# <b>\ref adaptors_triangular_matrices_square</b>
+// -# <b>\ref adaptors_triangular_matrices_triangular</b>
+// -# <b>\ref adaptors_triangular_matrices_initialization</b>
+// -# <b>\ref adaptors_triangular_matrices_storage</b>
+// -# <b>\ref adaptors_triangular_matrices_scaling</b>
+//
+// \n \subsection adaptors_triangular_matrices_square Triangular Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 lower dynamic matrix
+ LowerMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::LowerMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 lower static matrix
+ LowerMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ LowerMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection adaptors_triangular_matrices_triangular The Triangular Property is Always Enforced!
+//
+// This means that it is only allowed to modify elements in the lower part or the diagonal of
+// a lower triangular matrix and in the upper part or the diagonal of an upper triangular matrix.
+// Unitriangular and strictly triangular matrices are even more restrictive and don't allow the
+// modification of diagonal elements. Also, triangular matrices can only be assigned matrices that
+// don't violate their triangular property. The following example demonstrates this restriction
+// by means of the blaze::LowerMatrix adaptor. For examples with other triangular matrix types
+// see the according class documentations.
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+
+ typedef LowerMatrix< CompressedMatrix<double,rowMajor> > CompressedLower;
+
+ // Default constructed, row-major 3x3 lower compressed matrix
+ CompressedLower A( 3 );
+
+ // Initializing elements via the function call operator
+ A(0,0) = 1.0; // Initialization of the diagonal element (0,0)
+ A(2,0) = 2.0; // Initialization of the lower element (2,0)
+ A(1,2) = 9.0; // Throws an exception; invalid modification of upper element
+
+ // Inserting two more elements via the insert() function
+ A.insert( 1, 0, 3.0 ); // Inserting the lower element (1,0)
+ A.insert( 2, 1, 4.0 ); // Inserting the lower element (2,1)
+ A.insert( 0, 2, 9.0 ); // Throws an exception; invalid insertion of upper element
+
+ // Appending an element via the append() function
+ A.reserve( 1, 3 ); // Reserving enough capacity in row 1
+ A.append( 1, 1, 5.0 ); // Appending the diagonal element (1,1)
+ A.append( 1, 2, 9.0 ); // Throws an exception; appending an element in the upper part
+
+ // Access via a non-const iterator
+ CompressedLower::Iterator it = A.begin(1);
+ *it = 6.0; // Modifies the lower element (1,0)
+ ++it;
+ *it = 9.0; // Modifies the diagonal element (1,1)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 2, 0 ); // Erasing the lower element (2,0)
+
+ // Construction from a lower dense matrix
+ StaticMatrix<double,3UL,3UL> B{ { 3.0, 0.0, 0.0 },
+ { 8.0, 0.0, 0.0 },
+ { -2.0, -1.0, 4.0 } };
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-lower dense matrix
+ StaticMatrix<double,3UL,3UL> D{ { 3.0, 0.0, -2.0 },
+ { 8.0, 0.0, 0.0 },
+ { -2.0, -1.0, 4.0 } };
+
+ C = D; // Throws an exception; lower matrix invariant would be violated!
+ \endcode
+
+// The triangular property is also enforced during the construction of triangular custom matrices:
+// In case the given array of elements does not represent the according triangular matrix type, a
+// \c std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::LowerMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef LowerMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomLower;
+
+ // Creating a 3x3 lower custom matrix from a properly initialized array
+ double array[9] = { 1.0, 0.0, 0.0,
+ 2.0, 3.0, 0.0,
+ 4.0, 5.0, 6.0 };
+ CustomLower A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 lower custom matrix from an uninitialized array
+ CustomLower B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the triangular matrix property is enforced for views (rows, columns, submatrices, ...)
+// on the triangular matrix. The following example demonstrates that modifying the elements of an
+// entire row and submatrix of a lower matrix only affects the lower and diagonal matrix elements.
+// Again, this example uses blaze::LowerMatrix, for examples with other triangular matrix types
+// see the according class documentations.
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+
+ // Setup of the lower matrix
+ //
+ // ( 0 0 0 0 )
+ // A = ( 1 2 0 0 )
+ // ( 0 3 0 0 )
+ // ( 4 0 5 0 )
+ //
+ LowerMatrix< DynamicMatrix<int> > A( 4 );
+ A(1,0) = 1;
+ A(1,1) = 2;
+ A(2,1) = 3;
+ A(3,0) = 4;
+ A(3,2) = 5;
+
+ // Setting the lower and diagonal elements in the 2nd row to 9 results in the matrix
+ //
+ // ( 0 0 0 0 )
+ // A = ( 1 2 0 0 )
+ // ( 9 9 9 0 )
+ // ( 4 0 5 0 )
+ //
+ row( A, 2 ) = 9;
+
+ // Setting the lower and diagonal elements in the 1st and 2nd column to 7 results in
+ //
+ // ( 0 0 0 0 )
+ // A = ( 1 7 0 0 )
+ // ( 9 7 7 0 )
+ // ( 4 7 7 0 )
+ //
+ submatrix( A, 0, 1, 4, 2 ) = 7;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to rows/columns and submatrices of
+// triangular matrices. Since only lower/upper and potentially diagonal elements may be modified
+// the matrix to be assigned must be structured such that the triangular matrix invariant of the
+// matrix is preserved. Otherwise a \c std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::LowerMatrix;
+ using blaze::rowVector;
+
+ // Setup of two default 4x4 lower matrices
+ LowerMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of a 4-dimensional vector
+ //
+ // v = ( 1 2 3 0 )
+ //
+ DynamicVector<int,rowVector> v{ 1, 2, 3, 0 };
+
+ // OK: Assigning v to the 2nd row of A1 preserves the lower matrix invariant
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 0 0 0 )
+ // ( 1 2 3 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 2 ) = v; // OK
+
+ // Error: Assigning v to the 1st row of A1 violates the lower matrix invariant! The element
+ // marked with X cannot be assigned and triggers an exception.
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 1 2 X 0 )
+ // ( 1 2 3 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 1 ) = v; // Assignment throws an exception!
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 0 0 )
+ // B = ( 7 0 )
+ // ( 8 9 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL, 0 );
+ B(1,0) = 7;
+ B(2,0) = 8;
+ B(2,1) = 9;
+
+ // OK: Assigning B to a submatrix of A2 such that the lower matrix invariant can be preserved
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 7 0 0 )
+ // ( 0 8 9 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the lower matrix invariant cannot be
+ // preserved! The elements marked with X cannot be assigned without violating the invariant!
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 7 X 0 )
+ // ( 0 8 8 X )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 2UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection adaptors_triangular_matrices_initialization The Elements of a Dense Triangular Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency during the creation of a dense lower or
+// upper matrix this initialization is important since otherwise the lower/upper matrix property
+// of dense lower matrices would not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+ using blaze::UpperMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // 5x5 row-major lower dynamic matrix with default initialized upper matrix
+ LowerMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+
+ // 7x7 column-major upper dynamic matrix with default initialized lower matrix
+ UpperMatrix< DynamicMatrix<int,columnMajor> > C( 7 );
+
+ // 3x3 row-major diagonal dynamic matrix with default initialized lower and upper matrix
+ DiagonalMatrix< DynamicMatrix<int,rowMajor> > D( 3 );
+ \endcode
+
+// \n \subsection adaptors_triangular_matrices_storage Dense Triangular Matrices Store All Elements!
+//
+// All dense triangular matrices store all \f$ N \times N \f$ elements, including the immutable
+// elements in the lower or upper part, respectively. Therefore dense triangular matrices don't
+// provide any kind of memory reduction! There are two main reasons for this: First, storing also
+// the zero elements guarantees maximum performance for many algorithms that perform vectorized
+// operations on the triangular matrices, which is especially true for small dense matrices.
+// Second, conceptually all triangular adaptors merely restrict the interface to the matrix type
+// \c MT and do not change the data layout or the underlying matrix type.
+//
+// This property matters most for diagonal matrices. In order to achieve the perfect combination
+// of performance and memory consumption for a diagonal matrix it is recommended to use dense
+// matrices for small diagonal matrices and sparse matrices for large diagonal matrices:
+
+ \code
+ // Recommendation 1: use dense matrices for small diagonal matrices
+ typedef blaze::DiagonalMatrix< blaze::StaticMatrix<float,3UL,3UL> > SmallDiagonalMatrix;
+
+ // Recommendation 2: use sparse matrices for large diagonal matrices
+ typedef blaze::DiagonalMatrix< blaze::CompressedMatrix<float> > LargeDiagonalMatrix;
+ \endcode
+
+// \n \subsection adaptors_triangular_matrices_scaling Unitriangular Matrices Cannot Be Scaled!
+//
+// Since the diagonal elements of a unitriangular matrix have a fixed value of 1 it is not possible
+// to self-scale such a matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+
+ UniLowerMatrix< DynamicMatrix<int> > A( 4 );
+
+ A *= 2; // Compilation error; Scale operation is not available on an unilower matrix
+ A /= 2; // Compilation error; Scale operation is not available on an unilower matrix
+ A.scale( 2 ); // Compilation error; Scale function is not available on an unilower matrix
+
+ A = A * 2; // Throws an exception; Invalid assignment of non-unilower matrix
+ A = A / 2; // Throws an exception; Invalid assignment of non-unilower matrix
+ \endcode
+
+// \n \section adaptors_triangular_matrices_arithmetic_operations Arithmetic Operations
+// <hr>
+//
+// A lower and upper triangular matrix can participate in numerical operations in any way any other
+// dense or sparse matrix can participate. It can also be combined with any other dense or sparse
+// vector or matrix. The following code example gives an impression of the use of blaze::LowerMatrix
+// and blaze::UpperMatrix within arithmetic operations:
+
+ \code
+ using blaze::LowerMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ UpperMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ LowerMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > E;
+ UpperMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major lower matrix
+ F = C - D; // Matrix subtraction and assignment to a column-major upper matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// Note that diagonal, unitriangular and strictly triangular matrix types can be used in the same
+// way, but may pose some additional restrictions (see the according class documentations).
+//
+//
+// \n \section adaptors_triangular_matrices_block_structured Block-Structured Triangular Matrices
+// <hr>
+//
+// It is also possible to use block-structured triangular matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::LowerMatrix;
+ using blaze::UpperMatrix;
+
+ // Definition of a 5x5 block-structured lower matrix based on DynamicMatrix
+ LowerMatrix< DynamicMatrix< StaticMatrix<int,3UL,3UL> > > A( 5 );
+
+ // Definition of a 7x7 block-structured upper matrix based on CompressedMatrix
+ UpperMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > B( 7 );
+ \endcode
+
+// Also in this case the triangular matrix invariant is enforced, i.e. it is not possible to
+// manipulate elements in the upper part (lower triangular matrix) or the lower part (upper
+// triangular matrix) of the matrix:
+
+ \code
+ const StaticMatrix<int,3UL,3UL> C{ { 1, -4, 5 },
+ { 6, 8, -3 },
+ { 2, -1, 2 } };
+
+ A(2,4)(1,1) = -5; // Invalid manipulation of upper matrix element; Results in an exception
+ B.insert( 4, 2, C ); // Invalid insertion of the elements (4,2); Results in an exception
+ \endcode
+
+// Note that unitriangular matrices are restricted to numeric element types and therefore cannot
+// be used for block-structured matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::UniLowerMatrix;
+ using blaze::UniUpperMatrix;
+
+ // Compilation error: lower unitriangular matrices are restricted to numeric element types
+ UniLowerMatrix< DynamicMatrix< StaticMatrix<int,3UL,3UL> > > A( 5 );
+
+ // Compilation error: upper unitriangular matrices are restricted to numeric element types
+ UniUpperMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > B( 7 );
+ \endcode
+
+// \n \section adaptors_triangular_matrices_performance Performance Considerations
+// <hr>
+//
+// The \b Blaze library tries to exploit the properties of lower and upper triangular matrices
+// whenever and wherever possible. Therefore using triangular matrices instead of a general
+// matrices can result in a considerable performance improvement. However, there are also
+// situations when using a triangular matrix introduces some overhead. The following examples
+// demonstrate several common situations where triangular matrices can positively or negatively
+// impact performance.
+//
+// \n \subsection adaptors_triangular_matrices_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is triangular, \b Blaze can exploit the
+// fact that either the lower or upper part of the matrix contains only default elements and
+// restrict the algorithm to the non-zero elements. The following example demonstrates this by
+// means of a dense matrix/dense matrix multiplication with lower triangular matrices:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ LowerMatrix< DynamicMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// In comparison to a general matrix multiplication, the performance advantage is significant,
+// especially for large matrices. Therefore is it highly recommended to use the blaze::LowerMatrix
+// and blaze::UpperMatrix adaptors when a matrix is known to be lower or upper triangular,
+// respectively. Note however that the performance advantage is most pronounced for dense matrices
+// and much less so for sparse matrices.
+//
+// \n \subsection adaptors_triangular_matrices_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar performance improvement can be gained when using a triangular matrix in a matrix/vector
+// multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicVector<double,columnVector> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example, \b Blaze also exploits the structure of the matrix and approx. halves the
+// runtime of the multiplication. Also in case of matrix/vector multiplications the performance
+// improvement is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection adaptors_triangular_matrices_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a triangular matrix on the right-hand side of an assignment (i.e. for
+// read access), which introduces absolutely no performance penalty, using a triangular matrix
+// on the left-hand side of an assignment (i.e. for write access) may introduce additional
+// overhead when it is assigned a general matrix, which is not triangular at compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+
+ LowerMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the lower matrix; no performance penalty
+ C = A; // Assignment of a lower matrix to another lower matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a lower matrix; some runtime overhead
+ \endcode
+
+// When assigning a general (potentially not lower triangular) matrix to a lower matrix or a
+// general (potentially not upper triangular) matrix to an upper matrix it is necessary to check
+// whether the matrix is lower or upper at runtime in order to guarantee the triangular property
+// of the matrix. In case it turns out to be lower or upper, respectively, it is assigned as
+// efficiently as possible, if it is not, an exception is thrown. In order to prevent this runtime
+// overhead it is therefore generally advisable to assign lower or upper triangular matrices to
+// other lower or upper triangular matrices.\n
+// In this context it is especially noteworthy that the addition, subtraction, and multiplication
+// of two triangular matrices of the same structure always results in another triangular matrix:
+
+ \code
+ LowerMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a lower matrix; no runtime overhead
+ C = A - B; // Results in a lower matrix; no runtime overhead
+ C = A * B; // Results in a lower matrix; no runtime overhead
+ \endcode
+
+ \code
+ UpperMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a upper matrix; no runtime overhead
+ C = A - B; // Results in a upper matrix; no runtime overhead
+ C = A * B; // Results in a upper matrix; no runtime overhead
+ \endcode
+
+// \n Previous: \ref adaptors_hermitian_matrices &nbsp; &nbsp; Next: \ref views
+*/
+//*************************************************************************************************
+
+
+//**Views******************************************************************************************
+/*!\page views Views
+//
+// \tableofcontents
+//
+//
+// \section views_general General Concepts
+// <hr>
+//
+// Views represents parts of a vector or matrix, such as a subvector, a submatrix, or a specific
+// row or column of a matrix. As such, views act as a reference to a specific part of a vector
+// or matrix. This reference is valid and can be used in every way as any other vector or matrix
+// can be used as long as the referenced vector or matrix is not resized or entirely destroyed.
+// Views also act as alias to the elements of the vector or matrix: Changes made to the elements
+// (e.g. modifying values, inserting or erasing elements) via the view are immediately visible in
+// the vector or matrix and changes made via the vector or matrix are immediately visible in the
+// view.
+//
+// The \b Blaze library provides the following views on vectors and matrices:
+//
+// Vector views:
+// - \ref views_subvectors
+//
+// Matrix views:
+// - \ref views_submatrices
+// - \ref views_rows
+// - \ref views_columns
+//
+//
+// \n \section views_examples Examples
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StaticVector;
+
+ // Setup of the 3x5 row-major matrix
+ //
+ // ( 1 0 -2 3 0 )
+ // ( 0 2 5 -1 -1 )
+ // ( 1 0 0 2 1 )
+ //
+ DynamicMatrix<int> A{ { 1, 0, -2, 3, 0 },
+ { 0, 2, 5, -1, -1 },
+ { 1, 0, 0, 2, 1 } };
+
+ // Setup of the 2-dimensional row vector
+ //
+ // ( 18 19 )
+ //
+ StaticVector<int,rowVector> vec{ 18, 19 };
+
+ // Assigning to the elements (1,2) and (1,3) via a subvector of a row
+ //
+ // ( 1 0 -2 3 0 )
+ // ( 0 2 18 19 -1 )
+ // ( 1 0 0 2 1 )
+ //
+ subvector( row( A, 1UL ), 2UL, 2UL ) = vec;
+ \endcode
+
+// \n Previous: \ref adaptors_triangular_matrices &nbsp; &nbsp; Next: \ref views_subvectors
+*/
+//*************************************************************************************************
+
+
+//**Subvectors*************************************************************************************
+/*!\page views_subvectors Subvectors
+//
+// \tableofcontents
+//
+//
+// Subvectors provide views on a specific part of a dense or sparse vector. As such, subvectors
+// act as a reference to a specific range within a vector. This reference is valid and can be
+// used in every way any other dense or sparse vector can be used as long as the vector containing
+// the subvector is not resized or entirely destroyed. The subvector also acts as an alias to the
+// vector elements in the specified range: Changes made to the elements (e.g. modifying values,
+// inserting or erasing elements) are immediately visible in the vector and changes made via the
+// vector are immediately visible in the subvector.
+//
+//
+// \n \section views_subvectors_class The Subvector Class Template
+// <hr>
+//
+// The blaze::Subvector class template represents a view on a specific subvector of a dense or
+// sparse vector primitive. It can be included via the header file
+
+ \code
+ #include <blaze/math/Subvector.h>
+ \endcode
+
+// The type of the vector is specified via two template parameters:
+
+ \code
+ template< typename VT, bool AF >
+ class Subvector;
+ \endcode
+
+// - \c VT: specifies the type of the vector primitive. Subvector can be used with every vector
+// primitive or view, but does not work with any vector expression type.
+// - \c AF: the alignment flag specifies whether the subvector is aligned (blaze::aligned) or
+// unaligned (blaze::unaligned). The default value is blaze::unaligned.
+//
+//
+// \n \section views_subvectors_setup Setup of Subvectors
+// <hr>
+//
+// A view on a dense or sparse subvector can be created very conveniently via the \c subvector()
+// function. This view can be treated as any other vector, i.e. it can be assigned to, it can
+// be copied from, and it can be used in arithmetic operations. A subvector created from a row
+// vector can be used as any other row vector, a subvector created from a column vector can be
+// used as any other column vector. The view can also be used on both sides of an assignment:
+// The subvector can either be used as an alias to grant write access to a specific subvector
+// of a vector primitive on the left-hand side of an assignment or to grant read-access to a
+// specific subvector of a vector primitive or expression on the right-hand side of an assignment.
+// The following example demonstrates this in detail:
+
+ \code
+ typedef blaze::DynamicVector<double,blaze::rowVector> DenseVectorType;
+ typedef blaze::CompressedVector<int,blaze::rowVector> SparseVectorType;
+
+ DenseVectorType d1, d2;
+ SparseVectorType s1, s2;
+ // ... Resizing and initialization
+
+ // Creating a view on the first ten elements of the dense vector d1
+ blaze::Subvector<DenseVectorType> dsv = subvector( d1, 0UL, 10UL );
+
+ // Creating a view on the second ten elements of the sparse vector s1
+ blaze::Subvector<SparseVectorType> ssv = subvector( s1, 10UL, 10UL );
+
+ // Creating a view on the addition of d2 and s2
+ dsv = subvector( d2 + s2, 5UL, 10UL );
+
+ // Creating a view on the multiplication of d2 and s2
+ ssv = subvector( d2 * s2, 2UL, 10UL );
+ \endcode
+
+// The \c subvector() function can be used on any dense or sparse vector, including expressions,
+// as demonstrated in the example. Note however that a blaze::Subvector can only be instantiated
+// with a dense or sparse vector primitive, i.e. with types that can be written, and not with an
+// expression type.
+//
+//
+// \n \section views_subvectors_common_operations Common Operations
+// <hr>
+//
+// A subvector view can be used like any other dense or sparse vector. For instance, the current
+// number of elements can be obtained via the \c size() function, the current capacity via the
+// \c capacity() function, and the number of non-zero elements via the \c nonZeros() function.
+// However, since subvectors are references to a specific range of a vector, several operations
+// are not possible on views, such as resizing and swapping. The following example shows this by
+// means of a dense subvector view:
+
+ \code
+ typedef blaze::DynamicVector<int,blaze::rowVector> VectorType;
+ typedef blaze::Subvector<VectorType> SubvectorType;
+
+ VectorType v( 42UL );
+ // ... Resizing and initialization
+
+ // Creating a view on the range [5..15] of vector v
+ SubvectorType sv = subvector( v, 5UL, 10UL );
+
+ sv.size(); // Returns the number of elements in the subvector
+ sv.capacity(); // Returns the capacity of the subvector
+ sv.nonZeros(); // Returns the number of non-zero elements contained in the subvector
+
+ sv.resize( 84UL ); // Compilation error: Cannot resize a subvector of a vector
+
+ SubvectorType sv2 = subvector( v, 15UL, 10UL );
+ swap( sv, sv2 ); // Compilation error: Swap operation not allowed
+ \endcode
+
+// \n \section views_subvectors_element_access Element Access
+// <hr>
+//
+// The elements of a subvector can be directly accessed via the subscript operator:
+
+ \code
+ typedef blaze::DynamicVector<double,blaze::rowVector> VectorType;
+ VectorType v;
+ // ... Resizing and initialization
+
+ // Creating an 8-dimensional subvector, starting from index 4
+ blaze::Subvector<VectorType> sv = subvector( v, 4UL, 8UL );
+
+ // Setting the 1st element of the subvector, which corresponds to
+ // the element at index 5 in vector v
+ sv[1] = 2.0;
+ \endcode
+
+ \code
+ typedef blaze::CompressedVector<double,blaze::rowVector> VectorType;
+ VectorType v;
+ // ... Resizing and initialization
+
+ // Creating an 8-dimensional subvector, starting from index 4
+ blaze::Subvector<VectorType> sv = subvector( v, 4UL, 8UL );
+
+ // Setting the 1st element of the subvector, which corresponds to
+ // the element at index 5 in vector v
+ sv[1] = 2.0;
+ \endcode
+
+// The numbering of the subvector elements is
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right),\f]
+
+// where N is the specified size of the subvector. Alternatively, the elements of a subvector can
+// be traversed via iterators. Just as with vectors, in case of non-const subvectors, \c begin()
+// and \c end() return an Iterator, which allows a manipulation of the non-zero values, in case
+// of constant subvectors a ConstIterator is returned:
+
+ \code
+ typedef blaze::DynamicVector<int,blaze::rowVector> VectorType;
+ typedef blaze::Subvector<VectorType> SubvectorType;
+
+ VectorType v( 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to a specific subvector of the dense vector v
+ SubvectorType sv = subvector( v, 16UL, 64UL );
+
+ for( SubvectorType::Iterator it=sv.begin(); it!=sv.end(); ++it ) {
+ *it = ...; // OK: Write access to the dense subvector value.
+ ... = *it; // OK: Read access to the dense subvector value.
+ }
+
+ for( SubvectorType::ConstIterator it=sv.begin(); it!=sv.end(); ++it ) {
+ *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = *it; // OK: Read access to the dense subvector value.
+ }
+ \endcode
+
+ \code
+ typedef blaze::CompressedVector<int,blaze::rowVector> VectorType;
+ typedef blaze::Subvector<VectorType> SubvectorType;
+
+ VectorType v( 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to a specific subvector of the sparse vector v
+ SubvectorType sv = subvector( v, 16UL, 64UL );
+
+ for( SubvectorType::Iterator it=sv.begin(); it!=sv.end(); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+
+ for( SubvectorType::ConstIterator it=sv.begin(); it!=sv.end(); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+ \endcode
+
+// \n \section views_subvectors_element_insertion Element Insertion
+// <hr>
+//
+// Inserting/accessing elements in a sparse subvector can be done by several alternative functions.
+// The following example demonstrates all options:
+
+ \code
+ typedef blaze::CompressedVector<double,blaze::rowVector> VectorType;
+ VectorType v( 256UL ); // Non-initialized vector of size 256
+
+ typedef blaze::Subvector<VectorType> SubvectorType;
+ SubvectorType sv( subvector( v, 10UL, 60UL ) ); // View on the range [10..69] of v
+
+ // The subscript operator provides access to all possible elements of the sparse subvector,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse subvector, the element is inserted into the
+ // subvector.
+ sv[42] = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element
+ // is not contained in the vector it is inserted into the vector, if it is already contained
+ // in the vector its value is modified.
+ sv.set( 45UL, -1.2 );
+
+ // An alternative for inserting elements into the subvector is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the subvector.
+ sv.insert( 50UL, 3.7 );
+
+ // Just as in case of vectors, elements can also be inserted via the append() function. In
+ // case of subvectors, append() also requires that the appended element's index is strictly
+ // larger than the currently largest non-zero index of the subvector and that the subvector's
+ // capacity is large enough to hold the new element. Note however that due to the nature of
+ // a subvector, which may be an alias to the middle of a sparse vector, the append() function
+ // does not work as efficiently for a subvector as it does for a vector.
+ sv.reserve( 10UL );
+ sv.append( 51UL, -2.1 );
+ \endcode
+
+// \n \section views_subvectors_arithmetic_operations Arithmetic Operations
+// <hr>
+//
+// Both dense and sparse subvectors can be used in all arithmetic operations that any other dense
+// or sparse vector can be used in. The following example gives an impression of the use of dense
+// subvectors within arithmetic operations. All operations (addition, subtraction, multiplication,
+// scaling, ...) can be performed on all possible combinations of dense and sparse subvectors with
+// fitting element types:
+
+ \code
+ typedef blaze::DynamicVector<double,blaze::rowVector> DenseVectorType;
+ typedef blaze::CompressedVector<double,blaze::rowVector> SparseVectorType;
+ DenseVectorType d1, d2, d3;
+ SparseVectorType s1, s2;
+
+ // ... Resizing and initialization
+
+ typedef blaze::DynamicMatrix<double,blaze::rowMajor> DenseMatrixType;
+ DenseMatrixType A;
+
+ typedef blaze::Subvector<DenseVectorType> SubvectorType;
+ SubvectorType dsv( subvector( d1, 0UL, 10UL ) ); // View on the range [0..9] of vector d1
+
+ dsv = d2; // Dense vector initialization of the range [0..9]
+ subvector( d1, 10UL, 10UL ) = s1; // Sparse vector initialization of the range [10..19]
+
+ d3 = dsv + d2; // Dense vector/dense vector addition
+ s2 = s1 + subvector( d1, 10UL, 10UL ); // Sparse vector/dense vector addition
+ d2 = dsv * subvector( d1, 20UL, 10UL ); // Component-wise vector multiplication
+
+ subvector( d1, 3UL, 4UL ) *= 2.0; // In-place scaling of the range [3..6]
+ d2 = subvector( d1, 7UL, 3UL ) * 2.0; // Scaling of the range [7..9]
+ d2 = 2.0 * subvector( d1, 7UL, 3UL ); // Scaling of the range [7..9]
+
+ subvector( d1, 0UL , 10UL ) += d2; // Addition assignment
+ subvector( d1, 10UL, 10UL ) -= s2; // Subtraction assignment
+ subvector( d1, 20UL, 10UL ) *= dsv; // Multiplication assignment
+
+ double scalar = subvector( d1, 5UL, 10UL ) * trans( s1 ); // Scalar/dot/inner product between two vectors
+
+ A = trans( s1 ) * subvector( d1, 4UL, 16UL ); // Outer product between two vectors
+ \endcode
+
+// \n \section views_aligned_subvectors Aligned Subvectors
+// <hr>
+//
+// Usually subvectors can be defined anywhere within a vector. They may start at any position and
+// may have an arbitrary size (only restricted by the size of the underlying vector). However, in
+// contrast to vectors themselves, which are always properly aligned in memory and therefore can
+// provide maximum performance, this means that subvectors in general have to be considered to be
+// unaligned. This can be made explicit by the blaze::unaligned flag:
+
+ \code
+ using blaze::unaligned;
+
+ typedef blaze::DynamicVector<double,blaze::rowVector> DenseVectorType;
+
+ DenseVectorType x;
+ // ... Resizing and initialization
+
+ // Identical creations of an unaligned subvector in the range [8..23]
+ blaze::Subvector<DenseVectorType> sv1 = subvector ( x, 8UL, 16UL );
+ blaze::Subvector<DenseVectorType> sv2 = subvector<unaligned>( x, 8UL, 16UL );
+ blaze::Subvector<DenseVectorType,unaligned> sv3 = subvector ( x, 8UL, 16UL );
+ blaze::Subvector<DenseVectorType,unaligned> sv4 = subvector<unaligned>( x, 8UL, 16UL );
+ \endcode
+
+// All of these calls to the \c subvector() function are identical. Whether the alignment flag is
+// explicitly specified or not, it always returns an unaligned subvector. Whereas this may provide
+// full flexibility in the creation of subvectors, this might result in performance disadvantages
+// in comparison to vector primitives (even in case the specified subvector could be aligned).
+// Whereas vector primitives are guaranteed to be properly aligned and therefore provide maximum
+// performance in all operations, a general view on a vector might not be properly aligned. This
+// may cause a performance penalty on some platforms and/or for some operations.
+//
+// However, it is also possible to create aligned subvectors. Aligned subvectors are identical to
+// unaligned subvectors in all aspects, except that they may pose additional alignment restrictions
+// and therefore have less flexibility during creation, but don't suffer from performance penalties
+// and provide the same performance as the underlying vector. Aligned subvectors are created by
+// explicitly specifying the blaze::aligned flag:
+
+ \code
+ using blaze::aligned;
+
+ // Creating an aligned dense subvector in the range [8..23]
+ blaze::Subvector<DenseVectorType,aligned> sv = subvector<aligned>( x, 8UL, 16UL );
+ \endcode
+
+// The alignment restrictions refer to system dependent address restrictions for the used element
+// type and the available vectorization mode (SSE, AVX, ...). In order to be properly aligned the
+// first element of the subvector must be aligned. The following source code gives some examples
+// for a double precision dynamic vector, assuming that AVX is available, which packs 4 \c double
+// values into a SIMD vector:
+
+ \code
+ using blaze::aligned;
+ using blaze::columnVector;
+
+ typedef blaze::DynamicVector<double,columnVector> VectorType;
+ typedef blaze::Subvector<VectorType,aligned> SubvectorType;
+
+ VectorType d( 17UL );
+ // ... Resizing and initialization
+
+ // OK: Starts at the beginning, i.e. the first element is aligned
+ SubvectorType dsv1 = subvector<aligned>( d, 0UL, 13UL );
+
+ // OK: Start index is a multiple of 4, i.e. the first element is aligned
+ SubvectorType dsv2 = subvector<aligned>( d, 4UL, 7UL );
+
+ // OK: The start index is a multiple of 4 and the subvector includes the last element
+ SubvectorType dsv3 = subvector<aligned>( d, 8UL, 9UL );
+
+ // Error: Start index is not a multiple of 4, i.e. the first element is not aligned
+ SubvectorType dsv4 = subvector<aligned>( d, 5UL, 8UL );
+ \endcode
+
+// Note that the discussed alignment restrictions are only valid for aligned dense subvectors.
+// In contrast, aligned sparse subvectors at this time don't pose any additional restrictions.
+// Therefore aligned and unaligned sparse subvectors are truly fully identical. Still, in case
+// the blaze::aligned flag is specified during setup, an aligned subvector is created:
+
+ \code
+ using blaze::aligned;
+
+ typedef blaze::CompressedVector<double,blaze::rowVector> SparseVectorType;
+
+ SparseVectorType x;
+ // ... Resizing and initialization
+
+ // Creating an aligned subvector in the range [8..23]
+ blaze::Subvector<SparseVectorType,aligned> sv = subvector<aligned>( x, 8UL, 16UL );
+ \endcode
+
+// \n \section views_subvectors_on_subvectors Subvectors on Subvectors
+// <hr>
+//
+// It is also possible to create a subvector view on another subvector. In this context it is
+// important to remember that the type returned by the \c subvector() function is the same type
+// as the type of the given subvector, not a nested subvector type, since the view on a subvector
+// is just another view on the underlying vector:
+
+ \code
+ typedef blaze::DynamicVector<double,blaze::rowVector> VectorType;
+ typedef blaze::Subvector<VectorType> SubvectorType;
+
+ VectorType d1;
+
+ // ... Resizing and initialization
+
+ // Creating a subvector view on the dense vector d1
+ SubvectorType sv1 = subvector( d1, 5UL, 10UL );
+
+ // Creating a subvector view on the dense subvector sv1
+ SubvectorType sv2 = subvector( sv1, 1UL, 5UL );
+ \endcode
+
+// \n Previous: \ref views &nbsp; &nbsp; Next: \ref views_submatrices
+*/
+//*************************************************************************************************
+
+
+//**Submatrices************************************************************************************
+/*!\page views_submatrices Submatrices
+//
+// \tableofcontents
+//
+//
+// Submatrices provide views on a specific part of a dense or sparse matrix just as subvectors
+// provide views on specific parts of vectors. As such, submatrices act as a reference to a
+// specific block within a matrix. This reference is valid and can be used in evary way any
+// other dense or sparse matrix can be used as long as the matrix containing the submatrix is
+// not resized or entirely destroyed. The submatrix also acts as an alias to the matrix elements
+// in the specified block: Changes made to the elements (e.g. modifying values, inserting or
+// erasing elements) are immediately visible in the matrix and changes made via the matrix are
+// immediately visible in the submatrix.
+//
+//
+// \n \section views_submatrices_class The Submatrix Class Template
+// <hr>
+//
+// The blaze::Submatrix class template represents a view on a specific submatrix of a dense or
+// sparse matrix primitive. It can be included via the header file
+
+ \code
+ #include <blaze/math/Submatrix.h>
+ \endcode
+
+// The type of the matrix is specified via two template parameters:
+
+ \code
+ template< typename MT, bool AF >
+ class Submatrix;
+ \endcode
+
+// - \c MT: specifies the type of the matrix primitive. Submatrix can be used with every matrix
+// primitive, but does not work with any matrix expression type.
+// - \c AF: the alignment flag specifies whether the submatrix is aligned (blaze::aligned) or
+// unaligned (blaze::unaligned). The default value is blaze::unaligned.
+//
+//
+// \n \section views_submatrices_setup Setup of Submatrices
+// <hr>
+//
+// A view on a submatrix can be created very conveniently via the \c submatrix() function.
+// This view can be treated as any other matrix, i.e. it can be assigned to, it can be copied
+// from, and it can be used in arithmetic operations. A submatrix created from a row-major
+// matrix will itself be a row-major matrix, a submatrix created from a column-major matrix
+// will be a column-major matrix. The view can also be used on both sides of an assignment:
+// The submatrix can either be used as an alias to grant write access to a specific submatrix
+// of a matrix primitive on the left-hand side of an assignment or to grant read-access to
+// a specific submatrix of a matrix primitive or expression on the right-hand side of an
+// assignment. The following example demonstrates this in detail:
+
+ \code
+ typedef blaze::DynamicMatrix<double,blaze::rowMajor> DenseMatrixType;
+ typedef blaze::CompressedVector<int,blaze::columnMajor> SparseMatrixType;
+
+ DenseMatrixType D1, D2;
+ SparseMatrixType S1, S2;
+ // ... Resizing and initialization
+
+ // Creating a view on the first 8x16 block of the dense matrix D1
+ blaze::Submatrix<DenseMatrixType> dsm = submatrix( D1, 0UL, 0UL, 8UL, 16UL );
+
+ // Creating a view on the second 8x16 block of the sparse matrix S1
+ blaze::Submatrix<SparseMatrixType> ssm = submatrix( S1, 0UL, 16UL, 8UL, 16UL );
+
+ // Creating a view on the addition of D2 and S2
+ dsm = submatrix( D2 + S2, 5UL, 10UL, 8UL, 16UL );
+
+ // Creating a view on the multiplication of D2 and S2
+ ssm = submatrix( D2 * S2, 7UL, 13UL, 8UL, 16UL );
+ \endcode
+
+// \n \section views_submatrices_common_operations Common Operations
+// <hr>
+//
+// The current size of the matrix, i.e. the number of rows or columns can be obtained via the
+// \c rows() and \c columns() functions, the current total capacity via the \c capacity() function,
+// and the number of non-zero elements via the \c nonZeros() function. However, since submatrices
+// are views on a specific submatrix of a matrix, several operations are not possible on views,
+// such as resizing and swapping:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType> SubmatrixType;
+
+ MatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a view on the a 8x12 submatrix of matrix A
+ SubmatrixType sm = submatrix( A, 0UL, 0UL, 8UL, 12UL );
+
+ sm.rows(); // Returns the number of rows of the submatrix
+ sm.columns(); // Returns the number of columns of the submatrix
+ sm.capacity(); // Returns the capacity of the submatrix
+ sm.nonZeros(); // Returns the number of non-zero elements contained in the submatrix
+
+ sm.resize( 10UL, 8UL ); // Compilation error: Cannot resize a submatrix of a matrix
+
+ SubmatrixType sm2 = submatrix( A, 8UL, 0UL, 12UL, 8UL );
+ swap( sm, sm2 ); // Compilation error: Swap operation not allowed
+ \endcode
+
+// \n \section views_submatrices_element_access Element Access
+// <hr>
+//
+// The elements of a submatrix can be directly accessed with the function call operator:
+
+ \code
+ typedef blaze::DynamicMatrix<double,blaze::rowMajor> MatrixType;
+ MatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a 8x8 submatrix, starting from position (4,4)
+ blaze::Submatrix<MatrixType> sm = submatrix( A, 4UL, 4UL, 8UL, 8UL );
+
+ // Setting the element (0,0) of the submatrix, which corresponds to
+ // the element at position (4,4) in matrix A
+ sm(0,0) = 2.0;
+ \endcode
+
+ \code
+ typedef blaze::CompressedMatrix<double,blaze::rowMajor> MatrixType;
+ MatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a 8x8 submatrix, starting from position (4,4)
+ blaze::Submatrix<MatrixType> sm = submatrix( A, 4UL, 4UL, 8UL, 8UL );
+
+ // Setting the element (0,0) of the submatrix, which corresponds to
+ // the element at position (4,4) in matrix A
+ sm(0,0) = 2.0;
+ \endcode
+
+// Alternatively, the elements of a submatrix can be traversed via (const) iterators. Just as
+// with matrices, in case of non-const submatrices, \c begin() and \c end() return an Iterator,
+// which allows a manipulation of the non-zero values, in case of constant submatrices a
+// ConstIterator is returned:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType> SubmatrixType;
+
+ MatrixType A( 256UL, 512UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to a specific submatrix of the dense matrix A
+ SubmatrixType sm = submatrix( A, 16UL, 16UL, 64UL, 128UL );
+
+ // Traversing the elements of the 0th row via iterators to non-const elements
+ for( SubmatrixType::Iterator it=sm.begin(0); it!=sm.end(0); ++it ) {
+ *it = ...; // OK: Write access to the dense submatrix value.
+ ... = *it; // OK: Read access to the dense submatrix value.
+ }
+
+ // Traversing the elements of the 1st row via iterators to const elements
+ for( SubmatrixType::ConstIterator it=sm.begin(1); it!=sm.end(1); ++it ) {
+ *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = *it; // OK: Read access to the dense submatrix value.
+ }
+ \endcode
+
+ \code
+ typedef blaze::CompressedMatrix<int,blaze::rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType> SubmatrixType;
+
+ MatrixType A( 256UL, 512UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to a specific submatrix of the sparse matrix A
+ SubmatrixType sm = submatrix( A, 16UL, 16UL, 64UL, 128UL );
+
+ // Traversing the elements of the 0th row via iterators to non-const elements
+ for( SubmatrixType::Iterator it=sm.begin(0); it!=sm.end(0); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+
+ // Traversing the elements of the 1st row via iterators to const elements
+ for( SubmatrixType::ConstIterator it=sm.begin(1); it!=sm.end(1); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+ \endcode
+
+// \n \section views_submatrices_element_insertion Element Insertion
+// <hr>
+//
+// Inserting/accessing elements in a sparse submatrix can be done by several alternative functions.
+// The following example demonstrates all options:
+
+ \code
+ typedef blaze::CompressedMatrix<double,blaze::rowMajor> MatrixType;
+ MatrixType A( 256UL, 512UL ); // Non-initialized matrix of size 256x512
+
+ typedef blaze::Submatrix<MatrixType> SubmatrixType;
+ SubmatrixType sm = submatrix( A, 10UL, 10UL, 16UL, 16UL ); // View on a 16x16 submatrix of A
+
+ // The function call operator provides access to all possible elements of the sparse submatrix,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse submatrix, the element is inserted into the
+ // submatrix.
+ sm(2,4) = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element is
+ // not contained in the submatrix it is inserted into the submatrix, if it is already contained
+ // in the submatrix its value is modified.
+ sm.set( 2UL, 5UL, -1.2 );
+
+ // An alternative for inserting elements into the submatrix is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the submatrix.
+ sm.insert( 2UL, 6UL, 3.7 );
+
+ // Just as in case of sparse matrices, elements can also be inserted via the append() function.
+ // In case of submatrices, append() also requires that the appended element's index is strictly
+ // larger than the currently largest non-zero index in the according row or column of the
+ // submatrix and that the according row's or column's capacity is large enough to hold the new
+ // element. Note however that due to the nature of a submatrix, which may be an alias to the
+ // middle of a sparse matrix, the append() function does not work as efficiently for a
+ // submatrix as it does for a matrix.
+ sm.reserve( 2UL, 10UL );
+ sm.append( 2UL, 10UL, -2.1 );
+ \endcode
+
+// \n \section views_submatrices_arithmetic_operations Arithmetic Operations
+// <hr>
+//
+// Both dense and sparse submatrices can be used in all arithmetic operations that any other dense
+// or sparse matrix can be used in. The following example gives an impression of the use of dense
+// submatrices within arithmetic operations. All operations (addition, subtraction, multiplication,
+// scaling, ...) can be performed on all possible combinations of dense and sparse matrices with
+// fitting element types:
+
+ \code
+ typedef blaze::DynamicMatrix<double,blaze::rowMajor> DenseMatrixType;
+ typedef blaze::CompressedMatrix<double,blaze::rowMajor> SparseMatrixType;
+ DenseMatrixType D1, D2, D3;
+ SparseMatrixType S1, S2;
+
+ typedef blaze::CompressedVector<double,blaze::columnVector> SparseVectorType;
+ SparseVectorType a, b;
+
+ // ... Resizing and initialization
+
+ typedef Submatrix<DenseMatrixType> SubmatrixType;
+ SubmatrixType sm = submatrix( D1, 0UL, 0UL, 8UL, 8UL ); // View on the 8x8 submatrix of matrix D1
+ // starting from row 0 and column 0
+
+ submatrix( D1, 0UL, 8UL, 8UL, 8UL ) = D2; // Dense matrix initialization of the 8x8 submatrix
+ // starting in row 0 and column 8
+ sm = S1; // Sparse matrix initialization of the second 8x8 submatrix
+
+ D3 = sm + D2; // Dense matrix/dense matrix addition
+ S2 = S1 - submatrix( D1, 8UL, 0UL, 8UL, 8UL ); // Sparse matrix/dense matrix subtraction
+ D2 = sm * submatrix( D1, 8UL, 8UL, 8UL, 8UL ); // Dense matrix/dense matrix multiplication
+
+ submatrix( D1, 8UL, 0UL, 8UL, 8UL ) *= 2.0; // In-place scaling of a submatrix of D1
+ D2 = submatrix( D1, 8UL, 8UL, 8UL, 8UL ) * 2.0; // Scaling of the a submatrix of D1
+ D2 = 2.0 * sm; // Scaling of the a submatrix of D1
+
+ submatrix( D1, 0UL, 8UL, 8UL, 8UL ) += D2; // Addition assignment
+ submatrix( D1, 8UL, 0UL, 8UL, 8UL ) -= S1; // Subtraction assignment
+ submatrix( D1, 8UL, 8UL, 8UL, 8UL ) *= sm; // Multiplication assignment
+
+ a = submatrix( D1, 4UL, 4UL, 8UL, 8UL ) * b; // Dense matrix/sparse vector multiplication
+ \endcode
+
+// \n \section views_aligned_submatrices Aligned Submatrices
+// <hr>
+//
+// Usually submatrices can be defined anywhere within a matrix. They may start at any position and
+// may have an arbitrary extension (only restricted by the extension of the underlying matrix).
+// However, in contrast to matrices themselves, which are always properly aligned in memory and
+// therefore can provide maximum performance, this means that submatrices in general have to be
+// considered to be unaligned. This can be made explicit by the blaze::unaligned flag:
+
+ \code
+ using blaze::unaligned;
+
+ typedef blaze::DynamicMatrix<double,blaze::rowMajor> DenseMatrixType;
+
+ DenseMatrixType A;
+ // ... Resizing and initialization
+
+ // Identical creations of an unaligned submatrix of size 8x8, starting in row 0 and column 0
+ blaze::Submatrix<DenseMatrixType> sm1 = submatrix ( A, 0UL, 0UL, 8UL, 8UL );
+ blaze::Submatrix<DenseMatrixType> sm2 = submatrix<unaligned>( A, 0UL, 0UL, 8UL, 8UL );
+ blaze::Submatrix<DenseMatrixType,unaligned> sm3 = submatrix ( A, 0UL, 0UL, 8UL, 8UL );
+ blaze::Submatrix<DenseMatrixType,unaligned> sm4 = submatrix<unaligned>( A, 0UL, 0UL, 8UL, 8UL );
+ \endcode
+
+// All of these calls to the \c submatrix() function are identical. Whether the alignment flag is
+// explicitly specified or not, it always returns an unaligned submatrix. Whereas this may provide
+// full flexibility in the creation of submatrices, this might result in performance disadvantages
+// in comparison to matrix primitives (even in case the specified submatrix could be aligned).
+// Whereas matrix primitives are guaranteed to be properly aligned and therefore provide maximum
+// performance in all operations, a general view on a matrix might not be properly aligned. This
+// may cause a performance penalty on some platforms and/or for some operations.
+//
+// However, it is also possible to create aligned submatrices. Aligned submatrices are identical to
+// unaligned submatrices in all aspects, except that they may pose additional alignment restrictions
+// and therefore have less flexibility during creation, but don't suffer from performance penalties
+// and provide the same performance as the underlying matrix. Aligned submatrices are created by
+// explicitly specifying the blaze::aligned flag:
+
+ \code
+ using blaze::aligned;
+
+ // Creating an aligned submatrix of size 8x8, starting in row 0 and column 0
+ blaze::Submatrix<DenseMatrixType,aligned> sv = submatrix<aligned>( A, 0UL, 0UL, 8UL, 8UL );
+ \endcode
+
+// The alignment restrictions refer to system dependent address restrictions for the used element
+// type and the available vectorization mode (SSE, AVX, ...). In order to be properly aligned the
+// first element of each row/column of the submatrix must be aligned. The following source code
+// gives some examples for a double precision row-major dynamic matrix, assuming that padding is
+// enabled and that AVX is available, which packs 4 \c double values into a SIMD vector:
+
+ \code
+ using blaze::aligned;
+ using blaze::rowMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType,aligned> SubmatrixType;
+
+ MatrixType D( 13UL, 17UL );
+ // ... Resizing and initialization
+
+ // OK: Starts at position (0,0), i.e. the first element of each row is aligned (due to padding)
+ SubmatrixType dsm1 = submatrix<aligned>( D, 0UL, 0UL, 7UL, 11UL );
+
+ // OK: First column is a multiple of 4, i.e. the first element of each row is aligned (due to padding)
+ SubmatrixType dsm2 = submatrix<aligned>( D, 3UL, 12UL, 8UL, 16UL );
+
+ // OK: First column is a multiple of 4 and the submatrix includes the last row and column
+ SubmatrixType dsm3 = submatrix<aligned>( D, 4UL, 0UL, 9UL, 17UL );
+
+ // Error: First column is not a multiple of 4, i.e. the first element is not aligned
+ SubmatrixType dsm4 = submatrix<aligned>( D, 2UL, 3UL, 12UL, 12UL );
+ \endcode
+
+// Note that the discussed alignment restrictions are only valid for aligned dense submatrices.
+// In contrast, aligned sparse submatrices at this time don't pose any additional restrictions.
+// Therefore aligned and unaligned sparse submatrices are truly fully identical. Still, in case
+// the blaze::aligned flag is specified during setup, an aligned submatrix is created:
+
+ \code
+ using blaze::aligned;
+
+ typedef blaze::CompressedMatrix<double,blaze::rowMajor> SparseMatrixType;
+
+ SparseMatrixType A;
+ // ... Resizing and initialization
+
+ // Creating an aligned submatrix of size 8x8, starting in row 0 and column 0
+ blaze::Submatrix<SparseMatrixType,aligned> sv = submatrix<aligned>( A, 0UL, 0UL, 8UL, 8UL );
+ \endcode
+
+// \n \section views_submatrices_on_submatrices Submatrices on Submatrices
+// <hr>
+//
+// It is also possible to create a submatrix view on another submatrix. In this context it is
+// important to remember that the type returned by the \c submatrix() function is the same type
+// as the type of the given submatrix, since the view on a submatrix is just another view on the
+// underlying matrix:
+
+ \code
+ typedef blaze::DynamicMatrix<double,blaze::rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType> SubmatrixType;
+
+ MatrixType D1;
+
+ // ... Resizing and initialization
+
+ // Creating a submatrix view on the dense matrix D1
+ SubmatrixType sm1 = submatrix( D1, 4UL, 4UL, 8UL, 16UL );
+
+ // Creating a submatrix view on the dense submatrix sm1
+ SubmatrixType sm2 = submatrix( sm1, 1UL, 1UL, 4UL, 8UL );
+ \endcode
+
+// \n \section views_submatrices_on_symmetric_matrices Submatrices on Symmetric Matrices
+//
+// Submatrices can also be created on symmetric matrices (see the \c SymmetricMatrix class template):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::Submatrix;
+
+ typedef SymmetricMatrix< DynamicMatrix<int> > SymmetricDynamicType;
+ typedef Submatrix< SymmetricDynamicType > SubmatrixType;
+
+ // Setup of a 16x16 symmetric matrix
+ SymmetricDynamicType A( 16UL );
+
+ // Creating a dense submatrix of size 8x12, starting in row 2 and column 4
+ SubmatrixType sm = submatrix( A, 2UL, 4UL, 8UL, 12UL );
+ \endcode
+
+// It is important to note, however, that (compound) assignments to such submatrices have a
+// special restriction: The symmetry of the underlying symmetric matrix must not be broken!
+// Since the modification of element \f$ a_{ij} \f$ of a symmetric matrix also modifies the
+// element \f$ a_{ji} \f$, the matrix to be assigned must be structured such that the symmetry
+// of the symmetric matrix is preserved. Otherwise a \c std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Setup of two default 4x4 symmetric matrices
+ SymmetricMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 1 2 )
+ // B = ( 3 4 )
+ // ( 5 6 )
+ //
+ DynamicMatrix<int> B{ { 1, 2 }, { 3, 4 }, { 5, 6 } };
+
+ // OK: Assigning B to a submatrix of A1 such that the symmetry can be preserved
+ //
+ // ( 0 0 1 2 )
+ // A1 = ( 0 0 3 4 )
+ // ( 1 3 5 6 )
+ // ( 2 4 6 0 )
+ //
+ submatrix( A1, 0UL, 2UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the symmetry cannot be preserved!
+ // The elements marked with X cannot be assigned unambiguously!
+ //
+ // ( 0 1 2 0 )
+ // A2 = ( 1 3 X 0 )
+ // ( 2 X 6 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n Previous: \ref views_subvectors &nbsp; &nbsp; Next: \ref views_rows
+*/
+//*************************************************************************************************
+
+
+//**Rows*******************************************************************************************
+/*!\page views_rows Rows
+//
+// \tableofcontents
+//
+//
+// Rows provide views on a specific row of a dense or sparse matrix. As such, rows act as a
+// reference to a specific row. This reference is valid and can be used in every way any other
+// row vector can be used as long as the matrix containing the row is not resized or entirely
+// destroyed. The row also acts as an alias to the row elements: Changes made to the elements
+// (e.g. modifying values, inserting or erasing elements) are immediately visible in the matrix
+// and changes made via the matrix are immediately visible in the row.
+//
+//
+// \n \section views_rows_class The Row Class Template
+// <hr>
+//
+// The blaze::Row class template represents a reference to a specific row of a dense or sparse
+// matrix primitive. It can be included via the header file
+
+ \code
+ #include <blaze/math/Row.h>
+ \endcode
+
+// The type of the matrix is specified via template parameter:
+
+ \code
+ template< typename MT >
+ class Row;
+ \endcode
+
+// \c MT specifies the type of the matrix primitive. Row can be used with every matrix primitive,
+// but does not work with any matrix expression type.
+//
+//
+// \n \section views_rows_setup Setup of Rows
+// <hr>
+//
+// A reference to a dense or sparse row can be created very conveniently via the \c row() function.
+// This reference can be treated as any other row vector, i.e. it can be assigned to, it can be
+// copied from, and it can be used in arithmetic operations. The reference can also be used on
+// both sides of an assignment: The row can either be used as an alias to grant write access to a
+// specific row of a matrix primitive on the left-hand side of an assignment or to grant read-access
+// to a specific row of a matrix primitive or expression on the right-hand side of an assignment.
+// The following two examples demonstrate this for dense and sparse matrices:
+
+ \code
+ typedef blaze::DynamicVector<double,rowVector> DenseVectorType;
+ typedef blaze::CompressedVector<double,rowVector> SparseVectorType;
+ typedef blaze::DynamicMatrix<double,rowMajor> DenseMatrixType;
+ typedef blaze::CompressedMatrix<double,rowMajor> SparseMatrixType;
+
+ DenseVectorType x;
+ SparseVectorType y;
+ DenseMatrixType A, B;
+ SparseMatrixType C, D;
+ // ... Resizing and initialization
+
+ // Setting the 2nd row of matrix A to x
+ blaze::Row<DenseMatrixType> row2 = row( A, 2UL );
+ row2 = x;
+
+ // Setting the 3rd row of matrix B to y
+ row( B, 3UL ) = y;
+
+ // Setting x to the 4th row of the result of the matrix multiplication
+ x = row( A * B, 4UL );
+
+ // Setting y to the 2nd row of the result of the sparse matrix multiplication
+ y = row( C * D, 2UL );
+ \endcode
+
+// The \c row() function can be used on any dense or sparse matrix, including expressions, as
+// illustrated by the source code example. However, rows cannot be instantiated for expression
+// types, but only for matrix primitives, respectively, i.e. for matrix types that offer write
+// access.
+//
+//
+// \n \section views_rows_common_operations Common Operations
+// <hr>
+//
+// A row view can be used like any other row vector. For instance, the current number of elements
+// can be obtained via the \c size() function, the current capacity via the \c capacity() function,
+// and the number of non-zero elements via the \c nonZeros() function. However, since rows are
+// references to specific rows of a matrix, several operations are not possible on views, such
+// as resizing and swapping. The following example shows this by means of a dense row view:
+
+ \code
+ typedef blaze::DynamicMatrix<int,rowMajor> MatrixType;
+ typedef blaze::Row<MatrixType> RowType;
+
+ MatrixType A( 42UL, 42UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 2nd row of matrix A
+ RowType row2 = row( A, 2UL );
+
+ row2.size(); // Returns the number of elements in the row
+ row2.capacity(); // Returns the capacity of the row
+ row2.nonZeros(); // Returns the number of non-zero elements contained in the row
+
+ row2.resize( 84UL ); // Compilation error: Cannot resize a single row of a matrix
+
+ RowType row3 = row( A, 3UL );
+ swap( row2, row3 ); // Compilation error: Swap operation not allowed
+ \endcode
+
+// \n \section views_rows_element_access Element Access
+// <hr>
+//
+// The elements of the row can be directly accessed with the subscript operator. The numbering
+// of the row elements is
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right),\f]
+
+// where N is the number of columns of the referenced matrix. Alternatively, the elements of
+// a row can be traversed via iterators. Just as with vectors, in case of non-const rows,
+// \c begin() and \c end() return an Iterator, which allows a manipulation of the non-zero
+// value, in case of a constant row a ConstIterator is returned:
+
+ \code
+ typedef blaze::DynamicMatrix<int,rowMajor> MatrixType;
+ typedef blaze::Row<MatrixType> RowType;
+
+ MatrixType A( 128UL, 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st row of matrix A
+ RowType row31 = row( A, 31UL );
+
+ for( RowType::Iterator it=row31.begin(); it!=row31.end(); ++it ) {
+ *it = ...; // OK; Write access to the dense row value
+ ... = *it; // OK: Read access to the dense row value.
+ }
+
+ for( RowType::ConstIterator it=row31.begin(); it!=row31.end(); ++it ) {
+ *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = *it; // OK: Read access to the dense row value.
+ }
+ \endcode
+
+ \code
+ typedef blaze::CompressedMatrix<int,rowMajor> MatrixType;
+ typedef blaze::Row<MatrixType> RowType;
+
+ MatrixType A( 128UL, 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st row of matrix A
+ RowType row31 = row( A, 31UL );
+
+ for( RowType::Iterator it=row31.begin(); it!=row31.end(); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+
+ for( RowType::Iterator it=row31.begin(); it!=row31.end(); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+ \endcode
+
+// \n \section views_rows_element_insertion Element Insertion
+// <hr>
+//
+// Inserting/accessing elements in a sparse row can be done by several alternative functions.
+// The following example demonstrates all options:
+
+ \code
+ typedef blaze::CompressedMatrix<double,blaze::rowMajor> MatrixType;
+ MatrixType A( 10UL, 100UL ); // Non-initialized 10x100 matrix
+
+ typedef blaze::Row<MatrixType> RowType;
+ RowType row0( row( A, 0UL ) ); // Reference to the 0th row of A
+
+ // The subscript operator provides access to all possible elements of the sparse row,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse row, the element is inserted into the row.
+ row0[42] = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element
+ // is not contained in the row it is inserted into the row, if it is already contained in
+ // the row its value is modified.
+ row0.set( 45UL, -1.2 );
+
+ // An alternative for inserting elements into the row is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the row.
+ row0.insert( 50UL, 3.7 );
+
+ // A very efficient way to add new elements to a sparse row is the append() function.
+ // Note that append() requires that the appended element's index is strictly larger than
+ // the currently largest non-zero index of the row and that the row's capacity is large
+ // enough to hold the new element.
+ row0.reserve( 10UL );
+ row0.append( 51UL, -2.1 );
+ \endcode
+
+// \n \section views_rows_arithmetic_operations Arithmetic Operations
+// <hr>
+//
+// Both dense and sparse rows can be used in all arithmetic operations that any other dense or
+// sparse row vector can be used in. The following example gives an impression of the use of
+// dense rows within arithmetic operations. All operations (addition, subtraction, multiplication,
+// scaling, ...) can be performed on all possible combinations of dense and sparse rows with
+// fitting element types:
+
+ \code
+ blaze::DynamicVector<double,blaze::rowVector> a( 2UL, 2.0 ), b;
+ blaze::CompressedVector<double,blaze::rowVector> c( 2UL );
+ c[1] = 3.0;
+
+ typedef blaze::DynamicMatrix<double,blaze::rowMajor> DenseMatrix;
+ DenseMatrix A( 4UL, 2UL ); // Non-initialized 4x2 matrix
+
+ typedef blaze::Row<DenseMatrix> RowType;
+ RowType row0( row( A, 0UL ) ); // Reference to the 0th row of A
+
+ row0[0] = 0.0; // Manual initialization of the 0th row of A
+ row0[1] = 0.0;
+ row( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st row of A
+ row( A, 2UL ) = a; // Dense vector initialization of the 2nd row of A
+ row( A, 3UL ) = c; // Sparse vector initialization of the 3rd row of A
+
+ b = row0 + a; // Dense vector/dense vector addition
+ b = c + row( A, 1UL ); // Sparse vector/dense vector addition
+ b = row0 * row( A, 2UL ); // Component-wise vector multiplication
+
+ row( A, 1UL ) *= 2.0; // In-place scaling of the 1st row
+ b = row( A, 1UL ) * 2.0; // Scaling of the 1st row
+ b = 2.0 * row( A, 1UL ); // Scaling of the 1st row
+
+ row( A, 2UL ) += a; // Addition assignment
+ row( A, 2UL ) -= c; // Subtraction assignment
+ row( A, 2UL ) *= row( A, 0UL ); // Multiplication assignment
+
+ double scalar = row( A, 1UL ) * trans( c ); // Scalar/dot/inner product between two vectors
+
+ A = trans( c ) * row( A, 1UL ); // Outer product between two vectors
+ \endcode
+
+// \n \section views_rows_non_fitting_storage_order Views on Matrices with Non-Fitting Storage Order
+// <hr>
+//
+// Especially noteworthy is that row views can be created for both row-major and column-major
+// matrices. Whereas the interface of a row-major matrix only allows to traverse a row directly
+// and the interface of a column-major matrix only allows to traverse a column, via views it is
+// possible to traverse a row of a column-major matrix or a column of a row-major matrix. For
+// instance:
+
+ \code
+ typedef blaze::CompressedMatrix<int,columnMajor> MatrixType;
+ typedef blaze::Row<MatrixType> RowType;
+
+ MatrixType A( 64UL, 32UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st row of a column-major matrix A
+ RowType row1 = row( A, 1UL );
+
+ for( RowType::Iterator it=row1.begin(); it!=row1.end(); ++it ) {
+ // ...
+ }
+ \endcode
+
+// However, please note that creating a row view on a matrix stored in a column-major fashion
+// can result in a considerable performance decrease in comparison to a view on a matrix with
+// a fitting storage orientation. This is due to the non-contiguous storage of the matrix
+// elements. Therefore care has to be taken in the choice of the most suitable storage order:
+
+ \code
+ // Setup of two column-major matrices
+ CompressedMatrix<double,columnMajor> A( 128UL, 128UL );
+ CompressedMatrix<double,columnMajor> B( 128UL, 128UL );
+ // ... Resizing and initialization
+
+ // The computation of the 15th row of the multiplication between A and B ...
+ CompressedVector<double,rowVector> x = row( A * B, 15UL );
+
+ // ... is essentially the same as the following computation, which multiplies
+ // the 15th row of the column-major matrix A with B.
+ CompressedVector<double,rowVector> x = row( A, 15UL ) * B;
+ \endcode
+
+// Although \b Blaze performs the resulting vector/matrix multiplication as efficiently as possible
+// using a row-major storage order for matrix A would result in a more efficient evaluation.
+//
+// \n Previous: \ref views_submatrices &nbsp; &nbsp; Next: \ref views_columns
+*/
+//*************************************************************************************************
+
+
+//**Columns****************************************************************************************
+/*!\page views_columns Columns
+//
+// \tableofcontents
+//
+//
+// Just as rows provide a view on a specific row of a matrix, columns provide views on a specific
+// column of a dense or sparse matrix. As such, columns act as a reference to a specific column.
+// This reference is valid an can be used in every way any other column vector can be used as long
+// as the matrix containing the column is not resized or entirely destroyed. Changes made to the
+// elements (e.g. modifying values, inserting or erasing elements) are immediately visible in the
+// matrix and changes made via the matrix are immediately visible in the column.
+//
+//
+// \n \section views_columns_class The Column Class Template
+// <hr>
+//
+// The blaze::Column class template represents a reference to a specific column of a dense or
+// sparse matrix primitive. It can be included via the header file
+
+ \code
+ #include <blaze/math/Column.h>
+ \endcode
+
+// The type of the matrix is specified via template parameter:
+
+ \code
+ template< typename MT >
+ class Column;
+ \endcode
+
+// \c MT specifies the type of the matrix primitive. Column can be used with every matrix
+// primitive, but does not work with any matrix expression type.
+//
+//
+// \n \section views_colums_setup Setup of Columns
+// <hr>
+//
+// Similar to the setup of a row, a reference to a dense or sparse column can be created very
+// conveniently via the \c column() function. This reference can be treated as any other column
+// vector, i.e. it can be assigned to, copied from, and be used in arithmetic operations. The
+// column can either be used as an alias to grant write access to a specific column of a matrix
+// primitive on the left-hand side of an assignment or to grant read-access to a specific column
+// of a matrix primitive or expression on the right-hand side of an assignment. The following
+// two examples demonstrate this for dense and sparse matrices:
+
+ \code
+ typedef blaze::DynamicVector<double,columnVector> DenseVectorType;
+ typedef blaze::CompressedVector<double,columnVector> SparseVectorType;
+ typedef blaze::DynamicMatrix<double,columnMajor> DenseMatrixType;
+ typedef blaze::CompressedMatrix<double,columnMajor> SparseMatrixType;
+
+ DenseVectorType x;
+ SparseVectorType y;
+ DenseMatrixType A, B;
+ SparseMatrixType C, D;
+ // ... Resizing and initialization
+
+ // Setting the 1st column of matrix A to x
+ blaze::Column<DenseMatrixType> col1 = column( A, 1UL );
+ col1 = x;
+
+ // Setting the 4th column of matrix B to y
+ column( B, 4UL ) = y;
+
+ // Setting x to the 2nd column of the result of the matrix multiplication
+ x = column( A * B, 2UL );
+
+ // Setting y to the 2nd column of the result of the sparse matrix multiplication
+ y = column( C * D, 2UL );
+ \endcode
+
+// The \c column() function can be used on any dense or sparse matrix, including expressions, as
+// illustrated by the source code example. However, columns cannot be instantiated for expression
+// types, but only for matrix primitives, respectively, i.e. for matrix types that offer write
+// access.
+//
+//
+// \n \section views_columns_common_operations Common Operations
+// <hr>
+//
+// A column view can be used like any other column vector. For instance, the current number of
+// elements can be obtained via the \c size() function, the current capacity via the \c capacity()
+// function, and the number of non-zero elements via the \c nonZeros() function. However, since
+// columns are references to specific columns of a matrix, several operations are not possible on
+// views, such as resizing and swapping. The following example shows this by means of a dense
+// column view:
+
+ \code
+ typedef blaze::DynamicMatrix<int,columnMajor> MatrixType;
+ typedef blaze::Column<MatrixType> ColumnType;
+
+ MatrixType A( 42UL, 42UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 2nd column of matrix A
+ ColumnType col2 = column( A, 2UL );
+
+ col2.size(); // Returns the number of elements in the column
+ col2.capacity(); // Returns the capacity of the column
+ col2.nonZeros(); // Returns the number of non-zero elements contained in the column
+
+ col2.resize( 84UL ); // Compilation error: Cannot resize a single column of a matrix
+
+ ColumnType col3 = column( A, 3UL );
+ swap( col2, col3 ); // Compilation error: Swap operation not allowed
+ \endcode
+
+// \n \section views_columns_element_access Element Access
+// <hr>
+//
+// The elements of the column can be directly accessed with the subscript operator. The numbering
+// of the column elements is
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right),\f]
+
+// where N is the number of rows of the referenced matrix. Alternatively, the elements of
+// a column can be traversed via iterators. Just as with vectors, in case of non-const columns,
+// \c begin() and \c end() return an Iterator, which allows a manipulation of the non-zero
+// value, in case of a constant column a ConstIterator is returned:
+
+ \code
+ typedef blaze::DynamicMatrix<int,columnMajor> MatrixType;
+ typedef blaze::Column<MatrixType> ColumnType;
+
+ MatrixType A( 128UL, 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st column of matrix A
+ ColumnType col31 = column( A, 31UL );
+
+ for( ColumnType::Iterator it=col31.begin(); it!=col31.end(); ++it ) {
+ *it = ...; // OK; Write access to the dense column value
+ ... = *it; // OK: Read access to the dense column value.
+ }
+
+ for( ColumnType::ConstIterator it=col31.begin(); it!=col31.end(); ++it ) {
+ *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = *it; // OK: Read access to the dense column value.
+ }
+ \endcode
+
+ \code
+ typedef blaze::CompressedMatrix<int,columnMajor> MatrixType;
+ typedef blaze::Column<MatrixType> ColumnType;
+
+ MatrixType A( 128UL, 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st column of matrix A
+ ColumnType col31 = column( A, 31UL );
+
+ for( ColumnType::Iterator it=col31.begin(); it!=col31.end(); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+
+ for( ColumnType::Iterator it=col31.begin(); it!=col31.end(); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+ \endcode
+
+// \n \section views_columns_element_insertion Element Insertion
+// <hr>
+//
+// Inserting/accessing elements in a sparse column can be done by several alternative functions.
+// The following example demonstrates all options:
+
+ \code
+ typedef blaze::CompressedMatrix<double,blaze::columnMajor> MatrixType;
+ MatrixType A( 100UL, 10UL ); // Non-initialized 10x100 matrix
+
+ typedef blaze::Column<MatrixType> ColumnType;
+ ColumnType col0( column( A, 0UL ) ); // Reference to the 0th column of A
+
+ // The subscript operator provides access to all possible elements of the sparse column,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse column, the element is inserted into the column.
+ col0[42] = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element
+ // is not contained in the column it is inserted into the column, if it is already contained
+ // in the column its value is modified.
+ col0.set( 45UL, -1.2 );
+
+ // An alternative for inserting elements into the column is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the column.
+ col0.insert( 50UL, 3.7 );
+
+ // A very efficient way to add new elements to a sparse column is the append() function.
+ // Note that append() requires that the appended element's index is strictly larger than
+ // the currently largest non-zero index of the column and that the column's capacity is
+ // large enough to hold the new element.
+ col0.reserve( 10UL );
+ col0.append( 51UL, -2.1 );
+ \endcode
+
+// \n \section views_columns_arithmetic_operations Arithmetic Operations
+// <hr>
+//
+// Both dense and sparse columns can be used in all arithmetic operations that any other dense or
+// sparse column vector can be used in. The following example gives an impression of the use of
+// dense columns within arithmetic operations. All operations (addition, subtraction, multiplication,
+// scaling, ...) can be performed on all possible combinations of dense and sparse columns with
+// fitting element types:
+
+ \code
+ blaze::DynamicVector<double,blaze::columnVector> a( 2UL, 2.0 ), b;
+ blaze::CompressedVector<double,blaze::columnVector> c( 2UL );
+ c[1] = 3.0;
+
+ typedef blaze::DynamicMatrix<double,blaze::columnMajor> MatrixType;
+ MatrixType A( 2UL, 4UL ); // Non-initialized 2x4 matrix
+
+ typedef blaze::Column<DenseMatrix> ColumnType;
+ ColumnType col0( column( A, 0UL ) ); // Reference to the 0th column of A
+
+ col0[0] = 0.0; // Manual initialization of the 0th column of A
+ col0[1] = 0.0;
+ column( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st column of A
+ column( A, 2UL ) = a; // Dense vector initialization of the 2nd column of A
+ column( A, 3UL ) = c; // Sparse vector initialization of the 3rd column of A
+
+ b = col0 + a; // Dense vector/dense vector addition
+ b = c + column( A, 1UL ); // Sparse vector/dense vector addition
+ b = col0 * column( A, 2UL ); // Component-wise vector multiplication
+
+ column( A, 1UL ) *= 2.0; // In-place scaling of the 1st column
+ b = column( A, 1UL ) * 2.0; // Scaling of the 1st column
+ b = 2.0 * column( A, 1UL ); // Scaling of the 1st column
+
+ column( A, 2UL ) += a; // Addition assignment
+ column( A, 2UL ) -= c; // Subtraction assignment
+ column( A, 2UL ) *= column( A, 0UL ); // Multiplication assignment
+
+ double scalar = trans( c ) * column( A, 1UL ); // Scalar/dot/inner product between two vectors
+
+ A = column( A, 1UL ) * trans( c ); // Outer product between two vectors
+ \endcode
+
+// \n \section views_columns_non_fitting_storage_order Views on Matrices with Non-Fitting Storage Order
+// <hr>
+//
+// Especially noteworthy is that column views can be created for both row-major and column-major
+// matrices. Whereas the interface of a row-major matrix only allows to traverse a row directly
+// and the interface of a column-major matrix only allows to traverse a column, via views it is
+// possible to traverse a row of a column-major matrix or a column of a row-major matrix. For
+// instance:
+
+ \code
+ typedef blaze::CompressedMatrix<int,rowMajor> MatrixType;
+ typedef blaze::Column<MatrixType> ColumnType;
+
+ MatrixType A( 64UL, 32UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st column of a row-major matrix A
+ ColumnType col1 = column( A, 1UL );
+
+ for( ColumnType::Iterator it=col1.begin(); it!=col1.end(); ++it ) {
+ // ...
+ }
+ \endcode
+
+// However, please note that creating a column view on a matrix stored in a row-major fashion
+// can result in a considerable performance decrease in comparison to a view on a matrix with
+// a fitting storage orientation. This is due to the non-contiguous storage of the matrix
+// elements. Therefore care has to be taken in the choice of the most suitable storage order:
+
+ \code
+ // Setup of two row-major matrices
+ CompressedMatrix<double,rowMajor> A( 128UL, 128UL );
+ CompressedMatrix<double,rowMajor> B( 128UL, 128UL );
+ // ... Resizing and initialization
+
+ // The computation of the 15th column of the multiplication between A and B ...
+ CompressedVector<double,columnVector> x = column( A * B, 15UL );
+
+ // ... is essentially the same as the following computation, which multiplies
+ // the 15th column of the row-major matrix B with A.
+ CompressedVector<double,columnVector> x = A * column( B, 15UL );
+ \endcode
+
+// Although \b Blaze performs the resulting matrix/vector multiplication as efficiently as possible
+// using a column-major storage order for matrix B would result in a more efficient evaluation.
+//
+// \n Previous: \ref views_rows &nbsp; &nbsp; Next: \ref arithmetic_operations
+*/
+//*************************************************************************************************
+
+
+//**Arithmetic Operations**************************************************************************
+/*!\page arithmetic_operations Arithmetic Operations
+//
+// \tableofcontents
+//
+//
+// \b Blaze provides the following arithmetic operations for vectors and matrices:
+//
+// <ul>
+// <li> \ref addition </li>
+// <li> \ref subtraction </li>
+// <li> \ref scalar_multiplication </li>
+// <li> \ref vector_vector_multiplication
+// <ul>
+// <li> \ref componentwise_multiplication </li>
+// <li> \ref inner_product </li>
+// <li> \ref outer_product </li>
+// <li> \ref cross_product </li>
+// </ul>
+// </li>
+// <li> \ref vector_vector_division </li>
+// <li> \ref matrix_vector_multiplication </li>
+// <li> \ref matrix_matrix_multiplication </li>
+// </ul>
+//
+// \n Previous: \ref views_columns &nbsp; &nbsp; Next: \ref addition
+*/
+//*************************************************************************************************
+
+
+//**Addition***************************************************************************************
+/*!\page addition Addition
+//
+// The addition of vectors and matrices is as intuitive as the addition of scalar values. For both
+// the vector addition as well as the matrix addition the addition operator can be used. It even
+// enables the addition of dense and sparse vectors as well as the addition of dense and sparse
+// matrices:
+
+ \code
+ blaze::DynamicVector<int> v1( 5UL ), v3;
+ blaze::CompressedVector<float> v2( 5UL );
+
+ // ... Initializing the vectors
+
+ v3 = v1 + v2; // Addition of a two column vectors of different data type
+ \endcode
+
+ \code
+ blaze::DynamicMatrix<float,rowMajor> M1( 7UL, 3UL );
+ blaze::CompressedMatrix<size_t,columnMajor> M2( 7UL, 3UL ), M3;
+
+ // ... Initializing the matrices
+
+ M3 = M1 + M2; // Addition of a row-major and a column-major matrix of different data type
+ \endcode
+
+// Note that it is necessary that both operands have exactly the same dimensions. Violating this
+// precondition results in an exception. Also note that in case of vectors it is only possible to
+// add vectors with the same transpose flag:
+
+ \code
+ blaze::DynamicVector<int,columnVector> v1( 5UL );
+ blaze::CompressedVector<float,rowVector> v2( 5UL );
+
+ v1 + v2; // Compilation error: Cannot add a column vector and a row vector
+ v1 + trans( v2 ); // OK: Addition of two column vectors
+ \endcode
+
+// In case of matrices, however, it is possible to add row-major and column-major matrices. Note
+// however that in favor of performance the addition of two matrices with the same storage order
+// is favorable. The same argument holds for the element type: In case two vectors or matrices
+// with the same element type are added, the performance can be much higher due to vectorization
+// of the operation.
+
+ \code
+ blaze::DynamicVector<double>v1( 100UL ), v2( 100UL ), v3;
+
+ // ... Initialization of the vectors
+
+ v3 = v1 + v2; // Vectorized addition of two double precision vectors
+ \endcode
+
+ \code
+ blaze::DynamicMatrix<float> M1( 50UL, 70UL ), M2( 50UL, 70UL ), M3;
+
+ // ... Initialization of the matrices
+
+ M3 = M1 + M2; // Vectorized addition of two row-major, single precision dense matrices
+ \endcode
+
+// \n Previous: \ref arithmetic_operations &nbsp; &nbsp; Next: \ref subtraction
+*/
+//*************************************************************************************************
+
+
+//**Subtraction************************************************************************************
+/*!\page subtraction Subtraction
+//
+// The subtraction of vectors and matrices works exactly as intuitive as the addition, but with
+// the subtraction operator. For both the vector subtraction as well as the matrix subtraction
+// the subtraction operator can be used. It also enables the subtraction of dense and sparse
+// vectors as well as the subtraction of dense and sparse matrices:
+
+ \code
+ blaze::DynamicVector<int> v1( 5UL ), v3;
+ blaze::CompressedVector<float> v2( 5UL );
+
+ // ... Initializing the vectors
+
+ v3 = v1 - v2; // Subtraction of a two column vectors of different data type
+
+
+ blaze::DynamicMatrix<float,rowMajor> M1( 7UL, 3UL );
+ blaze::CompressedMatrix<size_t,columnMajor> M2( 7UL, 3UL ), M3;
+
+ // ... Initializing the matrices
+
+ M3 = M1 - M2; // Subtraction of a row-major and a column-major matrix of different data type
+ \endcode
+
+// Note that it is necessary that both operands have exactly the same dimensions. Violating this
+// precondition results in an exception. Also note that in case of vectors it is only possible to
+// subtract vectors with the same transpose flag:
+
+ \code
+ blaze::DynamicVector<int,columnVector> v1( 5UL );
+ blaze::CompressedVector<float,rowVector> v2( 5UL );
+
+ v1 - v2; // Compilation error: Cannot subtract a row vector from a column vector
+ v1 - trans( v2 ); // OK: Subtraction of two column vectors
+ \endcode
+
+// In case of matrices, however, it is possible to subtract row-major and column-major matrices.
+// Note however that in favor of performance the subtraction of two matrices with the same storage
+// order is favorable. The same argument holds for the element type: In case two vectors or matrices
+// with the same element type are added, the performance can be much higher due to vectorization
+// of the operation.
+
+ \code
+ blaze::DynamicVector<double>v1( 100UL ), v2( 100UL ), v3;
+
+ // ... Initialization of the vectors
+
+ v3 = v1 - v2; // Vectorized subtraction of two double precision vectors
+
+
+ blaze::DynamicMatrix<float> M1( 50UL, 70UL ), M2( 50UL, 70UL ), M3;
+
+ // ... Initialization of the matrices
+
+ M3 = M1 - M2; // Vectorized subtraction of two row-major, single precision dense matrices
+ \endcode
+
+// \n Previous: \ref addition &nbsp; &nbsp; Next: \ref scalar_multiplication
+*/
+//*************************************************************************************************
+
+
+//**Scalar Multiplication**************************************************************************
+/*!\page scalar_multiplication Scalar Multiplication
+//
+// The scalar multiplication is the multiplication of a scalar value with a vector or a matrix.
+// In \b Blaze it is possible to use all built-in/fundamental data types except bool as scalar
+// values. Additionally, it is possible to use std::complex values with the same built-in data
+// types as element type.
+
+ \code
+ blaze::StaticVector<int,3UL> v1{ 1, 2, 3 };
+
+ blaze::DynamicVector<double> v2 = v1 * 1.2;
+ blaze::CompressedVector<float> v3 = -0.3F * v1;
+ \endcode
+
+ \code
+ blaze::StaticMatrix<int,3UL,2UL> M1{ { 1, 2 }, { 3, 4 }, { 5, 6 } };
+
+ blaze::DynamicMatrix<double> M2 = M1 * 1.2;
+ blaze::CompressedMatrix<float> M3 = -0.3F * M1;
+ \endcode
+
+// Vectors and matrices cannot be used for as scalar value for scalar multiplications (see the
+// following example). However, each vector and matrix provides the \c scale() function, which
+// can be used to scale a vector or matrix element-wise with arbitrary scalar data types:
+
+ \code
+ blaze::CompressedMatrix< blaze::StaticMatrix<int,3UL,3UL> > M1;
+ blaze::StaticMatrix<int,3UL,3UL> scalar;
+
+ M1 * scalar; // No scalar multiplication, but matrix/matrix multiplication
+
+ M1.scale( scalar ); // Scalar multiplication
+ \endcode
+
+// \n Previous: \ref subtraction &nbsp; &nbsp; Next: \ref componentwise_multiplication
+*/
+//*************************************************************************************************
+
+
+//**Vector/Vector Multiplication*******************************************************************
+/*!\page vector_vector_multiplication Vector/Vector Multiplication
+//
+// \n \section componentwise_multiplication Componentwise Multiplication
+// <hr>
+//
+// Multiplying two vectors with the same transpose flag (i.e. either blaze::columnVector or
+// blaze::rowVector) via the multiplication operator results in a componentwise multiplication
+// of the two vectors:
+
+ \code
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+
+ CompressedVector<int,columnVector> v1( 17UL );
+ DynamicVector<int,columnVector> v2( 17UL );
+
+ StaticVector<double,10UL,rowVector> v3;
+ DynamicVector<double,rowVector> v4( 10UL );
+
+ // ... Initialization of the vectors
+
+ CompressedVector<int,columnVector> v5( v1 * v2 ); // Componentwise multiplication of a sparse and
+ // a dense column vector. The result is a sparse
+ // column vector.
+ DynamicVector<double,rowVector> v6( v3 * v4 ); // Componentwise multiplication of two dense row
+ // vectors. The result is a dense row vector.
+ \endcode
+
+// \n \section inner_product Inner Product / Scalar Product / Dot Product
+// <hr>
+//
+// The multiplication between a row vector and a column vector results in an inner product between
+// the two vectors:
+
+ \code
+ blaze::StaticVector<int,3UL,rowVector> v1{ 2, 5, -1 };
+ blaze::DynamicVector<int,columnVector> v2{ -1, 3, -2 };
+
+ int result = v1 * v2; // Results in the value 15
+ \endcode
+
+// The \c trans() function can be used to transpose a vector as necessary:
+
+ \code
+ blaze::StaticVector<int,3UL,rowVector> v1{ 2, 5, -1 };
+ blaze::StaticVector<int,3UL,rowVector> v2{ -1, 3, -2 };
+
+ int result = v1 * trans( v2 ); // Also results in the value 15
+ \endcode
+
+// Alternatively, either the \c dot() function or the comma operator can be used for any combination
+// of vectors (row or column vectors) to perform an inner product:
+
+ \code
+ blaze::StaticVector<int,3UL,rowVector> v1{ 2, 5, -1 };
+ blaze::StaticVector<int,3UL,rowVector> v2{ -1, 3, -2 };
+
+ int result = dot( v1, v2 ); // Inner product between two row vectors
+ \endcode
+
+ \code
+ blaze::StaticVector<int,3UL,columnVector> v1{ 2, 5, -1 };
+ blaze::StaticVector<int,3UL,columnVector> v2{ -1, 3, -2 };
+
+ int result = (v1,v2); // Inner product between two column vectors
+ \endcode
+
+// When using the comma operator, please note the brackets embracing the inner product expression.
+// Due to the low precedence of the comma operator (lower even than the assignment operator) these
+// brackets are strictly required for a correct evaluation of the inner product.
+//
+//
+// \n \section outer_product Outer Product
+// <hr>
+//
+// The multiplication between a column vector and a row vector results in the outer product of
+// the two vectors:
+
+ \code
+ blaze::StaticVector<int,3UL,columnVector> v1{ 2, 5, -1 };
+ blaze::DynamicVector<int,rowVector> v2{ -1, 3, -2 };
+
+ StaticMatrix<int,3UL,3UL> M1 = v1 * v2;
+ \endcode
+
+// The \c trans() function can be used to transpose a vector as necessary:
+
+ \code
+ blaze::StaticVector<int,3UL,rowVector> v1{ 2, 5, -1 };
+ blaze::StaticVector<int,3UL,rowVector> v2{ -1, 3, -2 };
+
+ int result = trans( v1 ) * v2;
+ \endcode
+
+// Alternatively, the \c outer() function can be used for any combination of vectors (row or column
+// vectors) to perform an outer product:
+
+ \code
+ blaze::StaticVector<int,3UL,rowVector> v1{ 2, 5, -1 };
+ blaze::StaticVector<int,3UL,rowVector> v2{ -1, 3, -2 };
+
+ StaticMatrix<int,3UL,3UL> M1 = outer( v1, v2 ); // Outer product between two row vectors
+ \endcode
+
+// \n \section cross_product Cross Product
+// <hr>
+//
+// Two vectors with the same transpose flag can be multiplied via the cross product. The cross
+// product between two vectors \f$ a \f$ and \f$ b \f$ is defined as
+
+ \f[
+ \left(\begin{array}{*{1}{c}}
+ c_0 \\
+ c_1 \\
+ c_2 \\
+ \end{array}\right)
+ =
+ \left(\begin{array}{*{1}{c}}
+ a_1 b_2 - a_2 b_1 \\
+ a_2 b_0 - a_0 b_2 \\
+ a_0 b_1 - a_1 b_0 \\
+ \end{array}\right).
+ \f]
+
+// Due to the absence of a \f$ \times \f$ operator in the C++ language, the cross product is
+// realized via the \c cross() function. Alternatively, the modulo operator (i.e. \c operator%)
+// can be used in case infix notation is required:
+
+ \code
+ blaze::StaticVector<int,3UL,columnVector> v1{ 2, 5, -1 };
+ blaze::DynamicVector<int,columnVector> v2{ -1, 3, -2 };
+
+ blaze::StaticVector<int,3UL,columnVector> v3( cross( v1, v2 ) );
+ blaze::StaticVector<int,3UL,columnVector> v4( v1 % v2 );
+ \endcode
+
+// Please note that the cross product is restricted to three dimensional (dense and sparse)
+// column vectors.
+//
+// \n Previous: \ref scalar_multiplication &nbsp; &nbsp; Next: \ref vector_vector_division
+*/
+//*************************************************************************************************
+
+
+//**Vector/Vector Division*************************************************************************
+/*!\page vector_vector_division Vector/Vector Division
+//
+// \n \section componentwise_division Componentwise Division
+// <hr>
+//
+// Dividing a vector by a dense vector with the same transpose flag (i.e. either blaze::columnVector
+// or blaze::rowVector) via the division operator results in a componentwise division:
+
+ \code
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+
+ CompressedVector<int,columnVector> v1( 17UL );
+ DynamicVector<int,columnVector> v2( 17UL );
+
+ StaticVector<double,10UL,rowVector> v3;
+ DynamicVector<double,rowVector> v4( 10UL );
+
+ // ... Initialization of the vectors
+
+ CompressedVector<int,columnVector> v5( v1 / v2 ); // Componentwise division of a sparse and a
+ // dense column vector. The result is a sparse
+ // column vector.
+ DynamicVector<double,rowVector> v6( v3 / v4 ); // Componentwise division of two dense row
+ // vectors. The result is a dense row vector.
+ \endcode
+
+// Note that all values of the divisor must be non-zero and that no checks are performed to assert
+// this precondition!
+//
+// \n Previous: \ref vector_vector_multiplication &nbsp; &nbsp; Next: \ref matrix_vector_multiplication
+*/
+//*************************************************************************************************
+
+
+//**Matrix/Vector Multiplication*******************************************************************
+/*!\page matrix_vector_multiplication Matrix/Vector Multiplication
+//
+// In \b Blaze matrix/vector multiplications can be as intuitively formulated as in mathematical
+// textbooks. Just as in textbooks there are two different multiplications between a matrix and
+// a vector: a matrix/column vector multiplication and a row vector/matrix multiplication:
+
+ \code
+ using blaze::StaticVector;
+ using blaze::DynamicVector;
+ using blaze::DynamicMatrix;
+
+ DynamicMatrix<int> M1( 39UL, 12UL );
+ StaticVector<int,12UL,columnVector> v1;
+
+ // ... Initialization of the matrix and the vector
+
+ DynamicVector<int,columnVector> v2 = M1 * v1; // Matrix/column vector multiplication
+ DynamicVector<int,rowVector> v3 = trans( v1 ) * M1; // Row vector/matrix multiplication
+ \endcode
+
+// Note that the storage order of the matrix poses no restrictions on the operation. Also note,
+// that the highest performance for a multiplication between a dense matrix and a dense vector can
+// be achieved if both the matrix and the vector have the same scalar element type.
+//
+// \n Previous: \ref vector_vector_division &nbsp; &nbsp; Next: \ref matrix_matrix_multiplication
+*/
+//*************************************************************************************************
+
+
+//**Matrix/Matrix Multiplication*******************************************************************
+/*!\page matrix_matrix_multiplication Matrix/Matrix Multiplication
+//
+// The matrix/matrix multiplication can be formulated exactly as in mathematical textbooks:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::CompressedMatrix;
+
+ DynamicMatrix<double> M1( 45UL, 85UL );
+ CompressedMatrix<float> M2( 85UL, 37UL );
+
+ // ... Initialization of the matrices
+
+ DynamicMatrix<double> M3 = M1 * M2;
+ \endcode
+
+// The storage order of the two matrices poses no restrictions on the operation, all variations
+// are possible. Note however that the highest performance for a multiplication between two dense
+// matrices can be expected for two matrices with the same scalar element type.
+//
+// \n Previous: \ref matrix_vector_multiplication &nbsp; &nbsp; Next: \ref custom_operations
+*/
+//*************************************************************************************************
+
+
+//**Custom Operations******************************************************************************
+/*!\page custom_operations Custom Operations
+//
+// In addition to the provided operations on vectors and matrices it is possible to define custom
+// operations. For this purpose, \b Blaze provides the \c forEach() function, which allows to pass
+// the required operation via functor or lambda:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+
+ B = forEach( A, []( double d ){ return std::sqrt( d ); } );
+ \endcode
+
+// This example demonstrates the most convenient way of defining a custom operation by passing a
+// lambda to the \c forEach() function. The lambda is executed on each single element of a dense
+// vector or matrix or each non-zero element of a sparse vector or matrix.
+//
+// Alternatively, it is possible to pass a custom functor:
+
+ \code
+ struct Sqrt
+ {
+ double operator()( double a ) const
+ {
+ return std::sqrt( a );
+ }
+ };
+
+ B = forEach( A, Sqrt() );
+ \endcode
+
+// In order for the functor to work in a call to \c forEach() it must define a function call
+// operator, which accepts arguments of the type of the according vector or matrix elements.
+//
+// Although the operation is automatically parallelized depending on the size of the vector or
+// matrix, no automatic vectorization is possible. In order to enable vectorization, a \c load()
+// function can be added to the functor, which handles the vectorized computation. Depending on
+// the data type this function is passed one of the following \b Blaze SIMD data types:
+//
+// <ul>
+// <li>SIMD data types for fundamental data types
+// <ul>
+// <li>\c blaze::SIMDint8: Packed SIMD type for 8-bit signed integral data types</li>
+// <li>\c blaze::SIMDuint8: Packed SIMD type for 8-bit unsigned integral data types</li>
+// <li>\c blaze::SIMDint16: Packed SIMD type for 16-bit signed integral data types</li>
+// <li>\c blaze::SIMDuint16: Packed SIMD type for 16-bit unsigned integral data types</li>
+// <li>\c blaze::SIMDint32: Packed SIMD type for 32-bit signed integral data types</li>
+// <li>\c blaze::SIMDuint32: Packed SIMD type for 32-bit unsigned integral data types</li>
+// <li>\c blaze::SIMDint64: Packed SIMD type for 64-bit signed integral data types</li>
+// <li>\c blaze::SIMDuint64: Packed SIMD type for 64-bit unsigned integral data types</li>
+// <li>\c blaze::SIMDfloat: Packed SIMD type for single precision floating point data</li>
+// <li>\c blaze::SIMDdouble: Packed SIMD type for double precision floating point data</li>
+// </ul>
+// </li>
+// <li>SIMD data types for complex data types
+// <ul>
+// <li>\c blaze::cint8: Packed SIMD type for complex 8-bit signed integral data types</li>
+// <li>\c blaze::cuint8: Packed SIMD type for complex 8-bit unsigned integral data types</li>
+// <li>\c blaze::cint16: Packed SIMD type for complex 16-bit signed integral data types</li>
+// <li>\c blaze::cuint16: Packed SIMD type for complex 16-bit unsigned integral data types</li>
+// <li>\c blaze::cint32: Packed SIMD type for complex 32-bit signed integral data types</li>
+// <li>\c blaze::cuint32: Packed SIMD type for complex 32-bit unsigned integral data types</li>
+// <li>\c blaze::cint64: Packed SIMD type for complex 64-bit signed integral data types</li>
+// <li>\c blaze::cuint64: Packed SIMD type for complex 64-bit unsigned integral data types</li>
+// <li>\c blaze::cfloat: Packed SIMD type for complex single precision floating point data</li>
+// <li>\c blaze::cdouble: Packed SIMD type for complex double precision floating point data</li>
+// </ul>
+// </li>
+// </ul>
+//
+// All SIMD types provide the \c value data member for a direct access to the underlying intrinsic
+// data element. In the following example, this intrinsic element is passed to the AVX function
+// \c _mm256_sqrt_pd():
+
+ \code
+ struct Sqrt
+ {
+ double operator()( double a ) const
+ {
+ return std::sqrt( a );
+ }
+
+ simd_double_t load( simd_double_t a ) const
+ {
+ return _mm256_sqrt_pd( a.value );
+ }
+ };
+ \endcode
+
+// In this example, whenever vectorization is generally applicable, the \c load() function is
+// called instead of the function call operator for as long as the number of remaining elements
+// is larger-or-equal to the width of the packed SIMD type. In all other cases (which also
+// includes peel-off and remainder loops) the scalar operation is used.
+//
+// Please note that this example has two drawbacks: First, it will only compile in case the
+// intrinsic \c _mm256_sqrt_pd() function is available (i.e. when AVX is active). Second, the
+// availability of AVX is not taken into account. The first drawback can be alleviated by making
+// the \c load() function a function template. The second drawback can be dealt with by adding a
+// \c simdEnabled() function template to the functor:
+
+ \code
+ struct Sqrt
+ {
+ double operator()( double a ) const
+ {
+ return std::sqrt( a );
+ }
+
+ template< typename T >
+ T load( T a ) const
+ {
+ return _mm256_sqrt_pd( a.value );
+ }
+
+ template< typename T >
+ static constexpr bool simdEnabled() {
+#if defined(__AVX__)
+ return true;
+#else
+ return false;
+#endif
+ }
+ };
+ \endcode
+
+// The \c simdEnabled() function must be a \c static, \c constexpr function and must return whether
+// or not vectorization is available for the given data type \c T. In case the function returns
+// \c true, the \c load() function is used for a vectorized evaluation, in case the function
+// returns \c false, \c load() is not called.
+//
+// Note that this is a simplified example that is only working when used for dense vectors and
+// matrices with double precision floating point elements. The following code shows the complete
+// implementation of the according functor that is used within the \b Blaze library. The \b Blaze
+// \c Sqrt functor is working for all data types that are providing a square root operation:
+
+ \code
+ namespace blaze {
+
+ struct Sqrt
+ {
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( sqrt( a ) )
+ {
+ return sqrt( a );
+ }
+
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDSqrt<T>::value; }
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( sqrt( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_TYPE( T );
+ return sqrt( a );
+ }
+ };
+
+ } // namespace blaze
+ \endcode
+
+// For more information on the available \b Blaze SIMD data types and functions, please see the
+// SIMD module in the complete \b Blaze documentation.
+//
+// \n Previous: \ref matrix_matrix_multiplication &nbsp; &nbsp; Next: \ref shared_memory_parallelization
+*/
+//*************************************************************************************************
+
+
+//**Shared Memory Parallelization******************************************************************
+/*!\page shared_memory_parallelization Shared Memory Parallelization
+//
+// One of the main motivations of the \b Blaze 1.x releases was to achieve maximum performance
+// on a single CPU core for all possible operations. However, today's CPUs are not single core
+// anymore, but provide several (homogeneous or heterogeneous) compute cores. In order to fully
+// exploit the performance potential of a multicore CPU, computations have to be parallelized
+// across all available cores of a CPU. For this purpose, \b Blaze provides three different
+// shared memory parallelization techniques:
+//
+// - \ref openmp_parallelization
+// - \ref cpp_threads_parallelization
+// - \ref boost_threads_parallelization
+//
+// In addition, \b Blaze provides means to enforce the serial execution of specific operations:
+//
+// - \ref serial_execution
+//
+// \n Previous: \ref custom_operations &nbsp; &nbsp; Next: \ref openmp_parallelization
+*/
+//*************************************************************************************************
+
+
+//**OpenMP Parallelization*************************************************************************
+/*!\page openmp_parallelization OpenMP Parallelization
+//
+// \tableofcontents
+//
+//
+// \n \section openmp_setup OpenMP Setup
+// <hr>
+//
+// To enable the OpenMP-based parallelization, all that needs to be done is to explicitly specify
+// the use of OpenMP on the command line:
+
+ \code
+ -fopenmp // GNU C++ compiler
+ -openmp // Intel C++ compiler
+ /openmp // Visual Studio
+ \endcode
+
+// This simple action will cause the \b Blaze library to automatically try to run all operations
+// in parallel with the specified number of threads.
+//
+// As common for OpenMP, the number of threads can be specified either via an environment variable
+
+ \code
+ export OMP_NUM_THREADS=4 // Unix systems
+ set OMP_NUM_THREADS=4 // Windows systems
+ \endcode
+
+// or via an explicit call to the \c omp_set_num_threads() function:
+
+ \code
+ omp_set_num_threads( 4 );
+ \endcode
+
+// Alternatively, the number of threads can also be specified via the \c setNumThreads() function
+// provided by the \b Blaze library:
+
+ \code
+ blaze::setNumThreads( 4 );
+ \endcode
+
+// Please note that the \b Blaze library does not limit the available number of threads. Therefore
+// it is in YOUR responsibility to choose an appropriate number of threads. The best performance,
+// though, can be expected if the specified number of threads matches the available number of
+// cores.
+//
+// In order to query the number of threads used for the parallelization of operations, the
+// \c getNumThreads() function can be used:
+
+ \code
+ const size_t threads = blaze::getNumThreads();
+ \endcode
+
+// In the context of OpenMP, the function returns the maximum number of threads OpenMP will use
+// within a parallel region and is therefore equivalent to the \c omp_get_max_threads() function.
+//
+//
+// \n \section openmp_configuration OpenMP Configuration
+// <hr>
+//
+// Note that \b Blaze is not unconditionally running an operation in parallel. In case \b Blaze
+// deems the parallel execution as counterproductive for the overall performance, the operation
+// is executed serially. One of the main reasons for not executing an operation in parallel is
+// the size of the operands. For instance, a vector addition is only executed in parallel if the
+// size of both vector operands exceeds a certain threshold. Otherwise, the performance could
+// seriously decrease due to the overhead caused by the thread setup. However, in order to be
+// able to adjust the \b Blaze library to a specific system, it is possible to configure these
+// thresholds manually. All shared memory thresholds are contained within the configuration file
+// <tt>./blaze/config/Thresholds.h</tt>.
+//
+// Please note that these thresholds are highly sensitiv to the used system architecture and
+// the shared memory parallelization technique (see also \ref cpp_threads_parallelization and
+// \ref boost_threads_parallelization). Therefore the default values cannot guarantee maximum
+// performance for all possible situations and configurations. They merely provide a reasonable
+// standard for the current CPU generation.
+//
+//
+// \n \section openmp_first_touch First Touch Policy
+// <hr>
+//
+// So far the \b Blaze library does not (yet) automatically initialize dynamic memory according
+// to the first touch principle. Consider for instance the following vector triad example:
+
+ \code
+ using blaze::columnVector;
+
+ const size_t N( 1000000UL );
+
+ blaze::DynamicVector<double,columnVector> a( N ), b( N ), c( N ), d( N );
+
+ // Initialization of the vectors b, c, and d
+ for( size_t i=0UL; i<N; ++i ) {
+ b[i] = rand<double>();
+ c[i] = rand<double>();
+ d[i] = rand<double>();
+ }
+
+ // Performing a vector triad
+ a = b + c * d;
+ \endcode
+
+// If this code, which is prototypical for many OpenMP applications that have not been optimized
+// for ccNUMA architectures, is run across several locality domains (LD), it will not scale
+// beyond the maximum performance achievable on a single LD if the working set does not fit into
+// the cache. This is because the initialization loop is executed by a single thread, writing to
+// \c b, \c c, and \c d for the first time. Hence, all memory pages belonging to those arrays will
+// be mapped into a single LD.
+//
+// As mentioned above, this problem can be solved by performing vector initialization in parallel:
+
+ \code
+ // ...
+
+ // Initialization of the vectors b, c, and d
+ #pragma omp parallel for
+ for( size_t i=0UL; i<N; ++i ) {
+ b[i] = rand<double>();
+ c[i] = rand<double>();
+ d[i] = rand<double>();
+ }
+
+ // ...
+ \endcode
+
+// This simple modification makes a huge difference on ccNUMA in memory-bound situations (as for
+// instance in all BLAS level 1 operations and partially BLAS level 2 operations). Therefore, in
+// order to achieve the maximum possible performance, it is imperative to initialize the memory
+// according to the later use of the data structures.
+//
+//
+// \n \section openmp_limitations Limitations of the OpenMP Parallelization
+// <hr>
+//
+// There are a few important limitations to the current \b Blaze OpenMP parallelization. The first
+// one involves the explicit use of an OpenMP parallel region (see \ref openmp_parallel), the
+// other one the OpenMP \c sections directive (see \ref openmp_sections).
+//
+//
+// \n \subsection openmp_parallel The Parallel Directive
+//
+// In OpenMP threads are explicitly spawned via the an OpenMP parallel directive:
+
+ \code
+ // Serial region, executed by a single thread
+
+ #pragma omp parallel
+ {
+ // Parallel region, executed by the specified number of threads
+ }
+
+ // Serial region, executed by a single thread
+ \endcode
+
+// Conceptually, the specified number of threads (see \ref openmp_setup) is created every time a
+// parallel directive is encountered. Therefore, from a performance point of view, it seems to be
+// beneficial to use a single OpenMP parallel directive for several operations:
+
+ \code
+ blaze::DynamicVector<double> x, y1, y2;
+ blaze::DynamicMatrix<double> A, B;
+
+ #pragma omp parallel
+ {
+ y1 = A * x;
+ y2 = B * x;
+ }
+ \endcode
+
+// Unfortunately, this optimization approach is not allowed within the \b Blaze library. More
+// explicitly, it is not allowed to put an operation into a parallel region. The reason is that
+// the entire code contained within a parallel region is executed by all threads. Although this
+// appears to just comprise the contained computations, a computation (or more specifically the
+// assignment of an expression to a vector or matrix) can contain additional logic that must not
+// be handled by multiple threads (as for instance memory allocations, setup of temporaries, etc.).
+// Therefore it is not possible to manually start a parallel region for several operations, but
+// \b Blaze will spawn threads automatically, depending on the specifics of the operation at hand
+// and the given operands.
+//
+// \n \subsection openmp_sections The Sections Directive
+//
+// OpenMP provides several work-sharing construct to distribute work among threads. One of these
+// constructs is the \c sections directive:
+
+ \code
+ blaze::DynamicVector<double> x, y1, y2;
+ blaze::DynamicMatrix<double> A, B;
+
+ // ... Resizing and initialization
+
+ #pragma omp sections
+ {
+ #pragma omp section
+
+ y1 = A * x;
+
+ #pragma omp section
+
+ y2 = B * x;
+
+ }
+ \endcode
+
+// In this example, two threads are used to compute two distinct matrix/vector multiplications
+// concurrently. Thereby each of the \c sections is executed by exactly one thread.
+//
+// Unfortunately \b Blaze does not support concurrent parallel computations and therefore this
+// approach does not work with any of the \b Blaze parallelization techniques. All techniques
+// (including the C++11 and Boost thread parallelizations; see \ref cpp_threads_parallelization
+// and \ref boost_threads_parallelization) are optimized for the parallel computation of an
+// operation within a single thread of execution. This means that \b Blaze tries to use all
+// available threads to compute the result of a single operation as efficiently as possible.
+// Therefore, for this special case, it is advisable to disable all \b Blaze parallelizations
+// and to let \b Blaze compute all operations within a \c sections directive in serial. This can
+// be done by either completely disabling the \b Blaze parallelization (see \ref serial_execution)
+// or by selectively serializing all operations within a \c sections directive via the \c serial()
+// function:
+
+ \code
+ blaze::DynamicVector<double> x, y1, y2;
+ blaze::DynamicMatrix<double> A, B;
+
+ // ... Resizing and initialization
+
+ #pragma omp sections
+ {
+ #pragma omp section
+
+ y1 = serial( A * x );
+
+ #pragma omp section
+
+ y2 = serial( B * x );
+
+ }
+ \endcode
+
+// Please note that the use of the \c BLAZE_SERIAL_SECTION (see also \ref serial_execution) does
+// NOT work in this context!
+//
+// \n Previous: \ref shared_memory_parallelization &nbsp; &nbsp; Next: \ref cpp_threads_parallelization
+*/
+//*************************************************************************************************
+
+
+//**C++11 Thread Parallelization*******************************************************************
+/*!\page cpp_threads_parallelization C++11 Thread Parallelization
+//
+// \tableofcontents
+//
+//
+// In addition to the OpenMP-based shared memory parallelization, starting with \b Blaze 2.1,
+// \b Blaze also provides a shared memory parallelization based on C++11 threads.
+//
+//
+// \n \section cpp_threads_setup C++11 Thread Setup
+// <hr>
+//
+// In order to enable the C++11 thread-based parallelization, first the according C++11-specific
+// compiler flags have to be used and second the \c BLAZE_USE_CPP_THREADS command line argument
+// has to be explicitly specified. For instance, in case of the GNU C++ and Clang compilers the
+// compiler flags have to be extended by
+
+ \code
+ ... -std=c++11 -DBLAZE_USE_CPP_THREADS ...
+ \endcode
+
+// This simple action will cause the \b Blaze library to automatically try to run all operations
+// in parallel with the specified number of C++11 threads. Note that in case both OpenMP and C++11
+// threads are enabled on the command line, the OpenMP-based parallelization has priority and
+// is preferred.
+//
+// The number of threads can be either specified via the environment variable \c BLAZE_NUM_THREADS
+
+ \code
+ export BLAZE_NUM_THREADS=4 // Unix systems
+ set BLAZE_NUM_THREADS=4 // Windows systems
+ \endcode
+
+// or alternatively via the \c setNumThreads() function provided by the \b Blaze library:
+
+ \code
+ blaze::setNumThreads( 4 );
+ \endcode
+
+// Please note that the \b Blaze library does not limit the available number of threads. Therefore
+// it is in YOUR responsibility to choose an appropriate number of threads. The best performance,
+// though, can be expected if the specified number of threads matches the available number of
+// cores.
+//
+// In order to query the number of threads used for the parallelization of operations, the
+// \c getNumThreads() function can be used:
+
+ \code
+ const size_t threads = blaze::getNumThreads();
+ \endcode
+
+// In the context of C++11 threads, the function will return the previously specified number of
+// threads.
+//
+//
+// \n \section cpp_threads_configuration C++11 Thread Configuration
+// <hr>
+//
+// As in case of the OpenMP-based parallelization \b Blaze is not unconditionally running an
+// operation in parallel. In case \b Blaze deems the parallel execution as counterproductive for
+// the overall performance, the operation is executed serially. One of the main reasons for not
+// executing an operation in parallel is the size of the operands. For instance, a vector addition
+// is only executed in parallel if the size of both vector operands exceeds a certain threshold.
+// Otherwise, the performance could seriously decrease due to the overhead caused by the thread
+// setup. However, in order to be able to adjust the \b Blaze library to a specific system, it
+// is possible to configure these thresholds manually. All thresholds are contained within the
+// configuration file <tt>./blaze/config/Thresholds.h</tt>.
+//
+// Please note that these thresholds are highly sensitiv to the used system architecture and
+// the shared memory parallelization technique. Therefore the default values cannot guarantee
+// maximum performance for all possible situations and configurations. They merely provide a
+// reasonable standard for the current CPU generation. Also note that the provided defaults
+// have been determined using the OpenMP parallelization and require individual adaption for
+// the C++11 thread parallelization.
+//
+//
+// \n \section cpp_threads_known_issues Known Issues
+// <hr>
+//
+// There is a known issue in Visual Studio 2012 and 2013 that may cause C++11 threads to hang
+// if their destructor is executed after the \c main() function:
+//
+// http://connect.microsoft.com/VisualStudio/feedback/details/747145
+//
+// Unfortunately, the C++11 parallelization of the \b Blaze library is affected from this bug.
+// In order to circumvent this problem, \b Blaze provides the \c shutDownThreads() function,
+// which can be used to manually destroy all threads at the end of the \c main() function:
+
+ \code
+ int main()
+ {
+ // ... Using the C++11 thread parallelization of Blaze
+
+ shutDownThreads();
+ }
+ \endcode
+
+// Please note that this function may only be used at the end of the \c main() function. After
+// this function no further computation may be executed! Also note that this function has an
+// effect for Visual Studio compilers only and doesn't need to be used with any other compiler.
+//
+// \n Previous: \ref openmp_parallelization &nbsp; &nbsp; Next: \ref boost_threads_parallelization
+*/
+//*************************************************************************************************
+
+
+//**Boost Thread Parallelization*******************************************************************
+/*!\page boost_threads_parallelization Boost Thread Parallelization
+//
+// \tableofcontents
+//
+//
+// The third available shared memory parallelization provided with \b Blaze is based on Boost
+// threads.
+//
+//
+// \n \section boost_threads_setup Boost Thread Setup
+// <hr>
+//
+// In order to enable the Boost thread-based parallelization, two steps have to be taken: First,
+// the \c BLAZE_USE_BOOST_THREADS command line argument has to be explicitly specified during
+// compilation:
+
+ \code
+ ... -DBLAZE_USE_BOOST_THREADS ...
+ \endcode
+
+// Second, the according Boost libraries have to be linked. These two simple actions will cause
+// the \b Blaze library to automatically try to run all operations in parallel with the specified
+// number of Boost threads. Note that the OpenMP-based and C++11 thread-based parallelizations
+// have priority, i.e. are preferred in case either is enabled in combination with the Boost
+// thread parallelization.
+//
+// The number of threads can be either specified via the environment variable \c BLAZE_NUM_THREADS
+
+ \code
+ export BLAZE_NUM_THREADS=4 // Unix systems
+ set BLAZE_NUM_THREADS=4 // Windows systems
+ \endcode
+
+// or alternatively via the \c setNumThreads() function provided by the \b Blaze library:
+
+ \code
+ blaze::setNumThreads( 4 );
+ \endcode
+
+// Please note that the \b Blaze library does not limit the available number of threads. Therefore
+// it is in YOUR responsibility to choose an appropriate number of threads. The best performance,
+// though, can be expected if the specified number of threads matches the available number of
+// cores.
+//
+// In order to query the number of threads used for the parallelization of operations, the
+// \c getNumThreads() function can be used:
+
+ \code
+ const size_t threads = blaze::getNumThreads();
+ \endcode
+
+// In the context of Boost threads, the function will return the previously specified number of
+// threads.
+//
+//
+// \n \section boost_threads_configuration Boost Thread Configuration
+// <hr>
+//
+// As in case of the other shared memory parallelizations \b Blaze is not unconditionally running
+// an operation in parallel (see \ref openmp_parallelization or \ref cpp_threads_parallelization).
+// All thresholds related to the Boost thread parallelization are also contained within the
+// configuration file <tt>./blaze/config/Thresholds.h</tt>.
+//
+// Please note that these thresholds are highly sensitiv to the used system architecture and
+// the shared memory parallelization technique. Therefore the default values cannot guarantee
+// maximum performance for all possible situations and configurations. They merely provide a
+// reasonable standard for the current CPU generation. Also note that the provided defaults
+// have been determined using the OpenMP parallelization and require individual adaption for
+// the Boost thread parallelization.
+//
+// \n Previous: \ref cpp_threads_parallelization &nbsp; &nbsp; Next: \ref serial_execution
+*/
+//*************************************************************************************************
+
+
+//**Serial Execution*******************************************************************************
+/*!\page serial_execution Serial Execution
+//
+// Sometimes it may be necessary to enforce the serial execution of specific operations. For this
+// purpose, the \b Blaze library offers three possible options: the serialization of a single
+// expression via the \c serial() function, the serialization of a block of expressions via the
+// \c BLAZE_SERIAL_SECTION, and the general deactivation of the parallel execution.
+//
+//
+// \n \section serial_execution_serial_expression Option 1: Serialization of a Single Expression
+// <hr>
+//
+// The first option is the serialization of a specific operation via the \c serial() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B, C;
+ // ... Resizing and initialization
+ C = serial( A + B );
+ \endcode
+
+// \c serial() enforces the serial evaluation of the enclosed expression. It can be used on any
+// kind of dense or sparse vector or matrix expression.
+//
+//
+// \n \section serial_execution_serial_section Option 2: Serialization of Multiple Expressions
+// <hr>
+//
+// The second option is the temporary and local enforcement of a serial execution via the
+// \c BLAZE_SERIAL_SECTION:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ blaze::DynamicMatrix<double,rowMajor> A;
+ blaze::DynamicVector<double,columnVector> b, c, d, x, y, z;
+
+ // ... Resizing and initialization
+
+ // Parallel execution
+ // If possible and beneficial for performance the following operation is executed in parallel.
+ x = A * b;
+
+ // Serial execution
+ // All operations executed within the serial section are guaranteed to be executed in
+ // serial (even if a parallel execution would be possible and/or beneficial).
+ BLAZE_SERIAL_SECTION
+ {
+ y = A * c;
+ z = A * d;
+ }
+
+ // Parallel execution continued
+ // ...
+ \endcode
+
+// Within the scope of the \c BLAZE_SERIAL_SECTION, all operations are guaranteed to run in serial.
+// Outside the scope of the serial section, all operations are run in parallel (if beneficial for
+// the performance).
+//
+// Note that the \c BLAZE_SERIAL_SECTION must only be used within a single thread of execution.
+// The use of the serial section within several concurrent threads will result undefined behavior!
+//
+//
+// \n \section serial_execution_deactivate_parallelism Option 3: Deactivation of Parallel Execution
+// <hr>
+//
+// The third option is the general deactivation of the parallel execution (even in case OpenMP is
+// enabled on the command line). This can be achieved via the \c BLAZE_USE_SHARED_MEMORY_PARALLELIZATION
+// switch in the <tt>./blaze/config/SMP.h</tt> configuration file:
+
+ \code
+ #define BLAZE_USE_SHARED_MEMORY_PARALLELIZATION 1
+ \endcode
+
+// In case the \c BLAZE_USE_SHARED_MEMORY_PARALLELIZATION switch is set to 0, the shared memory
+// parallelization is deactivated altogether.
+//
+// \n Previous: \ref boost_threads_parallelization &nbsp; &nbsp; Next: \ref serialization
+*/
+//*************************************************************************************************
+
+
+//**Serialization**********************************************************************************
+/*!\page serialization Serialization
+//
+// Sometimes it is necessary to store vector and/or matrices on disk, for instance for storing
+// results or for sharing specific setups with other people. The \b Blaze math serialization
+// module provides the according functionality to create platform independent, portable, binary
+// representations of vectors and matrices that can be used to store the \b Blaze data structures
+// without loss of precision and to reliably transfer them from one machine to another.
+//
+// The following two pages explain how to serialize vectors and matrices:
+//
+// - \ref vector_serialization
+// - \ref matrix_serialization
+//
+// \n Previous: \ref serial_execution &nbsp; &nbsp; Next: \ref vector_serialization
+*/
+//*************************************************************************************************
+
+
+//**Vector Serialization***************************************************************************
+/*!\page vector_serialization Vector Serialization
+//
+// The following example demonstrates the (de-)serialization of dense and sparse vectors:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ // Serialization of both vectors
+ {
+ blaze::StaticVector<double,5UL,rowVector> d;
+ blaze::CompressedVector<int,columnVector> s;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "vectors.blaze"
+ blaze::Archive<std::ofstream> archive( "vectors.blaze" );
+
+ // Serialization of both vectors into the same archive. Note that d lies before s!
+ archive << d << s;
+ }
+
+ // Reconstitution of both vectors
+ {
+ blaze::DynamicVector<double,rowVector> d1;
+ blaze::DynamicVector<int,rowVector> d2;
+
+ // Creating an archive that reads from the file "vectors.blaze"
+ blaze::Archive<std::ifstream> archive( "vectors.blaze" );
+
+ // Reconstituting the former d vector into d1. Note that it is possible to reconstitute
+ // the vector into a differrent kind of vector (StaticVector -> DynamicVector), but that
+ // the type of elements has to be the same.
+ archive >> d1;
+
+ // Reconstituting the former s vector into d2. Note that is is even possible to reconstitute
+ // a sparse vector as a dense vector (also the reverse is possible) and that a column vector
+ // can be reconstituted as row vector (and vice versa). Note however that also in this case
+ // the type of elements is the same!
+ archive >> d2
+ }
+ \endcode
+
+// The (de-)serialization of vectors is not restricted to vectors of built-in data type, but can
+// also be used for vectors with vector or matrix element type:
+
+ \code
+ // Serialization
+ {
+ blaze::CompressedVector< blaze::DynamicVector< blaze::complex<double> > > vec;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "vector.blaze"
+ blaze::Archive<std::ofstream> archive( "vector.blaze" );
+
+ // Serialization of the vector into the archive
+ archive << vec;
+ }
+
+ // Deserialization
+ {
+ blaze::CompressedVector< blaze::DynamicVector< blaze::complex<double> > > vec;
+
+ // Creating an archive that reads from the file "vector.blaze"
+ blaze::Archive<std::ifstream> archive( "vector.blaze" );
+
+ // Reconstitution of the vector from the archive
+ archive >> vec;
+ }
+ \endcode
+
+// As the examples demonstrates, the vector serialization offers an enormous flexibility. However,
+// several actions result in errors:
+//
+// - vectors cannot be reconstituted as matrices (and vice versa)
+// - the element type of the serialized and reconstituted vector must match, which means
+// that on the source and destination platform the general type (signed/unsigned integral
+// or floating point) and the size of the type must be exactly the same
+// - when reconstituting a \c StaticVector, its size must match the size of the serialized vector
+//
+// In case an error is encountered during (de-)serialization, a \c std::runtime_exception is
+// thrown.
+//
+// \n Previous: \ref serialization &nbsp; &nbsp; Next: \ref matrix_serialization
+*/
+//*************************************************************************************************
+
+
+//**Matrix Serialization***************************************************************************
+/*!\page matrix_serialization Matrix Serialization
+//
+// The serialization of matrices works in the same manner as the serialization of vectors. The
+// following example demonstrates the (de-)serialization of dense and sparse matrices:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Serialization of both matrices
+ {
+ blaze::StaticMatrix<double,3UL,5UL,rowMajor> D;
+ blaze::CompressedMatrix<int,columnMajor> S;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "matrices.blaze"
+ blaze::Archive<std::ofstream> archive( "matrices.blaze" );
+
+ // Serialization of both matrices into the same archive. Note that D lies before S!
+ archive << D << S;
+ }
+
+ // Reconstitution of both matrices
+ {
+ blaze::DynamicMatrix<double,rowMajor> D1;
+ blaze::DynamicMatrix<int,rowMajor> D2;
+
+ // Creating an archive that reads from the file "matrices.blaze"
+ blaze::Archive<std::ifstream> archive( "matrices.blaze" );
+
+ // Reconstituting the former D matrix into D1. Note that it is possible to reconstitute
+ // the matrix into a differrent kind of matrix (StaticMatrix -> DynamicMatrix), but that
+ // the type of elements has to be the same.
+ archive >> D1;
+
+ // Reconstituting the former S matrix into D2. Note that is is even possible to reconstitute
+ // a sparse matrix as a dense matrix (also the reverse is possible) and that a column-major
+ // matrix can be reconstituted as row-major matrix (and vice versa). Note however that also
+ // in this case the type of elements is the same!
+ archive >> D2
+ }
+ \endcode
+
+// Note that also in case of matrices it is possible to (de-)serialize matrices with vector or
+// matrix elements:
+
+ \code
+ // Serialization
+ {
+ blaze::CompressedMatrix< blaze::DynamicMatrix< blaze::complex<double> > > mat;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "matrix.blaze"
+ blaze::Archive<std::ofstream> archive( "matrix.blaze" );
+
+ // Serialization of the matrix into the archive
+ archive << mat;
+ }
+
+ // Deserialization
+ {
+ blaze::CompressedMatrix< blaze::DynamicMatrix< blaze::complex<double> > > mat;
+
+ // Creating an archive that reads from the file "matrix.blaze"
+ blaze::Archive<std::ifstream> archive( "matrix.blaze" );
+
+ // Reconstitution of the matrix from the archive
+ archive >> mat;
+ }
+ \endcode
+
+// Note that just as the vector serialization, the matrix serialization is restricted by a
+// few important rules:
+//
+// - matrices cannot be reconstituted as vectors (and vice versa)
+// - the element type of the serialized and reconstituted matrix must match, which means
+// that on the source and destination platform the general type (signed/unsigned integral
+// or floating point) and the size of the type must be exactly the same
+// - when reconstituting a \c StaticMatrix, the number of rows and columns must match those
+// of the serialized matrix
+//
+// In case an error is encountered during (de-)serialization, a \c std::runtime_exception is
+// thrown.
+//
+// \n Previous: \ref vector_serialization &nbsp; &nbsp; Next: \ref blas_functions \n
+*/
+//*************************************************************************************************
+
+
+//**BLAS Functions*********************************************************************************
+/*!\page blas_functions BLAS Functions
+//
+// \tableofcontents
+//
+//
+// For vector/vector, matrix/vector and matrix/matrix multiplications with large dense matrices
+// \b Blaze relies on the efficiency of BLAS libraries. For this purpose, \b Blaze implements
+// several convenient C++ wrapper functions for several BLAS functions. The following sections
+// give a complete overview of all available BLAS level 1, 2 and 3 functions.
+//
+//
+// \n \section blas_level_1 BLAS Level 1
+// <hr>
+//
+// \subsection blas_level_1_dot Dot Product (dot)
+//
+// The following wrapper functions provide a generic interface for the BLAS functions for the
+// dot product of two dense vectors (\c sdot(), \c ddot(), \c cdotu_sub(), and \c zdotu_sub()):
+
+ \code
+ namespace blaze {
+
+ float dot( const int n, const float* x, const int incX, const float* y, const int incY );
+
+ double dot( const int n, const double* x, const int incX, const double* y, const int incY );
+
+ complex<float> dot( const int n, const complex<float>* x, const int incX,
+ const complex<float>* y, const int incY );
+
+ complex<double> dot( const int n, const complex<double>* x, const int incX,
+ const complex<double>* y, const int incY );
+
+ template< typename VT1, bool TF1, typename VT2, bool TF2 >
+ ElementType_<VT1> dot( const DenseVector<VT1,TF1>& x, const DenseVector<VT2,TF2>& y );
+
+ } // namespace blaze
+ \endcode
+
+// \n \section blas_level_2 BLAS Level 2
+// <hr>
+//
+// \subsection blas_level_2_gemv General Matrix/Vector Multiplication (gemv)
+//
+// The following wrapper functions provide a generic interface for the BLAS functions for the
+// general matrix/vector multiplication (\c sgemv(), \c dgemv(), \c cgemv(), and \c zgemv()):
+
+ \code
+ namespace blaze {
+
+ void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n, float alpha,
+ const float* A, int lda, const float* x, int incX,
+ float beta, float* y, int incY );
+
+ void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n, double alpha,
+ const double* A, int lda, const double* x, int incX,
+ double beta, double* y, int incY );
+
+ void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n, complex<float> alpha,
+ const complex<float>* A, int lda, const complex<float>* x, int incX,
+ complex<float> beta, complex<float>* y, int incY );
+
+ void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n, complex<double> alpha,
+ const complex<double>* A, int lda, const complex<double>* x, int incX,
+ complex<double> beta, complex<double>* y, int incY );
+
+ template< typename VT1, typename MT1, bool SO, typename VT2, typename ST >
+ void gemv( DenseVector<VT1,false>& y, const DenseMatrix<MT1,SO>& A,
+ const DenseVector<VT2,false>& x, ST alpha, ST beta );
+
+ template< typename VT1, typename VT2, typename MT1, bool SO, typename ST >
+ void gemv( DenseVector<VT1,true>& y, const DenseVector<VT2,true>& x,
+ const DenseMatrix<MT1,SO>& A, ST alpha, ST beta );
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection blas_level_2_trmv Triangular Matrix/Vector Multiplication (trmv)
+//
+// The following wrapper functions provide a generic interface for the BLAS functions for the
+// matrix/vector multiplication with a triangular matrix (\c strmv(), \c dtrmv(), \c ctrmv(),
+// and \c ztrmv()):
+
+ \code
+ namespace blaze {
+
+ void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA, CBLAS_DIAG diag,
+ int n, const float* A, int lda, float* x, int incX );
+
+ void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA, CBLAS_DIAG diag,
+ int n, const double* A, int lda, double* x, int incX );
+
+ void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA, CBLAS_DIAG diag,
+ int n, const complex<float>* A, int lda, complex<float>* x, int incX );
+
+ void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA, CBLAS_DIAG diag,
+ int n, const complex<double>* A, int lda, complex<double>* x, int incX );
+
+ template< typename VT, typename MT, bool SO >
+ void trmv( DenseVector<VT,false>& x, const DenseMatrix<MT,SO>& A, CBLAS_UPLO uplo );
+
+ template< typename VT, typename MT, bool SO >
+ void trmv( DenseVector<VT,true>& x, const DenseMatrix<MT,SO>& A, CBLAS_UPLO uplo );
+
+ } // namespace blaze
+ \endcode
+
+// \n \section blas_level_3 BLAS Level 3
+// <hr>
+//
+// \subsection blas_level_3_gemm General Matrix/Matrix Multiplication (gemm)
+//
+// The following wrapper functions provide a generic interface for the BLAS functions for the
+// general matrix/matrix multiplication (\c sgemm(), \c dgemm(), \c cgemm(), and \c zgemm()):
+
+ \code
+ namespace blaze {
+
+ void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, float alpha, const float* A, int lda,
+ const float* B, int ldb, float beta, float* C, int ldc );
+
+ void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, double alpha, const double* A, int lda,
+ const double* B, int ldb, double beta, float* C, int ldc );
+
+ void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, complex<float> alpha, const complex<float>* A, int lda,
+ const complex<float>* B, int ldb, complex<float> beta, float* C, int ldc );
+
+ void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, complex<double> alpha, const complex<double>* A, int lda,
+ const complex<double>* B, int ldb, complex<double> beta, float* C, int ldc );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2, typename MT3, bool SO3, typename ST >
+ void gemm( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ const DenseMatrix<MT3,SO3>& B, ST alpha, ST beta );
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection blas_level_3_trmm Triangular Matrix/Matrix Multiplication (trmm)
+//
+// The following wrapper functions provide a generic interface for the BLAS functions for the
+// matrix/matrix multiplication with a triangular matrix (\c strmm(), \c dtrmm(), \c ctrmm(), and
+// \c ztrmm()):
+
+ \code
+ namespace blaze {
+
+ void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int m, int n, float alpha, const float* A,
+ int lda, float* B, int ldb );
+
+ void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int m, int n, double alpha, const double* A,
+ int lda, double* B, int ldb );
+
+ void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int m, int n, complex<float> alpha, const complex<float>* A,
+ int lda, complex<float>* B, int ldb );
+
+ void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int m, int n, complex<double> alpha, const complex<double>* A,
+ int lda, complex<double>* B, int ldb );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2, typename ST >
+ void trmm( DenseMatrix<MT1,SO1>& B, const DenseMatrix<MT2,SO2>& A,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha );
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection blas_level_3_trsm Triangular System Solver (trsm)
+//
+// The following wrapper functions provide a generic interface for the BLAS functions for solving
+// a triangular system of equations (\c strsm(), \c dtrsm(), \c ctrsm(), and \c ztrsm()):
+
+ \code
+ namespace blaze {
+
+ void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int m, int n, float alpha, const float* A,
+ int lda, float* B, int ldb );
+
+ void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int m, int n, double alpha, const double* A,
+ int lda, double* B, int ldb );
+
+ void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int m, int n, complex<float> alpha, const complex<float>* A,
+ int lda, complex<float>* B, int ldb );
+
+ void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int m, int n, complex<double> alpha, const complex<double>* A,
+ int lda, complex<double>* B, int ldb );
+
+ template< typename MT, bool SO, typename VT, bool TF, typename ST >
+ void trsm( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2, typename ST >
+ void trsm( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha );
+
+ } // namespace blaze
+ \endcode
+
+// \n Previous: \ref matrix_serialization &nbsp; &nbsp; Next: \ref lapack_functions \n
+*/
+//*************************************************************************************************
+
+
+//**LAPACK Functions*******************************************************************************
+/*!\page lapack_functions LAPACK Functions
+//
+// \tableofcontents
+//
+//
+// The \b Blaze library makes extensive use of the LAPACK functionality for various compute tasks
+// (including the decomposition, inversion and the computation of the determinant of dense matrices).
+// For this purpose, \b Blaze implements several convenient C++ wrapper functions for all required
+// LAPACK functions. The following sections give a complete overview of all available LAPACK wrapper
+// functions. For more details on the individual LAPACK functions see the \b Blaze function
+// documentation or the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note All functions only work for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// adaptors or matrices of any other element type results in a compile time error!
+//
+// \note All functions can only be used if the fitting LAPACK library is available and linked to
+// the final executable. Otherwise a call to this function will result in a linker error.
+//
+// \note For performance reasons all functions do only provide the basic exception safety guarantee,
+// i.e. in case an exception is thrown the given matrix may already have been modified.
+//
+//
+// \n \section lapack_decomposition Matrix Decomposition
+// <hr>
+//
+// The following functions decompose/factorize the given dense matrix. Based on this decomposition
+// the matrix can be inverted or used to solve a linear system of equations.
+//
+//
+// \n \subsection lapack_lu_decomposition LU Decomposition
+//
+// The following functions provide an interface for the LAPACK functions \c sgetrf(), \c dgetrf(),
+// \c cgetrf(), and \c zgetrf(), which compute the LU decomposition for the given general matrix:
+
+ \code
+ namespace blaze {
+
+ void getrf( int m, int n, float* A, int lda, int* ipiv, int* info );
+
+ void getrf( int m, int n, double* A, int lda, int* ipiv, int* info );
+
+ void getrf( int m, int n, complex<float>* A, int lda, int* ipiv, int* info );
+
+ void getrf( int m, int n, complex<double>* A, int lda, int* ipiv, int* info );
+
+ template< typename MT, bool SO >
+ void getrf( DenseMatrix<MT,SO>& A, int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// The decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]\n
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix, and \c U is an upper
+// triangular matrix. The resulting decomposition is stored within \a A: In case of a column-major
+// matrix, \c L is stored in the lower part of \a A and \c U is stored in the upper part. The unit
+// diagonal elements of \c L are not stored. In case \a A is a row-major matrix the result is
+// transposed.
+//
+// \note The LU decomposition will never fail, even for singular matrices. However, in case of a
+// singular matrix the resulting decomposition cannot be used for a matrix inversion or solving
+// a linear system of equations.
+//
+//
+// \n \subsection lapack_ldlt_decomposition LDLT Decomposition
+//
+// The following functions provide an interface for the LAPACK functions \c ssytrf(), \c dsytrf(),
+// \c csytrf(), and \c zsytrf(), which compute the LDLT (Bunch-Kaufman) decomposition for the given
+// symmetric indefinite matrix:
+
+ \code
+ namespace blaze {
+
+ void sytrf( char uplo, int n, float* A, int lda, int* ipiv, float* work, int lwork, int* info );
+
+ void sytrf( char uplo, int n, double* A, int lda, int* ipiv, double* work, int lwork, int* info );
+
+ void sytrf( char uplo, int n, complex<float>* A, int lda, int* ipiv, complex<float>* work, int lwork, int* info );
+
+ void sytrf( char uplo, int n, complex<double>* A, int lda, int* ipiv, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void sytrf( DenseMatrix<MT,SO>& A, char uplo, int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// The decomposition has the form
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// \note The Bunch-Kaufman decomposition will never fail, even for singular matrices. However, in
+// case of a singular matrix the resulting decomposition cannot be used for a matrix inversion or
+// solving a linear system of equations.
+//
+//
+// \n \subsection lapack_ldlh_decomposition LDLH Decomposition
+//
+// The following functions provide an interface for the LAPACK functions \c chetrf() and \c zsytrf(),
+// which compute the LDLH (Bunch-Kaufman) decomposition for the given Hermitian indefinite matrix:
+
+ \code
+ namespace blaze {
+
+ void hetrf( char uplo, int n, complex<float>* A, int lda, int* ipiv, complex<float>* work, int lwork, int* info );
+
+ void hetrf( char uplo, int n, complex<double>* A, int lda, int* ipiv, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void hetrf( DenseMatrix<MT,SO>& A, char uplo, int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// The decomposition has the form
+
+ \f[ A = U D U^{H} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// \note The Bunch-Kaufman decomposition will never fail, even for singular matrices. However, in
+// case of a singular matrix the resulting decomposition cannot be used for a matrix inversion or
+// solving a linear system of equations.
+//
+//
+// \n \subsection lapack_llh_decomposition Cholesky Decomposition
+//
+// The following functions provide an interface for the LAPACK functions \c spotrf(), \c dpotrf(),
+// \c cpotrf(), and \c zpotrf(), which compute the Cholesky (LLH) decomposition for the given
+// positive definite matrix:
+
+ \code
+ namespace blaze {
+
+ void potrf( char uplo, int n, float* A, int lda, int* info );
+
+ void potrf( char uplo, int n, double* A, int lda, int* info );
+
+ void potrf( char uplo, int n, complex<float>* A, int lda, int* info );
+
+ void potrf( char uplo, int n, complex<double>* A, int lda, int* info );
+
+ template< typename MT, bool SO >
+ void potrf( DenseMatrix<MT,SO>& A, char uplo );
+
+ } // namespace blaze
+ \endcode
+
+// The decomposition has the form
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The Cholesky
+// decomposition fails if the given matrix \a A is not a positive definite matrix. In this case
+// a \a std::std::invalid_argument exception is thrown.
+//
+//
+// \n \subsection lapack_qr_decomposition QR Decomposition
+//
+// The following functions provide an interface for the LAPACK functions \c sgeqrf(), \c dgeqrf(),
+// \c cgeqrf(), and \c zgeqrf(), which compute the QR decomposition of the given general matrix:
+
+ \code
+ namespace blaze {
+
+ void geqrf( int m, int n, float* A, int lda, float* tau, float* work, int lwork, int* info );
+
+ void geqrf( int m, int n, double* A, int lda, double* tau, double* work, int lwork, int* info );
+
+ void geqrf( int m, int n, complex<float>* A, int lda, complex<float>* tau, complex<float>* work, int lwork, int* info );
+
+ void geqrf( int m, int n, complex<double>* A, int lda, complex<double>* tau, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void geqrf( DenseMatrix<MT,SO>& A, typename MT::ElementType* tau );
+
+ } // namespace blaze
+ \endcode
+
+// The decomposition has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:m)</tt> is stored on exit in <tt>A(i+1:m,i)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and above the diagonal of the matrix contain the
+// min(\a m,\a n)-by-\a n upper trapezoidal matrix \c R (\c R is upper triangular if \a m >= \a n);
+// the elements below the diagonal, with the array \c tau, represent the orthogonal matrix \c Q as
+// a product of min(\a m,\a n) elementary reflectors.
+//
+// The following functions provide an interface for the LAPACK functions \c sorgqr(), \c dorgqr(),
+// \c cungqr(), and \c zunqqr(), which reconstruct the \c Q matrix from a QR decomposition:
+
+ \code
+ namespace blaze {
+
+ void orgqr( int m, int n, int k, float* A, int lda, const float* tau, float* work, int lwork, int* info );
+
+ void orgqr( int m, int n, int k, double* A, int lda, const double* tau, double* work, int lwork, int* info );
+
+ void ungqr( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau, complex<float>* work, int lwork, int* info );
+
+ void ungqr( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void orgqr( DenseMatrix<MT,SO>& A, const typename MT::ElementType* tau );
+
+ template< typename MT, bool SO >
+ void ungqr( DenseMatrix<MT,SO>& A, const typename MT::ElementType* tau );
+
+ } // namespace blaze
+ \endcode
+
+// The following functions provide an interface for the LAPACK functions \c sormqr(), \c dormqr(),
+// \c cunmqr(), and \c zunmqr(), which can be used to multiply a matrix with the \c Q matrix from
+// a QR decomposition:
+
+ \code
+ namespace blaze {
+
+ void ormqr( char side, char trans, int m, int n, int k, const float* A, int lda, const float* tau, float* C, int ldc, float* work, int lwork, int* info );
+
+ void ormqr( char side, char trans, int m, int n, int k, const double* A, int lda, const double* tau, double* C, int ldc, double* work, int lwork, int* info );
+
+ void unmqr( char side, char trans, int m, int n, int k, const complex<float>* A, int lda, const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work, int lwork, int* info );
+
+ void unmqr( char side, char trans, int m, int n, int k, const complex<double>* A, int lda, const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work, int lwork, int* info );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void ormqr( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A, char side, char trans, const ElementType_<MT2>* tau );
+
+ template< typename MT1, bool SO, typename MT2 >
+ void unmqr( DenseMatrix<MT1,SO>& C, DenseMatrix<MT2,SO>& A, char side, char trans, ElementType_<MT2>* tau );
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection lapack_rq_decomposition RQ Decomposition
+//
+// The following functions provide an interface for the LAPACK functions \c sgerqf(), \c dgerqf(),
+// \c cgerqf(), and \c zgerqf(), which compute the RQ decomposition of the given general matrix:
+
+ \code
+ namespace blaze {
+
+ void gerqf( int m, int n, float* A, int lda, float* tau, float* work, int lwork, int* info );
+
+ void gerqf( int m, int n, double* A, int lda, double* tau, double* work, int lwork, int* info );
+
+ void gerqf( int m, int n, complex<float>* A, int lda, complex<float>* tau, complex<float>* work, int lwork, int* info );
+
+ void gerqf( int m, int n, complex<double>* A, int lda, complex<double>* tau, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void gerqf( DenseMatrix<MT,SO>& A, typename MT::ElementType* tau );
+
+ } // namespace blaze
+ \endcode
+
+// The decomposition has the form
+
+ \f[ A = R \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(n-k+i+1:n) = 0</tt> and
+// <tt>v(n-k+i) = 1</tt>. <tt>v(1:n-k+i-1)</tt> is stored on exit in <tt>A(m-k+i,1:n-k+i-1)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m <= \a n, the upper triangle of the subarray
+// <tt>A(1:m,n-m+1:n)</tt> contains the \a m-by-\a m upper triangular matrix \c R and in case
+// \a m >= \a n, the elements on and above the (\a m-\a n)-th subdiagonal contain the \a m-by-\a n
+// upper trapezoidal matrix \c R; the remaining elements in combination with the array \c tau
+// represent the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The following functions provide an interface for the LAPACK functions \c sorgrq(), \c dorgrq(),
+// \c cungrq(), and \c zunqrq(), which reconstruct the \c Q matrix from a RQ decomposition:
+
+ \code
+ namespace blaze {
+
+ void orgrq( int m, int n, int k, float* A, int lda, const float* tau, float* work, int lwork, int* info );
+
+ void orgrq( int m, int n, int k, double* A, int lda, const double* tau, double* work, int lwork, int* info );
+
+ void ungrq( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau, complex<float>* work, int lwork, int* info );
+
+ void ungrq( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void orgrq( DenseMatrix<MT,SO>& A, const typename MT::ElementType* tau );
+
+ template< typename MT, bool SO >
+ void ungrq( DenseMatrix<MT,SO>& A, const typename MT::ElementType* tau );
+
+ } // namespace blaze
+ \endcode
+
+// The following functions provide an interface for the LAPACK functions \c sormrq(), \c dormrq(),
+// \c cunmrq(), and \c zunmrq(), which can be used to multiply a matrix with the \c Q matrix from
+// a RQ decomposition:
+
+ \code
+ namespace blaze {
+
+ void ormrq( char side, char trans, int m, int n, int k, const float* A, int lda, const float* tau, float* C, int ldc, float* work, int lwork, int* info );
+
+ void ormrq( char side, char trans, int m, int n, int k, const double* A, int lda, const double* tau, double* C, int ldc, double* work, int lwork, int* info );
+
+ void unmrq( char side, char trans, int m, int n, int k, const complex<float>* A, int lda, const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work, int lwork, int* info );
+
+ void unmrq( char side, char trans, int m, int n, int k, const complex<double>* A, int lda, const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work, int lwork, int* info );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void ormrq( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A, char side, char trans, const ElementType_<MT2>* tau );
+
+ template< typename MT1, bool SO, typename MT2 >
+ void unmrq( DenseMatrix<MT1,SO>& C, DenseMatrix<MT2,SO>& A, char side, char trans, ElementType_<MT2>* tau );
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection lapack_ql_decomposition QL Decomposition
+//
+// The following functions provide an interface for the LAPACK functions \c sgeqlf(), \c dgeqlf(),
+// \c cgeqlf(), and \c zgeqlf(), which compute the QL decomposition of the given general matrix:
+
+ \code
+ namespace blaze {
+
+ void geqlf( int m, int n, float* A, int lda, float* tau, float* work, int lwork, int* info );
+
+ void geqlf( int m, int n, double* A, int lda, double* tau, double* work, int lwork, int* info );
+
+ void geqlf( int m, int n, complex<float>* A, int lda, complex<float>* tau, complex<float>* work, int lwork, int* info );
+
+ void geqlf( int m, int n, complex<double>* A, int lda, complex<double>* tau, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void geqlf( DenseMatrix<MT,SO>& A, typename MT::ElementType* tau );
+
+ } // namespace blaze
+ \endcode
+
+// The decomposition has the form
+
+ \f[ A = Q \cdot L, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) . . . H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(m-k+i+1:m) = 0</tt> and
+// <tt>v(m-k+i) = 1</tt>. <tt>v(1:m-k+i-1)</tt> is stored on exit in <tt>A(1:m-k+i-1,n-k+i)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m >= \a n, the lower triangle of the subarray
+// A(m-n+1:m,1:n) contains the \a n-by-\a n lower triangular matrix \c L and in case \a m <= \a n,
+// the elements on and below the (\a n-\a m)-th subdiagonal contain the \a m-by-\a n lower
+// trapezoidal matrix \c L; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The following functions provide an interface for the LAPACK functions \c sorgql(), \c dorgql(),
+// \c cungql(), and \c zunqql(), which reconstruct the \c Q matrix from an QL decomposition:
+
+ \code
+ namespace blaze {
+
+ void orgql( int m, int n, int k, float* A, int lda, const float* tau, float* work, int lwork, int* info );
+
+ void orgql( int m, int n, int k, double* A, int lda, const double* tau, double* work, int lwork, int* info );
+
+ void ungql( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau, complex<float>* work, int lwork, int* info );
+
+ void ungql( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void orgql( DenseMatrix<MT,SO>& A, const typename MT::ElementType* tau );
+
+ template< typename MT, bool SO >
+ void ungql( DenseMatrix<MT,SO>& A, const typename MT::ElementType* tau );
+
+ } // namespace blaze
+ \endcode
+
+// The following functions provide an interface for the LAPACK functions \c sormql(), \c dormql(),
+// \c cunmql(), and \c zunmql(), which can be used to multiply a matrix with the \c Q matrix from
+// a QL decomposition:
+
+ \code
+ namespace blaze {
+
+ void ormql( char side, char trans, int m, int n, int k, const float* A, int lda, const float* tau, float* C, int ldc, float* work, int lwork, int* info );
+
+ void ormql( char side, char trans, int m, int n, int k, const double* A, int lda, const double* tau, double* C, int ldc, double* work, int lwork, int* info );
+
+ void unmql( char side, char trans, int m, int n, int k, const complex<float>* A, int lda, const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work, int lwork, int* info );
+
+ void unmql( char side, char trans, int m, int n, int k, const complex<double>* A, int lda, const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work, int lwork, int* info );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void ormql( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A, char side, char trans, const ElementType_<MT2>* tau );
+
+ template< typename MT1, bool SO, typename MT2 >
+ void unmql( DenseMatrix<MT1,SO>& C, DenseMatrix<MT2,SO>& A, char side, char trans, ElementType_<MT2>* tau );
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection lapack_lq_decomposition LQ Decomposition
+//
+// The following functions provide an interface for the LAPACK functions \c sgelqf(), \c dgelqf(),
+// \c cgelqf(), and \c zgelqf(), which compute the LQ decomposition of the given general matrix:
+
+ \code
+ namespace blaze {
+
+ void gelqf( int m, int n, float* A, int lda, float* tau, float* work, int lwork, int* info );
+
+ void gelqf( int m, int n, double* A, int lda, double* tau, double* work, int lwork, int* info );
+
+ void gelqf( int m, int n, complex<float>* A, int lda, complex<float>* tau, complex<float>* work, int lwork, int* info );
+
+ void gelqf( int m, int n, complex<double>* A, int lda, complex<double>* tau, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void gelqf( DenseMatrix<MT,SO>& A, typename MT::ElementType* tau );
+
+ } // namespace blaze
+ \endcode
+
+// The decomposition has the form
+
+ \f[ A = L \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) . . . H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:n)</tt> is stored on exit in <tt>A(i,i+1:n)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and below the diagonal of the matrix contain the
+// \a m-by-min(\a m,\a n) lower trapezoidal matrix \c L (\c L is lower triangular if \a m <= \a n);
+// the elements above the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The following functions provide an interface for the LAPACK functions \c sorglq(), \c dorglq(),
+// \c cunglq(), and \c zunqlq(), which reconstruct the \c Q matrix from an LQ decomposition:
+
+ \code
+ namespace blaze {
+
+ void orglq( int m, int n, int k, float* A, int lda, const float* tau, float* work, int lwork, int* info );
+
+ void orglq( int m, int n, int k, double* A, int lda, const double* tau, double* work, int lwork, int* info );
+
+ void unglq( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau, complex<float>* work, int lwork, int* info );
+
+ void unglq( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void orglq( DenseMatrix<MT,SO>& A, const typename MT::ElementType* tau );
+
+ template< typename MT, bool SO >
+ void unglq( DenseMatrix<MT,SO>& A, const typename MT::ElementType* tau );
+
+ } // namespace blaze
+ \endcode
+
+// The following functions provide an interface for the LAPACK functions \c sormlq(), \c dormlq(),
+// \c cunmlq(), and \c zunmlq(), which can be used to multiply a matrix with the \c Q matrix from
+// a LQ decomposition:
+
+ \code
+ namespace blaze {
+
+ void ormlq( char side, char trans, int m, int n, int k, const float* A, int lda, const float* tau, float* C, int ldc, float* work, int lwork, int* info );
+
+ void ormlq( char side, char trans, int m, int n, int k, const double* A, int lda, const double* tau, double* C, int ldc, double* work, int lwork, int* info );
+
+ void unmlq( char side, char trans, int m, int n, int k, const complex<float>* A, int lda, const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work, int lwork, int* info );
+
+ void unmlq( char side, char trans, int m, int n, int k, const complex<double>* A, int lda, const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work, int lwork, int* info );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void ormlq( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A, char side, char trans, const ElementType_<MT2>* tau );
+
+ template< typename MT1, bool SO, typename MT2 >
+ void unmlq( DenseMatrix<MT1,SO>& C, DenseMatrix<MT2,SO>& A, char side, char trans, ElementType_<MT2>* tau );
+
+ } // namespace blaze
+ \endcode
+
+// \n \section lapack_inversion Matrix Inversion
+// <hr>
+//
+// Given a matrix that has already been decomposed, the following functions can be used to invert
+// the matrix in-place.
+//
+//
+// \n \subsection lapack_lu_inversion LU-based Inversion
+//
+// The following functions provide an interface for the LAPACK functions \c sgetri(), \c dgetri(),
+// \c cgetri(), and \c zgetri(), which invert a general matrix that has already been decomposed by
+// an \ref lapack_lu_decomposition :
+
+ \code
+ namespace blaze {
+
+ void getri( int n, float* A, int lda, const int* ipiv, float* work, int lwork, int* info );
+
+ void getri( int n, double* A, int lda, const int* ipiv, double* work, int lwork, int* info );
+
+ void getri( int n, complex<float>* A, int lda, const int* ipiv, complex<float>* work, int lwork, int* info );
+
+ void getri( int n, complex<double>* A, int lda, const int* ipiv, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO >
+ void getri( DenseMatrix<MT,SO>& A, const int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// The functions fail if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// The first four functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_ldlt_inversion LDLT-based Inversion
+//
+// The following functions provide an interface for the LAPACK functions \c ssytri(), \c dsytri(),
+// \c csytri(), and \c zsytri(), which invert a symmetric indefinite matrix that has already been
+// decomposed by an \ref lapack_ldlt_decomposition :
+
+ \code
+ namespace blaze {
+
+ void sytri( char uplo, int n, float* A, int lda, const int* ipiv, float* work, int* info );
+
+ void sytri( char uplo, int n, double* A, int lda, const int* ipiv, double* work, int* info );
+
+ void sytri( char uplo, int n, complex<float>* A, int lda, const int* ipiv, complex<float>* work, int* info );
+
+ void sytri( char uplo, int n, complex<double>* A, int lda, const int* ipiv, complex<double>* work, int* info );
+
+ template< typename MT, bool SO >
+ void sytri( DenseMatrix<MT,SO>& A, char uplo, const int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// The functions fail if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// The first four functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_ldlh_inversion LDLH-based Inversion
+//
+// The following functions provide an interface for the LAPACK functions \c chetri() and
+// \c zhetri(), which invert an Hermitian indefinite matrix that has already been decomposed by
+// an \ref lapack_ldlh_decomposition :
+
+ \code
+ namespace blaze {
+
+ void hetri( char uplo, int n, complex<float>* A, int lda, const int* ipiv, complex<float>* work, int* info );
+
+ void hetri( char uplo, int n, complex<double>* A, int lda, const int* ipiv, complex<double>* work, int* info );
+
+ template< typename MT, bool SO >
+ void hetri( DenseMatrix<MT,SO>& A, char uplo, const int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// The functions fail if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// The first four functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_llh_inversion Cholesky-based Inversion
+//
+// The following functions provide an interface for the LAPACK functions \c spotri(), \c dpotri(),
+// \c cpotri(), and \c zpotri(), which invert a positive definite matrix that has already been
+// decomposed by an \ref lapack_llh_decomposition :
+
+ \code
+ namespace blaze {
+
+ void potri( char uplo, int n, float* A, int lda, int* info );
+
+ void potri( char uplo, int n, double* A, int lda, int* info );
+
+ void potri( char uplo, int n, complex<float>* A, int lda, int* info );
+
+ void potri( char uplo, int n, complex<double>* A, int lda, int* info );
+
+ template< typename MT, bool SO >
+ void potri( DenseMatrix<MT,SO>& A, char uplo );
+
+ } // namespace blaze
+ \endcode
+
+// The functions fail if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the given matrix is singular and not invertible.
+//
+// The first four functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_triangular_inversion Inversion of Triangular Matrices
+//
+// The following functions provide an interface for the LAPACK functions \c strtri(), \c dtrtri(),
+// \c ctrtri(), and \c ztrtri(), which invert the given triangular matrix in-place:
+
+ \code
+ namespace blaze {
+
+ void trtri( char uplo, char diag, int n, float* A, int lda, int* info );
+
+ void trtri( char uplo, char diag, int n, double* A, int lda, int* info );
+
+ void trtri( char uplo, char diag, int n, complex<float>* A, int lda, int* info );
+
+ void trtri( char uplo, char diag, int n, complex<double>* A, int lda, int* info );
+
+ template< typename MT, bool SO >
+ void trtri( DenseMatrix<MT,SO>& A, char uplo, char diag );
+
+ } // namespace blaze
+ \endcode
+
+// The functions fail if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the given \a diag argument is neither 'U' nor 'N';
+// - ... the given matrix is singular and not invertible.
+//
+// The first four functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \section lapack_substitution Substitution
+// <hr>
+//
+// Given a matrix that has already been decomposed the following functions can be used to perform
+// the forward/backward substitution step to compute the solution to a system of linear equations.
+// Note that depending on the storage order of the system matrix and the given right-hand side the
+// functions solve different equation systems:
+//
+// Single right-hand side:
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// Multiple right-hand sides:
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the general system matrix \a A is a n-by-n matrix that has already been
+// factorized by the according decomposition function, \a x and \a b are n-dimensional vectors
+// and \a X and \a B are either row-major m-by-n matrices or column-major n-by-m matrices.
+//
+//
+// \n \subsection lapack_lu_substitution LU-based Substitution
+//
+// The following functions provide an interface for the LAPACK functions \c sgetrs(), \c dgetrs(),
+// \c cgetrs(), and \c zgetrs(), which perform the substitution step for a general matrix that has
+// already been decomposed by an \ref lapack_lu_decomposition :
+
+ \code
+ namespace blaze {
+
+ void getrs( char trans, int n, int nrhs, const float* A, int lda, const int* ipiv, float* B, int ldb, int* info );
+
+ void getrs( char trans, int n, int nrhs, const double* A, int lda, const int* ipiv, double* B, int ldb, int* info );
+
+ void getrs( char trans, int n, const complex<float>* A, int lda, const int* ipiv, complex<float>* B, int ldb, int* info );
+
+ void getrs( char trans, int n, const complex<double>* A, int lda, const int* ipiv, complex<double>* B, int ldb, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void getrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char trans, const int* ipiv );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void getrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char trans, const int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the solution(s)
+// of the linear system of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a trans argument is neither 'N' nor 'T' nor 'C';
+// - ... the sizes of the two given matrices do not match.
+//
+// The first four functions report failure via the \c info argument, the last two functions throw
+// a \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_ldlt_substitution LDLT-based Substitution
+//
+// The following functions provide an interface for the LAPACK functions \c ssytrs(), \c dsytrs(),
+// \c csytrs(), and \c zsytrs(), which perform the substitution step for a symmetric indefinite
+// matrix that has already been decomposed by an \ref lapack_ldlt_decomposition :
+
+ \code
+ namespace blaze {
+
+ void sytrs( char uplo, int n, int nrhs, const float* A, int lda, const int* ipiv, float* B, int ldb, int* info );
+
+ void sytrs( char uplo, int n, int nrhs, const double* A, int lda, const int* ipiv, double* B, int ldb, int* info );
+
+ void sytrs( char uplo, int n, int nrhs, const complex<float>* A, int lda, const int* ipiv, complex<float>* B, int ldb, int* info );
+
+ void sytrs( char uplo, int n, int nrhs, const complex<double>* A, int lda, const int* ipiv, complex<double>* B, int ldb, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void sytrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, const int* ipiv );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void sytrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, const int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the solution(s)
+// of the linear system of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the sizes of the two given matrices do not match.
+//
+// The first four functions report failure via the \c info argument, the last two functions throw
+// a \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_ldlh_substitution LDLH-based Substitution
+//
+// The following functions provide an interface for the LAPACK functions \c chetrs(), and \c zhetrs(),
+// which perform the substitution step for an Hermitian indefinite matrix that has already been
+// decomposed by an \ref lapack_ldlh_decomposition :
+
+ \code
+ namespace blaze {
+
+ void hetrs( char uplo, int n, int nrhs, const complex<float>* A, int lda, const int* ipiv, complex<float>* B, int ldb, int* info );
+
+ void hetrs( char uplo, int n, int nrhs, const complex<double>* A, int lda, const int* ipiv, complex<double>* B, int ldb, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void hetrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, const int* ipiv );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void hetrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, const int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the solution(s)
+// of the linear system of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the sizes of the two given matrices do not match.
+//
+// The first two functions report failure via the \c info argument, the last two functions throw
+// a \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_llh_substitution Cholesky-based Substitution
+//
+// The following functions provide an interface for the LAPACK functions \c spotrs(), \c dpotrs(),
+// \c cpotrs(), and \c zpotrs(), which perform the substitution step for a positive definite matrix
+// that has already been decomposed by an \ref lapack_llh_decomposition :
+
+ \code
+ namespace blaze {
+
+ void potrs( char uplo, int n, int nrhs, const float* A, int lda, float* B, int ldb, int* info );
+
+ void potrs( char uplo, int n, int nrhs, const double* A, int lda, double* B, int ldb, int* info );
+
+ void potrs( char uplo, int n, int nrhs, const complex<float>* A, int lda, complex<float>* B, int ldb, int* info );
+
+ void potrs( char uplo, int n, int nrhs, const complex<double>* A, int lda, complex<double>* B, int ldb, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void potrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void potrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the solution(s)
+// of the linear system of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the sizes of the two given matrices do not match.
+//
+// The first two functions report failure via the \c info argument, the last two functions throw
+// a \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_triangular_substitution Substitution for Triangular Matrices
+//
+// The following functions provide an interface for the LAPACK functions \c strtrs(), \c dtrtrs(),
+// \c ctrtrs(), and \c ztrtrs(), which perform the substitution step for a triangular matrix:
+
+ \code
+ namespace blaze {
+
+ void trtrs( char uplo, char trans, char diag, int n, int nrhs, const float* A, int lda, float* B, int ldb, int* info );
+
+ void trtrs( char uplo, char trans, char diag, int n, int nrhs, const double* A, int lda, double* B, int ldb, int* info );
+
+ void trtrs( char uplo, char trans, char diag, int n, int nrhs, const complex<float>* A, int lda, complex<float>* B, int ldb, int* info );
+
+ void trtrs( char uplo, char trans, char diag, int n, int nrhs, const complex<double>* A, int lda, complex<double>* B, int ldb, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void trtrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, char trans, char diag );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void trtrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, char trans, char diag );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the solution(s)
+// of the linear system of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the given \a trans argument is neither 'N' nor 'T' nor 'C';
+// - ... the given \a diag argument is neither 'U' nor 'N';
+// - ... the sizes of the two given matrices do not match.
+//
+// The first four functions report failure via the \c info argument, the last two functions throw
+// a \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \section lapack_linear_system_solver Linear System Solver
+// <hr>
+//
+// The following functions represent compound functions that perform both the decomposition step
+// as well as the substitution step to compute the solution to a system of linear equations. Note
+// that depending on the storage order of the system matrix and the given right-hand side the
+// functions solve different equation systems:
+//
+// Single right-hand side:
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// Multiple right-hand sides:
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the general system matrix \a A is a n-by-n matrix that has already been
+// factorized by the according decomposition function, \a x and \a b are n-dimensional vectors
+// and \a X and \a B are either row-major m-by-n matrices or column-major n-by-m matrices.
+//
+//
+// \subsection lapack_lu_linear_system_solver LU-based Linear System Solver
+//
+// The following functions provide an interface for the LAPACK functions \c sgesv(), \c dgesv(),
+// \c cgesv(), and \c zgesv(), which combine an \ref lapack_lu_decomposition and the according
+// \ref lapack_lu_substitution :
+
+ \code
+ namespace blaze {
+
+ void gesv( int n, int nrhs, float* A, int lda, int* ipiv, float* B, int ldb, int* info );
+
+ void gesv( int n, int nrhs, double* A, int lda, int* ipiv, double* B, int ldb, int* info );
+
+ void gesv( int n, int nrhs, complex<float>* A, int lda, int* ipiv, complex<float>* B, int ldb, int* info );
+
+ void gesv( int n, int nrhs, complex<double>* A, int lda, int* ipiv, complex<double>* B, int ldb, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void gesv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, int* ipiv );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void gesv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the
+// solution(s) of the linear system of equations and \a A has been decomposed by means of an
+// \ref lapack_lu_decomposition.
+//
+// The functions fail if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given system matrix is singular and not invertible.
+//
+// The first four functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_ldlt_linear_system_solver LDLT-based Linear System Solver
+//
+// The following functions provide an interface for the LAPACK functions \c ssysv(), \c dsysv(),
+// \c csysv(), and \c zsysv(), which combine an \ref lapack_ldlt_decomposition and the according
+// \ref lapack_ldlt_substitution :
+
+ \code
+ namespace blaze {
+
+ void sysv( char uplo, int n, int nrhs, float* A, int lda, int* ipiv, float* B, int ldb, float* work, int lwork, int* info );
+
+ void sysv( char uplo, int n, int nrhs, double* A, int lda, int* ipiv, double* B, int ldb, double* work, int lwork, int* info );
+
+ void sysv( char uplo, int n, int nrhs, complex<float>* A, int lda, int* ipiv, complex<float>* B, int ldb, complex<float>* work, int lwork, int* info );
+
+ void sysv( char uplo, int n, int nrhs, complex<double>* A, int lda, int* ipiv, complex<double>* B, int ldb, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void sysv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, int* ipiv );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void sysv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the
+// solution(s) of the linear system of equations and \a A has been decomposed by means of an
+// \ref lapack_ldlt_decomposition.
+//
+// The functions fail if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the sizes of the two given matrices do not match;
+// - ... the given system matrix is singular and not invertible.
+//
+// The first four functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_ldlh_linear_system_solver LDLH-based Linear System Solver
+//
+// The following functions provide an interface for the LAPACK functions \c shesv(), \c dhesv(),
+// \c chesv(), and \c zhesv(), which combine an \ref lapack_ldlh_decomposition and the according
+// \ref lapack_ldlh_substitution :
+
+ \code
+ namespace blaze {
+
+ void hesv( char uplo, int n, int nrhs, complex<float>* A, int lda, int* ipiv, complex<float>* B, int ldb, complex<float>* work, int lwork, int* info );
+
+ void hesv( char uplo, int n, int nrhs, complex<double>* A, int lda, int* ipiv, complex<double>* B, int ldb, complex<double>* work, int lwork, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void hesv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, int* ipiv );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void hesv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, int* ipiv );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the
+// solution(s) of the linear system of equations and \a A has been decomposed by means of an
+// \ref lapack_ldlh_decomposition.
+//
+// The functions fail if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the sizes of the two given matrices do not match;
+// - ... the given system matrix is singular and not invertible.
+//
+// The first two functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_llh_linear_system_solver Cholesky-based Linear System Solver
+//
+// The following functions provide an interface for the LAPACK functions \c sposv(), \c dposv(),
+// \c cposv(), and \c zposv(), which combine an \ref lapack_llh_decomposition and the according
+// \ref lapack_llh_substitution :
+
+ \code
+ namespace blaze {
+
+ void posv( char uplo, int n, int nrhs, float* A, int lda, float* B, int ldb, int* info );
+
+ void posv( char uplo, int n, int nrhs, double* A, int lda, double* B, int ldb, int* info );
+
+ void posv( char uplo, int n, int nrhs, complex<float>* A, int lda, complex<float>* B, int ldb, int* info );
+
+ void posv( char uplo, int n, int nrhs, complex<double>* A, int lda, complex<double>* B, int ldb, int* info );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void posv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo );
+
+ template< typename MT1, bool SO1, typename MT2, bool SO2 >
+ void posv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the
+// solution(s) of the linear system of equations and \a A has been decomposed by means of an
+// \ref lapack_llh_decomposition.
+//
+// The functions fail if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the sizes of the two given matrices do not match;
+// - ... the given system matrix is singular and not invertible.
+//
+// The first four functions report failure via the \c info argument, the fifth function throws a
+// \a std::invalid_argument exception in case of an error.
+//
+//
+// \n \subsection lapack_triangular_linear_system_solver Linear System Solver for Triangular Matrices
+//
+// The following functions provide an interface for the LAPACK functions \c strsv(), \c dtrsv(),
+// \c ctrsv(), and \c ztrsv():
+
+ \code
+ namespace blaze {
+
+ void trsv( char uplo, char trans, char diag, int n, const float* A, int lda, float* x, int incX );
+
+ void trsv( char uplo, char trans, char diag, int n, const double* A, int lda, double* x, int incX );
+
+ void trsv( char uplo, char trans, char diag, int n, const complex<float>* A, int lda, complex<float>* x, int incX );
+
+ void trsv( char uplo, char trans, char diag, int n, const complex<double>* A, int lda, complex<double>* x, int incX );
+
+ template< typename MT, bool SO, typename VT, bool TF >
+ void trsv( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, char trans, char diag );
+
+ } // namespace blaze
+ \endcode
+
+// If the function exits successfully, the vector \a b or the matrix \a B contain the
+// solution(s) of the linear system of equations.
+//
+// The functions fail if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither 'L' nor 'U';
+// - ... the given \a trans argument is neither 'N' nor 'T' nor 'C';
+// - ... the given \a diag argument is neither 'U' nor 'N'.
+//
+// The last function throws a \a std::invalid_argument exception in case of an error. Note that
+// none of the functions does perform any test for singularity or near-singularity. Such tests
+// must be performed prior to calling this function!
+//
+//
+// \n Previous: \ref blas_functions &nbsp; &nbsp; Next: \ref configuration_files \n
+*/
+//*************************************************************************************************
+
+
+//**Configuration Files****************************************************************************
+/*!\page configuration_files Configuration Files
+//
+// \tableofcontents
+//
+//
+// Sometimes it might necessary to adapt \b Blaze to specific requirements. For this purpose
+// \b Blaze provides several configuration files in the <tt>./blaze/config/</tt> subdirectory,
+// which provide ample opportunity to customize internal settings, behavior, and thresholds.
+// This chapter explains the most important of these configuration files.
+//
+//
+// \n \section transpose_flag Default Vector Storage
+// <hr>
+//
+// The \b Blaze default is that all vectors are created as column vectors (if not specified
+// explicitly):
+
+ \code
+ blaze::StaticVector<double,3UL> x; // Creates a 3-dimensional static column vector
+ \endcode
+
+// The header file <tt>./blaze/config/TransposeFlag.h</tt> allows the configuration of the default
+// vector storage (i.e. the default transpose flag of the vectors). Via the \c defaultTransposeFlag
+// value the default transpose flag for all vector of the \b Blaze library can be specified:
+
+ \code
+ constexpr bool defaultTransposeFlag = columnVector;
+ \endcode
+
+// Valid settings for the \c defaultTransposeFlag are blaze::rowVector and blaze::columnVector.
+//
+//
+// \n \section storage_order Default Matrix Storage
+// <hr>
+//
+// Matrices are by default created as row-major matrices:
+
+ \code
+ blaze::StaticMatrix<double,3UL,3UL> A; // Creates a 3x3 row-major matrix
+ \endcode
+
+// The header file <tt>./blaze/config/StorageOrder.h</tt> allows the configuration of the default
+// matrix storage order. Via the \c defaultStorageOrder value the default storage order for all
+// matrices of the \b Blaze library can be specified.
+
+ \code
+ constexpr bool defaultStorageOrder = rowMajor;
+ \endcode
+
+// Valid settings for the \c defaultStorageOrder are blaze::rowMajor and blaze::columnMajor.
+//
+//
+// \n \section blas_mode BLAS Mode
+// <hr>
+//
+// In order to achieve maximum performance for multiplications with dense matrices, \b Blaze can
+// be configured to use a BLAS library. Via the following compilation switch in the configuration
+// file <tt>./blaze/config/BLAS.h</tt> BLAS can be enabled:
+
+ \code
+ #define BLAZE_BLAS_MODE 1
+ \endcode
+
+// In case the selected BLAS library provides parallel execution, the \c BLAZE_BLAS_IS_PARALLEL
+// switch should be activated to prevent \b Blaze from parallelizing on its own:
+
+ \code
+ #define BLAZE_BLAS_IS_PARALLEL 1
+ \endcode
+
+// In case no BLAS library is available, \b Blaze will still work and will not be reduced in
+// functionality, but performance may be limited.
+//
+//
+// \n \section cache_size Cache Size
+// <hr>
+//
+// The optimization of several \b Blaze compute kernels depends on the cache size of the target
+// architecture. By default, \b Blaze assumes a cache size of 3 MiByte. However, for optimal
+// speed the exact cache size of the system should be provided via the \c cacheSize value in the
+// <tt>./blaze/config/CacheSize.h</tt> configuration file:
+
+ \code
+ constexpr size_t cacheSize = 3145728UL;
+ \endcode
+
+// \n \section vectorization Vectorization
+// <hr>
+//
+// In order to achieve maximum performance and to exploit the compute power of a target platform
+// the \b Blaze library attempts to vectorize all linear algebra operations by SSE, AVX, and/or
+// MIC intrinsics, depending on which instruction set is available. However, it is possible to
+// disable the vectorization entirely by the compile time switch in the configuration file
+// <tt>./blaze/config/Vectorization.h</tt>:
+
+ \code
+ #define BLAZE_USE_VECTORIZATION 1
+ \endcode
+
+// In case the switch is set to 1, vectorization is enabled and the \b Blaze library is allowed
+// to use intrinsics to speed up computations. In case the switch is set to 0, vectorization is
+// disabled entirely and the \b Blaze library chooses default, non-vectorized functionality for
+// the operations. Note that deactivating the vectorization may pose a severe performance
+// limitation for a large number of operations!
+//
+//
+// \n \section thresholds Thresholds
+// <hr>
+//
+// \b Blaze provides several thresholds that can be adapted to the characteristics of the target
+// platform. For instance, the \c DMATDVECMULT_THRESHOLD specifies the threshold between the
+// application of the custom \b Blaze kernels for small dense matrix/dense vector multiplications
+// and the BLAS kernels for large multiplications. All thresholds, including the thresholds for
+// the OpenMP-based parallelization, are contained within the configuration file
+// <tt>./blaze/config/Thresholds.h</tt>.
+//
+//
+// \n \section padding Padding
+// <hr>
+//
+// By default the \b Blaze library uses padding for all dense vectors and matrices in order to
+// achieve maximum performance in all operations. Due to padding, the proper alignment of data
+// elements can be guaranteed and the need for remainder loops is minimized. However, on the
+// downside padding introduces an additional memory overhead, which can be large depending on
+// the used data type.
+//
+// The configuration file <tt>./blaze/config/Optimizations.h</tt> provides a compile time switch
+// that can be used to (de-)activate padding:
+
+ \code
+ constexpr bool usePadding = true;
+ \endcode
+
+// If \c usePadding is set to \c true padding is enabled for all dense vectors and matrices, if
+// it is set to \c false padding is disabled. Note however that disabling padding can considerably
+// reduce the performance of all dense vector and matrix operations!
+//
+//
+// \n \section streaming Streaming (Non-Temporal Stores)
+// <hr>
+//
+// For vectors and matrices that don't fit into the cache anymore non-temporal stores can provide
+// a significant performance advantage of about 20%. However, this advantage is only in effect in
+// case the memory bandwidth of the target architecture is maxed out. If the target architecture's
+// memory bandwidth cannot be exhausted the use of non-temporal stores can decrease performance
+// instead of increasing it.
+//
+// The configuration file <tt>./blaze/config/Optimizations.h</tt> provides a compile time switch
+// that can be used to (de-)activate streaming:
+
+ \code
+ constexpr bool useStreaming = true;
+ \endcode
+
+// If \c useStreaming is set to \c true streaming is enabled, if it is set to \c false streaming
+// is disabled. It is recommended to consult the target architecture's white papers to decide
+// whether streaming is beneficial or hurtful for performance.
+//
+//
+// \n Previous: \ref lapack_functions &nbsp; &nbsp; Next: \ref custom_data_types \n
+*/
+//*************************************************************************************************
+
+
+//**Custom Data Types******************************************************************************
+/*!\page custom_data_types Custom Data Types
+//
+//
+// The \b Blaze library tries hard to make the use of custom data types as convenient, easy and
+// intuitive as possible. However, unfortunately it is not possible to meet the requirements of
+// all possible data types. Thus it might be necessary to provide \b Blaze with some additional
+// information about the data type. The following sections give an overview of the necessary steps
+// to enable the use of the hypothetical custom data type \c custom::double_t for vector and
+// matrix operations. For example:
+
+ \code
+ blaze::DynamicVector<custom::double_t> a, b, c;
+ // ... Resizing and initialization
+ c = a + b;
+ \endcode
+
+// The \b Blaze library assumes that the \c custom::double_t data type provides \c operator+()
+// for additions, \c operator-() for subtractions, \c operator*() for multiplications and
+// \c operator/() for divisions. If any of these functions is missing it is necessary to implement
+// the operator to perform the according operation. For this example we assume that the custom
+// data type provides the four following functions instead of operators:
+
+ \code
+ namespace custom {
+
+ double_t add ( const double_t& a, const double_t b );
+ double_t sub ( const double_t& a, const double_t b );
+ double_t mult( const double_t& a, const double_t b );
+ double_t div ( const double_t& a, const double_t b );
+
+ } // namespace custom
+ \endcode
+
+// The following implementations will satisfy the requirements of the \b Blaze library:
+
+ \code
+ inline custom::double_t operator+( const custom::double_t& a, const custom::double_t& b )
+ {
+ return add( a, b );
+ }
+
+ inline custom::double_t operator-( const custom::double_t& a, const custom::double_t& b )
+ {
+ return sub( a, b );
+ }
+
+ inline custom::double_t operator*( const custom::double_t& a, const custom::double_t& b )
+ {
+ return mult( a, b );
+ }
+
+ inline custom::double_t operator/( const custom::double_t& a, const custom::double_t& b )
+ {
+ return div( a, b );
+ }
+ \endcode
+
+// \b Blaze will use all the information provided with these functions (for instance the return
+// type) to properly handle the operations. In the rare case that the return type cannot be
+// automatically determined from the operator it might be additionally necessary to provide a
+// specialization of the following four \b Blaze class templates:
+
+ \code
+ namespace blaze {
+
+ template<>
+ struct AddTrait<custom::double_t,custom::double_t> {
+ typedef custom::double_t Type;
+ };
+
+ template<>
+ struct SubTrait<custom::double_t,custom::double_t> {
+ typedef custom::double_t Type;
+ };
+
+ template<>
+ struct MultTrait<custom::double_t,custom::double_t> {
+ typedef custom::double_t Type;
+ };
+
+ template<>
+ struct DivTrait<custom::double_t,custom::double_t> {
+ typedef custom::double_t Type;
+ };
+
+ } // namespace blaze
+ \endcode
+
+// The same steps are necessary if several custom data types need to be combined (as for instance
+// \c custom::double_t and \c custom::float_t). Note that in this case both permutations need to
+// be taken into account:
+
+ \code
+ custom::double_t operator+( const custom::double_t& a, const custom::float_t& b );
+ custom::double_t operator+( const custom::float_t& a, const custom::double_t& b );
+ // ...
+ \endcode
+
+// Please note that only built-in data types apply for vectorization and thus custom data types
+// cannot achieve maximum performance!
+//
+//
+// \n Previous: \ref configuration_files &nbsp; &nbsp; Next: \ref error_reporting_customization \n
+*/
+//*************************************************************************************************
+
+
+//**Customization of the Error Reporting Mechanism*************************************************
+/*!\page error_reporting_customization Customization of the Error Reporting Mechanism
+//
+// \tableofcontents
+//
+//
+// \n \section error_reporting_background Background
+// <hr>
+//
+// The default way of \b Blaze to report errors of any kind is to throw a standard exception.
+// However, although in general this approach works well, in certain environments and under
+// special circumstances exceptions may not be the mechanism of choice and a different error
+// reporting mechanism may be desirable. For this reason, \b Blaze provides several macros,
+// which enable the customization of the error reporting mechanism. Via these macros it is
+// possible to replace the standard exceptions by some other exception type or a completely
+// different approach to report errors.
+//
+//
+// \n \section error_reporting_general_customization Customization of the Reporting Mechanism
+// <hr>
+//
+// In some cases it might be necessary to adapt the entire error reporting mechanism and to
+// replace it by some other means to signal failure. The primary macro for this purpose is the
+// \c BLAZE_THROW macro:
+
+ \code
+ #define BLAZE_THROW( EXCEPTION ) \
+ throw EXCEPTION
+ \endcode
+
+// This macro represents the default mechanism of the \b Blaze library to report errors of any
+// kind. In order to customize the error reporing mechanism all that needs to be done is to
+// define the macro prior to including any \b Blaze header file. This will cause the \b Blaze
+// specific mechanism to be overridden. The following example demonstrates this by replacing
+// exceptions by a call to a \c log() function and a direct call to abort:
+
+ \code
+ #define BLAZE_THROW( EXCEPTION ) \
+ log( "..." ); \
+ abort()
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// Doing this will trigger a call to \c log() and an abort instead of throwing an exception
+// whenever an error (such as an invalid argument) is detected.
+//
+// \note It is possible to execute several statements instead of executing a single statement to
+// throw an exception. Also note that it is recommended to define the macro such that a subsequent
+// semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the error reporting mechanism via
+// this macro can have a significant effect on the library. Thus be advised to use the macro
+// with due care!
+//
+//
+// \n \section error_reporting_exception_customization Customization of the Type of Exceptions
+// <hr>
+//
+// In addition to the customization of the entire error reporting mechanism it is also possible
+// to customize the type of exceptions being thrown. This can be achieved by customizing any
+// number of the following macros:
+
+ \code
+ #define BLAZE_THROW_BAD_ALLOC \
+ BLAZE_THROW( std::bad_alloc() )
+
+ #define BLAZE_THROW_LOGIC_ERROR( MESSAGE ) \
+ BLAZE_THROW( std::logic_error( MESSAGE ) )
+
+ #define BLAZE_THROW_INVALID_ARGUMENT( MESSAGE ) \
+ BLAZE_THROW( std::invalid_argument( MESSAGE ) )
+
+ #define BLAZE_THROW_LENGTH_ERROR( MESSAGE ) \
+ BLAZE_THROW( std::length_error( MESSAGE ) )
+
+ #define BLAZE_THROW_OUT_OF_RANGE( MESSAGE ) \
+ BLAZE_THROW( std::out_of_range( MESSAGE ) )
+
+ #define BLAZE_THROW_RUNTIME_ERROR( MESSAGE ) \
+ BLAZE_THROW( std::runtime_error( MESSAGE ) )
+ \endcode
+
+// In order to customize the type of exception the according macro has to be defined prior to
+// including any \b Blaze header file. This will override the \b Blaze default behavior. The
+// following example demonstrates this by replacing \c std::invalid_argument by a custom
+// exception type:
+
+ \code
+ class InvalidArgument
+ {
+ public:
+ InvalidArgument();
+ explicit InvalidArgument( const std::string& message );
+ // ...
+ };
+
+ #define BLAZE_THROW_INVALID_ARGUMENT( MESSAGE ) \
+ BLAZE_THROW( InvalidArgument( MESSAGE ) )
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// By manually defining the macro, an \c InvalidArgument exception is thrown instead of a
+// \c std::invalid_argument exception. Note that it is recommended to define the macro such
+// that a subsequent semicolon is required!
+//
+// \warning These macros are provided with the intention to assist in adapting \b Blaze to
+// special conditions and environments. However, the customization of the type of an exception
+// via this macro may have an effect on the library. Thus be advised to use the macro with due
+// care!
+//
+//
+// \n \section error_reporting_special_errors Customization of Special Errors
+// <hr>
+//
+// Last but not least it is possible to customize the error reporting for special kinds of errors.
+// This can be achieved by customizing any number of the following macros:
+
+ \code
+ #define BLAZE_THROW_DIVISION_BY_ZERO( MESSAGE ) \
+ BLAZE_THROW_RUNTIME_ERROR( MESSAGE )
+
+ #define BLAZE_THROW_LAPACK_ERROR( MESSAGE ) \
+ BLAZE_THROW_RUNTIME_ERROR( MESSAGE )
+ \endcode
+
+// As explained in the previous sections, in order to customize the handling of special errors
+// the according macro has to be defined prior to including any \b Blaze header file. This will
+// override the \b Blaze default behavior.
+//
+//
+// \n Previous: \ref custom_data_types &nbsp; &nbsp; Next: \ref intra_statement_optimization \n
+*/
+//*************************************************************************************************
+
+
+//**Intra-Statement Optimization*******************************************************************
+/*!\page intra_statement_optimization Intra-Statement Optimization
+//
+// One of the prime features of the \b Blaze library is the automatic intra-statement optimization.
+// In order to optimize the overall performance of every single statement \b Blaze attempts to
+// rearrange the operands based on their types. For instance, the following addition of dense and
+// sparse vectors
+
+ \code
+ blaze::DynamicVector<double> d1, d2, d3;
+ blaze::CompressedVector<double> s1;
+
+ // ... Resizing and initialization
+
+ d3 = d1 + s1 + d2;
+ \endcode
+
+// is automatically rearranged and evaluated as
+
+ \code
+ // ...
+ d3 = d1 + d2 + s1; // <- Note that s1 and d2 have been rearranged
+ \endcode
+
+// This order of operands is highly favorable for the overall performance since the addition of
+// the two dense vectors \c d1 and \c d2 can be handled much more efficiently in a vectorized
+// fashion.
+//
+// This intra-statement optimization can have a tremendous effect on the performance of a statement.
+// Consider for instance the following computation:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ blaze::DynamicVector<double> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * B * x;
+ \endcode
+
+// Since multiplications are evaluated from left to right, this statement would result in a
+// matrix/matrix multiplication, followed by a matrix/vector multiplication. However, if the
+// right subexpression is evaluated first, the performance can be dramatically improved since the
+// matrix/matrix multiplication can be avoided in favor of a second matrix/vector multiplication.
+// The \b Blaze library exploits this by automatically restructuring the expression such that the
+// right multiplication is evaluated first:
+
+ \code
+ // ...
+ y = A * ( B * x );
+ \endcode
+
+// Note however that although this intra-statement optimization may result in a measurable or
+// even significant performance improvement, this behavior may be undesirable for several reasons,
+// for instance because of numerical stability. Therefore, in case the order of evaluation matters,
+// the best solution is to be explicit and to separate a statement into several statements:
+
+ \code
+ blaze::DynamicVector<double> d1, d2, d3;
+ blaze::CompressedVector<double> s1;
+
+ // ... Resizing and initialization
+
+ d3 = d1 + s1; // Compute the dense vector/sparse vector addition first ...
+ d3 += d2; // ... and afterwards add the second dense vector
+ \endcode
+
+ \code
+ // ...
+ blaze::DynamicMatrix<double> A, B, C;
+ blaze::DynamicVector<double> x, y;
+
+ // ... Resizing and initialization
+
+ C = A * B; // Compute the left-hand side matrix-matrix multiplication first ...
+ y = C * x; // ... before the right-hand side matrix-vector multiplication
+ \endcode
+
+// Alternatively, it is also possible to use the \c eval() function to fix the order of evaluation:
+
+ \code
+ blaze::DynamicVector<double> d1, d2, d3;
+ blaze::CompressedVector<double> s1;
+
+ // ... Resizing and initialization
+
+ d3 = d1 + eval( s1 + d2 );
+ \endcode
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ blaze::DynamicVector<double> x, y;
+
+ // ... Resizing and initialization
+
+ y = eval( A * B ) * x;
+ \endcode
+
+// \n Previous: \ref error_reporting_customization
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/Util.h b/src/cpu/blaze/Util.h
new file mode 100644
index 00000000..53134fe8
--- /dev/null
+++ b/src/cpu/blaze/Util.h
@@ -0,0 +1,90 @@
+//=================================================================================================
+/*!
+// \file blaze/Util.h
+// \brief Header file for the inclusion of the utility module of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MODULE_H_
+#define _BLAZE_UTIL_MODULE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/AlignedAllocator.h>
+#include <blaze/util/AlignedArray.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Algorithm.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/ColorMacros.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/Constraints.h>
+#include <blaze/util/Convert.h>
+#include <blaze/util/DimensionOf.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EmptyType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Exception.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InputString.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/Limits.h>
+#include <blaze/util/Logging.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/MemoryPool.h>
+#include <blaze/util/MPL.h>
+#include <blaze/util/NonCopyable.h>
+#include <blaze/util/NonCreatable.h>
+#include <blaze/util/NullType.h>
+#include <blaze/util/PointerCast.h>
+#include <blaze/util/Policies.h>
+#include <blaze/util/PtrIterator.h>
+#include <blaze/util/PtrVector.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/Serialization.h>
+#include <blaze/util/Singleton.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Suffix.h>
+#include <blaze/util/SystemClock.h>
+#include <blaze/util/SystemClockID.h>
+#include <blaze/util/Thread.h>
+#include <blaze/util/ThreadPool.h>
+#include <blaze/util/Time.h>
+#include <blaze/util/Timing.h>
+#include <blaze/util/TypeList.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/TypeTraits.h>
+#include <blaze/util/UnsignedValue.h>
+#include <blaze/util/ValueTraits.h>
+
+#endif
diff --git a/src/cpu/blaze/config/Assertion.h b/src/cpu/blaze/config/Assertion.h
new file mode 100644
index 00000000..bd9dd024
--- /dev/null
+++ b/src/cpu/blaze/config/Assertion.h
@@ -0,0 +1,65 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Assertion.h
+// \brief Configuration of the run time assertion macros
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for internal assertions.
+// \ingroup config
+//
+// This compilation switch triggers internal assertions, which are used to verify the program
+// itself. The internal assertions can also be deactivated by defining \a NDEBUG during the
+// compilation.
+//
+// Possible settings for the internal assertion switch:
+// - Deactivated: \b 0
+// - Activated : \b 1
+*/
+#define BLAZE_INTERNAL_ASSERTION 0
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for user assertions.
+// \ingroup config
+//
+// This compilation switch triggers user assertions, which are used to check user specified
+// function parameters and values. The user assertions can also be deactivated by defining
+// \a NDEBUG during the compilation.
+//
+// Possible settings for the user assertion switch:
+// - Deactivated: \b 0
+// - Activated : \b 1
+*/
+#define BLAZE_USER_ASSERTION 0
+//*************************************************************************************************
diff --git a/src/cpu/blaze/config/BLAS.h b/src/cpu/blaze/config/BLAS.h
new file mode 100644
index 00000000..19aa33b9
--- /dev/null
+++ b/src/cpu/blaze/config/BLAS.h
@@ -0,0 +1,92 @@
+//=================================================================================================
+/*!
+// \file blaze/config/BLAS.h
+// \brief Configuration of the BLAS mode
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the BLAS mode.
+// \ingroup config
+//
+// This compilation switch enables/disables the BLAS mode. In case the BLAS mode is enabled,
+// several basic linear algebra functions (such as for instance matrix-matrix multiplications
+// between two dense matrices) are handled by performance optimized BLAS functions. Note that
+// in this case it is mandatory to provide the according BLAS header file for the compilation
+// of the Blaze library. In case the BLAS mode is disabled, all linear algebra functions use
+// the default implementations of the Blaze library and therefore BLAS is not a requirement
+// for the compilation process.
+//
+// Possible settings for the BLAS switch:
+// - Deactivated: \b 0
+// - Activated : \b 1
+//
+// Note that changing the setting of the BLAS mode requires a recompilation of all code using
+// the Blaze library.
+*/
+#define BLAZE_BLAS_MODE 0
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the parallel BLAS mode.
+// \ingroup config
+//
+// This compilation switch specifies whether the used BLAS library is itself parallelized or not.
+// In case the given BLAS library is itself parallelized, the Blaze library does not perform any
+// attempt to parallelize the execution of BLAS kernels. If, however, the given BLAS library is
+// not parallelized Blaze will attempt to parallelize the execution of BLAS kernels.
+//
+// Possible settings for the switch:
+// - BLAS library is not parallelized: \b 0
+// - BLAS library is parallelized : \b 1
+//
+// Note that changing the setting of the BLAS mode requires a recompilation of all code using the
+// Blaze library.
+*/
+#define BLAZE_BLAS_IS_PARALLEL 0
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the of the BLAS include file.
+// \ingroup config
+//
+// This compilation switch specifies the name of the BLAS include file. By default, the header
+// \c <cblas.h> is included when the BLAS mode is activated. In case the name of the include file
+// differs (as for instance in case of the MKL the file is called \c <mkl_cblas.h>) this switch
+// needs to be adapted accordingly.
+//
+// Note that changing the name of the BLAS include file requires a recompilation of all code using
+// the Blaze library.
+*/
+#define BLAZE_BLAS_INCLUDE_FILE <cblas.h>
+//*************************************************************************************************
diff --git a/src/cpu/blaze/config/CacheSize.h b/src/cpu/blaze/config/CacheSize.h
new file mode 100644
index 00000000..24ca536f
--- /dev/null
+++ b/src/cpu/blaze/config/CacheSize.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/config/CacheSize.h
+// \brief Configuration of the cache size of the target architecture
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief Cache size of the target architecture.
+// \ingroup config
+//
+// This setting specifies the available cache size in Byte of the used target architecture.
+// Several algorithms use this setting for an optimized evaluation.
+//
+// The size of the cache is specified in Byte. For instance, a cache of 3 MiByte must therefore
+// be specified as 3145728.
+*/
+constexpr size_t cacheSize = 3145728UL;
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/Config.h b/src/cpu/blaze/config/Config.h
new file mode 100644
index 00000000..570b482e
--- /dev/null
+++ b/src/cpu/blaze/config/Config.h
@@ -0,0 +1,53 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Config.h
+// \brief Config module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_CONFIG_CONFIG_H_
+#define _BLAZE_CONFIG_CONFIG_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup config Configuration
+//
+// The configuration module offers the possibility to tune the Blaze library to the individual
+// needs and requirements.
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/config/Debugging.h b/src/cpu/blaze/config/Debugging.h
new file mode 100644
index 00000000..ceab58a2
--- /dev/null
+++ b/src/cpu/blaze/config/Debugging.h
@@ -0,0 +1,55 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Debugging.h
+// \brief Configuration of the debugging policy of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the (de-)activation of the debug mode.
+// \ingroup config
+//
+// This compilation switch enables/disables the debug mode of the Blaze library. In case the
+// switch is set to 1 (i.e. in case the debug mode is enabled), the Blaze library is allowed
+// to perform additional runtime checks and to modify user-defined settings to guarantee a
+// full and thorough debugging process. In case the switch is set to 0 (i.e. the debug mode
+// is disabled), no additional checks are added and no settings are modified.
+//
+// Possible settings for the debug mode switch:
+// - Deactivated: \b 0 (default)
+// - Activated : \b 1
+*/
+#define BLAZE_USE_DEBUG_MODE 0
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/Inline.h b/src/cpu/blaze/config/Inline.h
new file mode 100644
index 00000000..4bd7fc4c
--- /dev/null
+++ b/src/cpu/blaze/config/Inline.h
@@ -0,0 +1,75 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Inline.h
+// \brief Configuration of the inline policy of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for a strengthened inline keyword.
+// \ingroup config
+//
+// The regular C++ \c inline keyword merely represents a hint to the compiler to inline a function.
+// Due to that, when using the \c inline keyword for performance critical functions, one is at the
+// mercy of the compiler to properly inline the functions. In order to improve the likelihood of
+// a function being properly inlined the BLAZE_STRONG_INLINE keyword can be used. In contrast to
+// the regular \c inline keyword, BLAZE_STRONG_INLINE uses platform-specific keywords and modifiers
+// to improve the likelihood of a function being properly inlined. Please note, however, that even
+// in case the platform-specific inline is used, there is no guarantee that a function is inlined
+// (see for instance the http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx).
+//
+// This compilation switch enables/disables the BLAZE_STRONG_INLINE keyword. When disabled, the
+// keyword uses the regular \c inline keyword as fallback. Possible setting for the switch are:
+// - Deactivated: \b 0
+// - Activated : \b 1
+*/
+#define BLAZE_USE_STRONG_INLINE 1
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for an enforced inline keyword.
+// \ingroup config
+//
+// Although the BLAZE_STRONG_INLINE keyword improves the likelihood of a function being inlined it
+// does not provide a 100% guarantee. Depending on the availability of an according keyword and/or
+// modifier on a specific platform, this guarantee is provided by the BLAZE_ALWAYS_INLINE keyword,
+// which uses platform-specific functionality to enforce the inlining of a function.
+//
+// This compilation switch enables/disables the BLAZE_ALWAYS_INLINE keyword. When disabled or in
+// case the platform does not provide a keyword and/or modifier for a 100% inline guarantee, the
+// BLAZE_ALWAYS_INLINE keyword uses the BLAZE_STRONG_INLINE keyword as fallback. Possible settings
+// for the switch are:
+// - Deactivated: \b 0
+// - Activated : \b 1
+*/
+#define BLAZE_USE_ALWAYS_INLINE 1
+//*************************************************************************************************
diff --git a/src/cpu/blaze/config/Logging.h b/src/cpu/blaze/config/Logging.h
new file mode 100644
index 00000000..4710c39c
--- /dev/null
+++ b/src/cpu/blaze/config/Logging.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Logging.h
+// \brief Configuration of the logging functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+namespace logging {
+
+//*************************************************************************************************
+/*!\brief Setting of the logging level.
+// \ingroup config
+//
+// This value specifies the logging level of the Blaze logging functionality. Depending on
+// this setting, more or less informations will be written to the log file(s). The following
+// logging levels can be selected:
+//
+// - \a inactive: Completely deactives the logging functionality, i.e., no log file(s) will be
+// written. Since this setting can immensely complicate error correction, it is
+// not recommended to use this setting!
+// - \a error : Only (severe) errors are written to the log file(s).
+// - \a warning : Extends the \a error setting by warning messages.
+// - \a info : Extends the \a warning setting by additional informative messages (default).
+// - \a progress: Extends the \a info setting by progress informations.
+// - \a debug : Extends the \a progress setting by debug information.
+// - \a detail : Extends the \a debug setting by very fine grained detail information.
+*/
+constexpr LogLevel loglevel = info;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Adding an additional spacing line between two log messages.
+// \ingroup config
+//
+// This setting gives the opportunity to add an additional spacing line between two log messages
+// to improve readability of log files. If set to \a true, each log message will be appended with
+// an additional empty line. If set to \a false, no line will be appended.
+*/
+constexpr bool spacing = false;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for function traces.
+// \ingroup config
+//
+// This compilation switch triggers the use of function traces. In case the switch is set to
+// 1, function traces via the BLAZE_FUNCTION_TRACE are enabled. Note however, that enabling
+// function traces creates a dependency to the compiled Blaze library, i.e. it will be
+// necessary to link the Blaze library to the executable. This is also true in case only
+// template functionality is used!
+//
+// Possible settings for the function trace switch:
+// - Deactivated: \b 0 (default)
+// - Activated : \b 1
+*/
+#define BLAZE_USE_FUNCTION_TRACES 0
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/MPI.h b/src/cpu/blaze/config/MPI.h
new file mode 100644
index 00000000..c94865d7
--- /dev/null
+++ b/src/cpu/blaze/config/MPI.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/config/MPI.h
+// \brief Configuration of the MPI parallelization
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the MPI parallelization.
+// \ingroup mpi
+//
+// This compilation switch enables/disables the MPI parallelization.
+//
+// Possible settings for the MPI switch:
+// - Deactivated: \b 0
+// - Activated : \b 1
+//
+// Note that changing the setting of the MPI parallel mode requires a recompilation of the
+// Blaze library. Also note that this switch is automatically set by the configuration script
+// of the Blaze library.
+*/
+#define BLAZE_MPI_PARALLEL_MODE 0
+//*************************************************************************************************
diff --git a/src/cpu/blaze/config/Optimizations.h b/src/cpu/blaze/config/Optimizations.h
new file mode 100644
index 00000000..24b6171b
--- /dev/null
+++ b/src/cpu/blaze/config/Optimizations.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Optimizations.h
+// \brief Configuration of performance optimizations
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief Configuration of the padding of dense vectors and matrices.
+// \ingroup config
+//
+// This configuration switch enables/disables the padding of dense vectors and matrices. Padding
+// is used by the Blaze library in order to achieve maximum performance for both dense vector
+// and matrix operations. Due to padding, the proper alignment of data elements can be guaranteed
+// and the need for remainder loops is minimized. In case the switch is set to \a true, padding
+// is enabled for all native dense vectors and matrices. If the switch is set to \a false, padding
+// is generally disabled.
+//
+// \warning Note that disabling padding can considerably reduce the performance of all dense
+// vector and matrix operations!
+*/
+constexpr bool usePadding = true;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Configuration of the streaming behavior.
+// \ingroup config
+//
+// For large vectors and matrices non-temporal stores can provide a significant performance
+// advantage of about 20%. However, this advantage is only in effect in case the memory bandwidth
+// of the target architecture is maxed out. If the target architecture's memory bandwidth cannot
+// be exhausted the use of non-temporal stores can decrease performance instead of increasing it.
+//
+// Via this compilation switch streaming (i.e. non-temporal stores) can be (de-)activated. If
+// set to \a true streaming is enabled, if set to \a false streaming is disabled.
+*/
+constexpr bool useStreaming = true;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Configuration switch for optimized kernels.
+// \ingroup config
+//
+// This configuration switch enables/disables all optimized compute kernels of the Blaze library,
+// including all vectorized and data type depending kernels. In case the switch is set to \a true
+// the optimized kernels are used whenever possible. In case the switch is set to \a false all
+// optimized kernels are not used, even if it would be possible.
+//
+// \warning Note that disabling the optimized kernels causes a severe performance limitiation
+// to nearly all operations!
+*/
+constexpr bool useOptimizedKernels = true;
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/Precision.h b/src/cpu/blaze/config/Precision.h
new file mode 100644
index 00000000..8b5a9706
--- /dev/null
+++ b/src/cpu/blaze/config/Precision.h
@@ -0,0 +1,50 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Precision.h
+// \brief Configuration of the floating point precision of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief Floating point data type of the Blaze library.
+// \ingroup config
+//
+// This type definition offers the possibility to switch the floating point precision of
+// the Blaze library between float, double and long double.
+//
+// Valid types for the \a real_t floating point type: <a>float, double, long double</a>
+*/
+typedef float real_t;
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/Random.h b/src/cpu/blaze/config/Random.h
new file mode 100644
index 00000000..cd34f0f0
--- /dev/null
+++ b/src/cpu/blaze/config/Random.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Random.h
+// \brief Configuration of the random number generator used in the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief Type of the random number generator of the Blaze library.
+// \ingroup config
+//
+// This type definition represents the type of the random number generated used in the Blaze
+// library. The default random number generator is the std::mt19937 mersenne-twister pseudo
+// random number generator. For more information see the following reference documentation:
+//
+// http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine
+*/
+typedef std::mt19937 RNG;
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/Restrict.h b/src/cpu/blaze/config/Restrict.h
new file mode 100644
index 00000000..38ccb512
--- /dev/null
+++ b/src/cpu/blaze/config/Restrict.h
@@ -0,0 +1,47 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Restrict.h
+// \brief Configuration of the restrict policy of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for C99 restrict keyword.
+// \ingroup config
+//
+// This compilation switch enables/disables the C99 restrict keyword.
+//
+// Possible settings for the C99 restrict switch:
+// - Deactivated: \b 0
+// - Activated : \b 1
+*/
+#define BLAZE_USE_RESTRICT 1
+//*************************************************************************************************
diff --git a/src/cpu/blaze/config/SMP.h b/src/cpu/blaze/config/SMP.h
new file mode 100644
index 00000000..b634c0f5
--- /dev/null
+++ b/src/cpu/blaze/config/SMP.h
@@ -0,0 +1,54 @@
+//=================================================================================================
+/*!
+// \file blaze/config/SMP.h
+// \brief Configuration of the shared-memory parallelization
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the (de-)activation of the shared-memory parallelization
+// \ingroup config
+//
+// This compilation switch enables/disables the shared-memory parallelization. In case the switch
+// is set to 1 (i.e. in case the shared-memory parallelization is enabled), the Blaze library is
+// allowed to execute operations in parallel. In case the switch is set to 0 (i.e. parallelization
+// is disabled), the Blaze library is restricted from executing operations in parallel.
+//
+// Possible settings for the shared-memory parallelization switch:
+// - Deactivated: \b 0
+// - Activated : \b 1 (default)
+*/
+#define BLAZE_USE_SHARED_MEMORY_PARALLELIZATION 1
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/StorageOrder.h b/src/cpu/blaze/config/StorageOrder.h
new file mode 100644
index 00000000..c25727ee
--- /dev/null
+++ b/src/cpu/blaze/config/StorageOrder.h
@@ -0,0 +1,59 @@
+//=================================================================================================
+/*!
+// \file blaze/config/StorageOrder.h
+// \brief Configuration of the default storage order for all matrices of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief The default storage order for all matrices of the Blaze library.
+// \ingroup config
+//
+// This value specifies the default storage order for all matrices of the Blaze library.
+// In case no explicit storage order is specified with the according matrix type, this
+// setting is used.
+
+ \code
+ // Explicit specification of the storage order => row-major matrix
+ StaticMatrix<double,3UL,3UL,rowMajor> A;
+
+ // No explicit specification of the storage order => use of the defaultStorageOrder
+ StaticMatrix<double,3UL,3UL> B;
+ \endcode
+
+// Valid settings for the defaultStorageOrder are blaze::rowMajor and blaze::columnMajor.
+*/
+constexpr bool defaultStorageOrder = rowMajor;
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/Thresholds.h b/src/cpu/blaze/config/Thresholds.h
new file mode 100644
index 00000000..2e0bb56f
--- /dev/null
+++ b/src/cpu/blaze/config/Thresholds.h
@@ -0,0 +1,1308 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Thresholds.h
+// \brief Configuration of the thresholds for matrix/vector and matrix/matrix multiplications
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLAS THRESHOLDS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Row-major dense matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the custom Blaze kernels
+// and the BLAS kernels for the row-major dense matrix/dense vector multiplication. In case
+// the number of elements in the dense matrix is equal or higher than this value, the BLAS
+// kernels are preferred over the custom Blaze kernels. In case the number of elements in the
+// dense matrix is smaller, the Blaze kernels are used.
+//
+// The default setting for this threshold is 4000000 (which for instance corresponds to a matrix
+// size of \f$ 2000 \times 2000 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::DMATDVECMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t DMATDVECMULT_USER_THRESHOLD = 4000000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major dense matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the custom Blaze kernels
+// and the BLAS kernels for the column-major dense matrix/dense vector multiplication. In case
+// the number of elements in the dense matrix is equal or higher than this value, the BLAS
+// kernels are preferred over the custom Blaze kernels. In case the number of elements in the
+// dense matrix is smaller, the Blaze kernels are used.
+//
+// The default setting for this threshold is 62500 (which for instance corresponds to a matrix
+// size of \f$ 250 \times 250 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::TDMATDVECMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t TDMATDVECMULT_USER_THRESHOLD = 62500UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Dense Vector/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the custom Blaze kernels
+// and the BLAS kernels for the dense vector/row-major dense matrix multiplication. In case
+// the number of elements in the dense matrix is equal or higher than this value, the BLAS
+// kernels are preferred over the custom Blaze kernels. In case the number of elements in the
+// dense matrix is smaller, the Blaze kernels are used.
+//
+// The default setting for this threshold is 62500 (which for instance corresponds to a matrix
+// size of \f$ 250 \times 250 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::TDVECDMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t TDVECDMATMULT_USER_THRESHOLD = 62500UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Dense Vector/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the custom Blaze kernels
+// and the BLAS kernels for the dense vector/column-major dense matrix multiplication. In case
+// the number of elements in the dense matrix is equal or higher than this value, the BLAS
+// kernels are preferred over the custom Blaze kernels. In case the number of elements in the
+// dense matrix is smaller, the Blaze kernels are used.
+//
+// The default setting for this threshold is 4000000 (which for instance corresponds to a matrix
+// size of \f$ 2000 \times 2000 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::TDVECTDMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t TDVECTDMATMULT_USER_THRESHOLD = 4000000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Row-major dense matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the custom Blaze kernels and
+// the BLAS kernels for the row-major dense matrix/row-major dense matrix multiplication. In
+// case the number of elements of the target matrix is equal or higher than this value, the
+// BLAS kernels are preferred over the custom Blaze kernels. In case the number of elements in
+// the target matrix is smaller, the Blaze kernels are used.
+//
+// The default setting for this threshold is 10000 (which for instance corresponds to a matrix
+// size of \f$ 100 \times 100 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::DMATDMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t DMATDMATMULT_USER_THRESHOLD = 10000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Row-major dense matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the custom Blaze kernels and
+// the BLAS kernels for the row-major dense matrix/column-major dense matrix multiplication. In
+// case the number of elements of the target matrix is equal or higher than this value, the
+// BLAS kernels are preferred over the custom Blaze kernels. In case the number of elements in
+// the target matrix is smaller, the Blaze kernels are used.
+//
+// The default setting for this threshold is 10000 (which for instance corresponds to a matrix
+// size of \f$ 100 \times 100 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::DMATTDMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t DMATTDMATMULT_USER_THRESHOLD = 10000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major dense matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the custom Blaze kernels and
+// the BLAS kernels for the column-major dense matrix/row-major dense matrix multiplication. In
+// case the number of elements of the target matrix is equal or higher than this value, the
+// BLAS kernels are preferred over the custom Blaze kernels. In case the number of elements in
+// the target matrix is smaller, the Blaze kernels are used.
+//
+// The default setting for this threshold is 10000 (which for instance corresponds to a matrix
+// size of \f$ 100 \times 100 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::TDMATDMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t TDMATDMATMULT_USER_THRESHOLD = 10000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major dense matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the custom Blaze kernels and
+// the BLAS kernels for the column-major dense matrix/column-major dense matrix multiplication.
+// In case the number of elements of the target matrix is equal or higher than this value, the
+// BLAS kernels are preferred over the custom Blaze kernels. In case the number of elements in
+// the target matrix is smaller, the Blaze kernels are used.
+//
+// The default setting for this threshold is 10000 (which for instance corresponds to a matrix
+// size of \f$ 100 \times 100 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::TDMATTDMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t TDMATTDMATMULT_USER_THRESHOLD = 10000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Row-major dense matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the Blaze kernels for small
+// and for large row-major dense matrix/row-major sparse matrix multiplications. In case the
+// number of elements of the target matrix is equal or higher than this value, the kernel for
+// large matrices is preferred over the kernel for small matrices. In case the number of elements
+// in the target matrix is smaller, the kernel for small matrices is used.
+//
+// The default setting for this threshold is 2500 (which for instance corresponds to a matrix
+// size of \f$ 50 \times 50 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::DMATSMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t DMATSMATMULT_USER_THRESHOLD = 2500UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major dense matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the Blaze kernels for small
+// and for large column-major dense matrix/row-major sparse matrix multiplications. In case the
+// number of elements of the target matrix is equal or higher than this value, the kernel for
+// large matrices is preferred over the kernel for small matrices. In case the number of elements
+// in the target matrix is smaller, the kernel for small matrices is used.
+//
+// The default setting for this threshold is 2500 (which for instance corresponds to a matrix
+// size of \f$ 50 \times 50 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::TDMATSMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t TDMATSMATMULT_USER_THRESHOLD = 2500UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major sparse matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the Blaze kernels for small
+// and for large column-major sparse matrix/row-major dense matrix multiplications. In case the
+// number of elements of the target matrix is equal or higher than this value, the kernel for
+// large matrices is preferred over the kernel for small matrices. In case the number of elements
+// in the target matrix is smaller, the kernel for small matrices is used.
+//
+// The default setting for this threshold is 10000 (which for instance corresponds to a matrix
+// size of \f$ 100 \times 100 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::TSMATDMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t TSMATDMATMULT_USER_THRESHOLD = 10000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major sparse matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This setting specifies the threshold between the application of the Blaze kernels for small
+// and for large column-major sparse matrix/column-major dense matrix multiplications. In case
+// the number of elements of the target matrix is equal or higher than this value, the kernel for
+// large matrices is preferred over the kernel for small matrices. In case the number of elements
+// in the target matrix is smaller, the kernel for small matrices is used.
+//
+// The default setting for this threshold is 22500 (which for instance corresponds to a matrix
+// size of \f$ 150 \times 150 \f$). Note that in case the Blaze debug mode is active, this
+// threshold will be replaced by the blaze::TSMATTDMATMULT_DEBUG_THRESHOLD value.
+*/
+constexpr size_t TSMATTDMATMULT_USER_THRESHOLD = 22500UL;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMP THRESHOLDS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief SMP dense vector assignment threshold.
+// \ingroup config
+//
+// This threshold specifies when an assignment of a simple dense vector can be executed in
+// parallel. In case the number of elements of the target vector is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of elements is below this
+// threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 38000. In case the threshold is set to 0, the
+// operation is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DVECASSIGN_USER_THRESHOLD = 38000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector addition threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/dense vector addition can be executed in parallel.
+// In case the number of elements of the target vector is larger or equal to this threshold, the
+// operation is executed in parallel. If the number of elements is below this threshold the
+// operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 38000. In case the threshold is set to 0, the
+// operation is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DVECDVECADD_USER_THRESHOLD = 38000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector subtraction threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/dense vector subtraction can be executed in
+// parallel. In case the number of elements of the target vector is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of elements is below this
+// threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 38000. In case the threshold is set to 0, the
+// operation is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DVECDVECSUB_USER_THRESHOLD = 38000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/dense vector multiplication can be executed
+// in parallel. In case the number of elements of the target vector is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of elements is below this
+// threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 38000. In case the threshold is set to 0, the
+// operation is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DVECDVECMULT_USER_THRESHOLD = 38000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector division threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/dense vector division can be executed in
+// parallel. In case the number of elements of the target vector is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of elements is below this
+// threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 38000. In case the threshold is set to 0, the
+// operation is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DVECDVECDIV_USER_THRESHOLD = 38000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/scalar multiplication/division threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/scalar multiplication/division can be executed
+// in parallel. In case the number of elements of the target vector is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of elements is below this
+// threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 51000. In case the threshold is set to 0, the
+// operation is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DVECSCALARMULT_USER_THRESHOLD = 51000UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/dense vector multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 330. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATDVECMULT_USER_THRESHOLD = 330UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major dense matrix/dense vector multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 360. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDMATDVECMULT_USER_THRESHOLD = 360UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/row-major dense matrix multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 370. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDVECDMATMULT_USER_THRESHOLD = 370UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/column-major dense matrix multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 340. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDVECTDMATMULT_USER_THRESHOLD = 340UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/sparse vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/sparse vector multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 480. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATSVECMULT_USER_THRESHOLD = 480UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/sparse vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major dense matrix/sparse vector multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 910. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDMATSVECMULT_USER_THRESHOLD = 910UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP sparse vector/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a sparse vector/row-major dense matrix multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 910. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSVECDMATMULT_USER_THRESHOLD = 910UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP sparse vector/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a sparse vector/column-major dense matrix multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 480. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSVECTDMATMULT_USER_THRESHOLD = 480UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major sparse matrix/dense vector multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 600. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_SMATDVECMULT_USER_THRESHOLD = 600UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major sparse matrix/dense vector multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 1250. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSMATDVECMULT_USER_THRESHOLD = 1250UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/row-major sparse matrix multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 1190. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDVECSMATMULT_USER_THRESHOLD = 1190UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/column-major sparse matrix multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 530. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDVECTSMATMULT_USER_THRESHOLD = 530UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/sparse vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major sparse matrix/sparse vector multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 260. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_SMATSVECMULT_USER_THRESHOLD = 260UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/sparse vector multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major sparse matrix/sparse vector multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 2160. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSMATSVECMULT_USER_THRESHOLD = 2160UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP sparse vector/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a sparse vector/row-major sparse matrix multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 2160. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSVECSMATMULT_USER_THRESHOLD = 2160UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP sparse vector/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a sparse vector/column-major sparse matrix multiplication can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 260. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSVECTSMATMULT_USER_THRESHOLD = 260UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense matrix assignment threshold.
+// \ingroup config
+//
+// This threshold specifies when an assignment with a simple dense matrix can be executed in
+// parallel. In case the number of rows/columns of the target matrix is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of rows/columns is below this
+// threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 220. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATASSIGN_USER_THRESHOLD = 220UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/row-major dense matrix addition threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/row-major dense matrix addition can
+// be executed in parallel. This threshold affects both additions between two row-major matrices
+// or two column-major dense matrices. In case the number of rows/columns of the target matrix
+// is larger or equal to this threshold, the operation is executed in parallel. If the number of
+// rows/columns is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 190. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATDMATADD_USER_THRESHOLD = 190UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/column-major dense matrix addition threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/column-major dense matrix addition can
+// be executed in parallel. This threshold affects both additions between a row-major matrix and
+// a column-major matrix and a column-major matrix and a row-major matrix. In case the number of
+// rows/columns of the target matrix is larger or equal to this threshold, the operation is
+// executed in parallel. If the number of rows/columns is below this threshold the operation is
+// executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 175. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATTDMATADD_USER_THRESHOLD = 175UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/row-major dense matrix subtraction threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/row-major dense matrix subtraction
+// can be executed in parallel. This threshold affects both subtractions between two row-major
+// matrices or two column-major dense matrices. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 190. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATDMATSUB_USER_THRESHOLD = 190UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/column-major dense matrix subtraction threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/column-major dense matrix subtraction
+// can be executed in parallel. This threshold affects both subtractions between a row-major
+// matrix and a column-major matrix and a column-major matrix and a row-major matrix. In case
+// the number of rows/columns of the target matrix is larger or equal to this threshold, the
+// operation is executed in parallel. If the number of rows/columns is below this threshold
+// the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 175. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATTDMATSUB_USER_THRESHOLD = 175UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense matrix/scalar multiplication/division threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense matrix/scalar multiplication or division can be executed
+// in parallel. In case the number of rows/columns of the target matrix is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of rows/columns is below this
+// threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 220. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATSCALARMULT_USER_THRESHOLD = 220UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/row-major dense matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 55. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATDMATMULT_USER_THRESHOLD = 55UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/column-major dense matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 55. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATTDMATMULT_USER_THRESHOLD = 55UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major dense matrix/row-major dense matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 55. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDMATDMATMULT_USER_THRESHOLD = 55UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major dense matrix/column-major dense matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 55. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDMATTDMATMULT_USER_THRESHOLD = 55UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/row-major sparse matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 64. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATSMATMULT_USER_THRESHOLD = 64UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major dense matrix/column-major sparse matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 68. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DMATTSMATMULT_USER_THRESHOLD = 68UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major dense matrix/row-major sparse matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 90. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDMATSMATMULT_USER_THRESHOLD = 90UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major dense matrix/column-major sparse matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 90. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TDMATTSMATMULT_USER_THRESHOLD = 90UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major sparse matrix/row-major dense matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 88. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_SMATDMATMULT_USER_THRESHOLD = 88UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major sparse matrix/column-major dense matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 72. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_SMATTDMATMULT_USER_THRESHOLD = 72UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major sparse matrix/row-major dense matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 66. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSMATDMATMULT_USER_THRESHOLD = 66UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major sparse matrix/column-major dense matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 66. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSMATTDMATMULT_USER_THRESHOLD = 66UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major sparse matrix/row-major sparse matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 150. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_SMATSMATMULT_USER_THRESHOLD = 150UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a row-major sparse matrix/column-major sparse matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 140. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_SMATTSMATMULT_USER_THRESHOLD = 140UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major sparse matrix/row-major sparse matrix multiplication
+// can be executed in parallel. In case the number of rows/columns of the target matrix is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of rows/columns
+// is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 140. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSMATSMATMULT_USER_THRESHOLD = 140UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This threshold specifies when a column-major sparse matrix/column-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 150. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_TSMATTSMATMULT_USER_THRESHOLD = 150UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector outer product threshold.
+// \ingroup config
+//
+// This threshold specifies when a dense vector/dense vector outer product can be executed in
+// parallel. In case the number of rows/columns of the target matrix is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of rows/columns is below this
+// threshold the operation is executed single-threaded.
+//
+// Please note that this threshold is highly sensitiv to the used system architecture and the
+// shared memory parallelization technique. Therefore the default value cannot guarantee maximum
+// performance for all possible situations and configurations. It merely provides a reasonable
+// standard for the current generation of CPUs. Also note that the provided default has been
+// determined using the OpenMP parallelization and requires individual adaption for the C++11
+// and Boost thread parallelization.
+//
+// The default setting for this threshold is 290. In case the threshold is set to 0, the operation
+// is unconditionally executed in parallel.
+*/
+constexpr size_t SMP_DVECTDVECMULT_USER_THRESHOLD = 290UL;
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/TransposeFlag.h b/src/cpu/blaze/config/TransposeFlag.h
new file mode 100644
index 00000000..718d1199
--- /dev/null
+++ b/src/cpu/blaze/config/TransposeFlag.h
@@ -0,0 +1,59 @@
+//=================================================================================================
+/*!
+// \file blaze/config/TransposeFlag.h
+// \brief Configuration of the default transpose flag for all vectors of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief The default transpose flag for all vectors of the Blaze library.
+// \ingroup config
+//
+// This value specifies the default transpose flag for all vector of the Blaze library.
+// In case no explicit transpose flag is specified with the according vector type, this
+// setting is used.
+
+ \code
+ // Explicit specification of the transpose flag => column vector
+ StaticVector<double,3UL,columnMajor> a;
+
+ // No explicit specification of the transpose flag => use of the defaultTransposeFlag
+ StaticVector<double,3UL> b;
+ \endcode
+
+// Valid settings for the defaultTransposeFlag are blaze::rowVector and blaze::columnVector.
+*/
+constexpr bool defaultTransposeFlag = columnVector;
+//*************************************************************************************************
+
+} // namespace blaze
diff --git a/src/cpu/blaze/config/Vectorization.h b/src/cpu/blaze/config/Vectorization.h
new file mode 100644
index 00000000..9ff12338
--- /dev/null
+++ b/src/cpu/blaze/config/Vectorization.h
@@ -0,0 +1,54 @@
+//=================================================================================================
+/*!
+// \file blaze/config/Vectorization.h
+// \brief Configuration of the vectorization policy of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for (de-)activation of the Blaze vectorization.
+// \ingroup config
+//
+// This compilation switch enables/disables vectorization of mathematical expressions via
+// the SSE, AVX, and/or MIC instruction sets. In case the switch is set to 1 (i.e. in case
+// vectorization is enabled), the Blaze library attempts to vectorize the linear algebra
+// operations by SSE, AVX, and/or MIC intrinsics (depending on which instruction set is
+// available on the target platform). In case the switch is set to 0 (i.e. vectorization
+// is disabled), the Blaze library chooses default, non-vectorized functionality for the
+// operations. Note that deactivating the vectorization may pose a severe performance
+// limitation for a large number of operations!
+//
+// Possible settings for the vectorization switch:
+// - Deactivated: \b 0
+// - Activated : \b 1 (default)
+*/
+#define BLAZE_USE_VECTORIZATION 1
+//*************************************************************************************************
diff --git a/src/cpu/blaze/math/Accuracy.h b/src/cpu/blaze/math/Accuracy.h
new file mode 100644
index 00000000..cb739435
--- /dev/null
+++ b/src/cpu/blaze/math/Accuracy.h
@@ -0,0 +1,906 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Accuracy.h
+// \brief Computation accuracy for floating point data types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ACCURACY_H_
+#define _BLAZE_MATH_ACCURACY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/Limits.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Negative computation accuracy for floating point data types.
+// \ingroup math
+//
+// The NegativeAccuracy class is a wrapper class around the functionality of the blaze::Limits
+// class. It represents the negative computation accuracy of the Blaze library for any floating
+// point data type. In order to assign a negative accuracy value, the NegativeAccuracy class can
+// be implicitly converted to the three built-in floating point data types float, double and long
+// double.
+//
+// \note The NegativeAccuracy class is a helper class for the Accuracy class. It cannot be
+// instantiated on its own, but can only be used by the Accuracy class.
+*/
+template< typename A > // Positive accuracy type
+class NegativeAccuracy
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef A PositiveType; //!< The positive accuracy type.
+ //**********************************************************************************************
+
+ private:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline NegativeAccuracy();
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Unary plus/minus operators******************************************************************
+ /*!\name Unary plus/minus operators */
+ //@{
+ inline const NegativeAccuracy& operator+() const;
+ inline const PositiveType operator-() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ template< typename T >
+ inline operator const T() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ NegativeAccuracy& operator=( const NegativeAccuracy& ); //!< Copy assignment operator (private & undefined)
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend class Accuracy;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor of the NegativeAccuracy class.
+*/
+template< typename A > // Positive accuracy type
+inline NegativeAccuracy<A>::NegativeAccuracy()
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UNARY PLUS/MINUS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the negative computation accuracy for all floating point data types.
+//
+// \return The negative computation accuracy.
+*/
+template< typename A > // Positive accuracy type
+inline const NegativeAccuracy<A>& NegativeAccuracy<A>::operator+() const
+{
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the positive computation accuracy for all floating point data types.
+//
+// \return The positive computation accuracy.
+*/
+template< typename A > // Positive accuracy type
+inline const typename NegativeAccuracy<A>::PositiveType NegativeAccuracy<A>::operator-() const
+{
+ return PositiveType();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the required floating point data type.
+//
+// The conversion operator returns the negative computation accuracy for the floating point
+// data type \a T.
+*/
+template< typename A > // Positive accuracy type
+template< typename T > // Floating point data type
+inline NegativeAccuracy<A>::operator const T() const
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Accuracy operators */
+//@{
+template< typename A, typename T >
+inline bool operator==( const NegativeAccuracy<A>& lhs, const T& rhs );
+
+template< typename A, typename T >
+inline bool operator==( const T& lhs, const NegativeAccuracy<A>& rhs );
+
+template< typename A, typename T >
+inline bool operator!=( const NegativeAccuracy<A>& lhs, const T& rhs );
+
+template< typename A, typename T >
+inline bool operator!=( const T& lhs, const NegativeAccuracy<A>& rhs );
+
+template< typename A, typename T >
+inline bool operator<( const NegativeAccuracy<A>& lhs, const T& rhs );
+
+template< typename A, typename T >
+inline bool operator<( const T& lhs, const NegativeAccuracy<A>& rhs );
+
+template< typename A, typename T >
+inline bool operator>( const NegativeAccuracy<A>& lhs, const T& rhs );
+
+template< typename A, typename T >
+inline bool operator>( const T& lhs, const NegativeAccuracy<A>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a NegativeAccuracy object and a floating point value.
+// \ingroup math
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is equal to the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator==( const NegativeAccuracy<A>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::accuracy() == rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a floating point value and a NegativeAccuracy object.
+// \ingroup math
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is equal to the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator==( const T& lhs, const NegativeAccuracy<A>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs == -Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a NegativeAccuracy object and a floating point value.
+// \ingroup math
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is unequal to the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator!=( const NegativeAccuracy<A>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::accuracy() != rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a floating point value and a NegativeAccuracy object.
+// \ingroup math
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is unequal to the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator!=( const T& lhs, const NegativeAccuracy<A>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs != -Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between a NegativeAccuracy object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is greater than the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator<( const NegativeAccuracy<A>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::accuracy() < rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between a floating point value and a NegativeAccuracy object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is smaller than the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator<( const T& lhs, const NegativeAccuracy<A>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs < -Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between a NegativeAccuracy object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is smaller than the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator>( const NegativeAccuracy<A>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::accuracy() > rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between a floating point value and a NegativeAccuracy object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is greater than the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator>( const T& lhs, const NegativeAccuracy<A>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs > -Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a NegativeAccuracy object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is greater than or equal to the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator<=( const NegativeAccuracy<A>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::accuracy() <= rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a floating point value and a NegativeAccuracy object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is smaller than or equal to the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator<=( const T& lhs, const NegativeAccuracy<A>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs <= -Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between a NegativeAccuracy object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is smaller than or equal to the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator>=( const NegativeAccuracy<A>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::accuracy() >= rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a floating point value and a NegativeAccuracy object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is greater than or equal to the negative accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename A // Positive accuracy type
+ , typename T > // Floating point data type
+inline bool operator>=( const T& lhs, const NegativeAccuracy<A>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs >= -Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computation accuracy for floating point data types.
+// \ingroup math
+//
+// The Accuracy class is a wrapper class around the functionality of the blaze::Limits class.
+// It represents the computation accuracy of the Blaze library for any floating point data
+// type. In order to assign an accuracy value, the Accuracy class can be implicitly converted
+// to the three built-in floating point data types float, double and long double.\n
+// In order to handle accuracy values conveniently, the global Accuracy instance blaze::accuracy
+// is provided, which can be used wherever a floating point data value is required.
+
+ \code
+ float f = accuracy; // Assigns the positive computation accuracy for single precision values
+ double d = -accuracy; // Assigns the negative computation accuracy for double precision values
+ \endcode
+*/
+class Accuracy
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef NegativeAccuracy<Accuracy> NegativeType; //!< The negated accuracy type.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline Accuracy();
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Unary plus/minus operators******************************************************************
+ /*!\name Unary plus/minus operators */
+ //@{
+ inline const Accuracy& operator+() const;
+ inline const NegativeType operator-() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ template< typename T >
+ inline operator const T() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ Accuracy& operator=( const Accuracy& ); //!< Copy assignment operator (private & undefined)
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor of the Accuracy class.
+*/
+inline Accuracy::Accuracy()
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UNARY PLUS/MINUS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the positive computation accuracy for all floating point data types.
+//
+// \return The positive computation accuracy.
+*/
+inline const Accuracy& Accuracy::operator+() const
+{
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the negative computation accuracy for all floating point data types.
+//
+// \return The negative computation accuracy.
+*/
+inline const Accuracy::NegativeType Accuracy::operator-() const
+{
+ return NegativeType();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the required floating point data type.
+//
+// The conversion operator returns the computation accuracy for the floating point data
+// type \a T.
+*/
+template< typename T > // Floating point data type
+inline Accuracy::operator const T() const
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Accuracy operators */
+//@{
+template< typename T >
+inline bool operator==( const Accuracy& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator==( const T& lhs, const Accuracy& rhs );
+
+template< typename T >
+inline bool operator!=( const Accuracy& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator!=( const T& lhs, const Accuracy& rhs );
+
+template< typename T >
+inline bool operator<( const Accuracy& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator<( const T& lhs, const Accuracy& rhs );
+
+template< typename T >
+inline bool operator>( const Accuracy& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator>( const T& lhs, const Accuracy& rhs );
+
+template< typename T >
+inline bool operator<=( const Accuracy& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator<=( const T& lhs, const Accuracy& rhs );
+
+template< typename T >
+inline bool operator>=( const Accuracy& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator>=( const T& lhs, const Accuracy& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between an Accuracy object and a floating point value.
+// \ingroup math
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is equal to the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator==( const Accuracy& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::accuracy() == rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a floating point value and an Accuracy object.
+// \ingroup math
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is equal to the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator==( const T& lhs, const Accuracy& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs == Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between an Accuracy object and a floating point value.
+// \ingroup math
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is unequal to the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator!=( const Accuracy& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::accuracy() != rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a floating point value and an Accuracy object.
+// \ingroup math
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is unequal to the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator!=( const T& lhs, const Accuracy& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs != Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between an Accuracy object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floatin point value is greater than the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator<( const Accuracy& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::accuracy() < rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between a floating point value and an Accuracy object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is smaller than the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator<( const T& lhs, const Accuracy& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs < Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between an Accuracy object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is smaller than the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator>( const Accuracy& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::accuracy() > rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between a floating point value and an Accuracy object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is greater than the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator>( const T& lhs, const Accuracy& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs > Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between an Accuracy object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is greater than or equal to the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator<=( const Accuracy& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::accuracy() <= rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a floating point value and an Accuracy object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is smaller than or equal to the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator<=( const T& lhs, const Accuracy& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs <= Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between an Accuracy object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is smaller than or equal to the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator>=( const Accuracy& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::accuracy() >= rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a floating point value and an Accuracy object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is greater than or equal to the accuracy, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T > // Floating point data type
+inline bool operator>=( const T& lhs, const Accuracy& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs >= Limits<T>::accuracy();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL ACCURACY VALUE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Global Accuracy instance.
+// \ingroup math
+//
+// The blaze::accuracy instance can be used wherever a floating point data type is expected.
+// It is implicitly converted to the corresponding floating point data type and represents
+// the computation accuracy of the Blaze library for the according data type.
+*/
+const Accuracy accuracy;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Aliases.h b/src/cpu/blaze/math/Aliases.h
new file mode 100644
index 00000000..31a57b98
--- /dev/null
+++ b/src/cpu/blaze/math/Aliases.h
@@ -0,0 +1,428 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Aliases.h
+// \brief Header file for auxiliary alias declarations
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ALIASES_H_
+#define _BLAZE_MATH_ALIASES_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ALIAS DECLARATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c BaseType type definitions.
+// \ingroup aliases
+//
+// The BaseType_ alias declaration provides a convenient shortcut to access the nested
+// \a BaseType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::BaseType;
+ using Type2 = BaseType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using BaseType_ = typename T::BaseType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c CompositeType type definitions.
+// \ingroup aliases
+//
+// The CompositeType_ alias declaration provides a convenient shortcut to access the nested
+// \a CompositeType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::CompositeType;
+ using Type2 = CompositeType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using CompositeType_ = typename T::CompositeType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c ConstIterator type definitions.
+// \ingroup aliases
+//
+// The ConstIterator_ alias declaration provides a convenient shortcut to access the nested
+// \a ConstIterator type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::ConstIterator;
+ using Type2 = ConstIterator_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using ConstIterator_ = typename T::ConstIterator;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c ConstPointer type definitions.
+// \ingroup aliases
+//
+// The ConstPointer_ alias declaration provides a convenient shortcut to access the nested
+// \a ConstPointer type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::ConstPointer;
+ using Type2 = ConstPointer_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using ConstPointer_ = typename T::ConstPointer;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c ConstReference type definitions.
+// \ingroup aliases
+//
+// The ConstReference_ alias declaration provides a convenient shortcut to access the nested
+// \a ConstReference type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::ConstReference;
+ using Type2 = ConstReference_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using ConstReference_ = typename T::ConstReference;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c ElementType type definitions.
+// \ingroup aliases
+//
+// The ElementType_ alias declaration provides a convenient shortcut to access the nested
+// \a ElementType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::ElementType;
+ using Type2 = ElementType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using ElementType_ = typename T::ElementType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c Iterator type definitions.
+// \ingroup aliases
+//
+// The Iterator_ alias declaration provides a convenient shortcut to access the nested
+// \a Iterator type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::Iterator;
+ using Type2 = Iterator_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using Iterator_ = typename T::Iterator;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c LeftOperand type definitions.
+// \ingroup aliases
+//
+// The LeftOperand_ alias declaration provides a convenient shortcut to access the nested
+// \a LeftOperand type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::LeftOperand;
+ using Type2 = LeftOperand_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using LeftOperand_ = typename T::LeftOperand;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c Operand type definitions.
+// \ingroup aliases
+//
+// The Operand_ alias declaration provides a convenient shortcut to access the nested \a Operand
+// type definition of the given type \a T. The following code example shows both ways to access
+// the nested type definition:
+
+ \code
+ using Type1 = typename T::Operand;
+ using Type2 = Operand_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using Operand_ = typename T::Operand;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c OppositeType type definitions.
+// \ingroup aliases
+//
+// The OppositeType_ alias declaration provides a convenient shortcut to access the nested
+// \a OppositeType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::OppositeType;
+ using Type2 = OppositeType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using OppositeType_ = typename T::OppositeType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c Pointer type definitions.
+// \ingroup aliases
+//
+// The Pointer_ alias declaration provides a convenient shortcut to access the nested
+// \a Pointer type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::Pointer;
+ using Type2 = Pointer_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using Pointer_ = typename T::Pointer;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c Reference type definitions.
+// \ingroup aliases
+//
+// The Reference_ alias declaration provides a convenient shortcut to access the nested
+// \a Reference type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::Reference;
+ using Type2 = Reference_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using Reference_ = typename T::Reference;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c RepresentedType type definitions.
+// \ingroup aliases
+//
+// The RepresentedType_ alias declaration provides a convenient shortcut to access the nested
+// \a RepresentedType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::RepresentedType;
+ using Type2 = RepresentedType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using RepresentedType_ = typename T::RepresentedType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c ResultType type definitions.
+// \ingroup aliases
+//
+// The ResultType_ alias declaration provides a convenient shortcut to access the nested
+// \a ResultType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::ResultType;
+ using Type2 = ResultType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using ResultType_ = typename T::ResultType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c ReturnType type definitions.
+// \ingroup aliases
+//
+// The ReturnType_ alias declaration provides a convenient shortcut to access the nested
+// \a ReturnType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::ReturnType;
+ using Type2 = ReturnType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using ReturnType_ = typename T::ReturnType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c RightOperand type definitions.
+// \ingroup aliases
+//
+// The RightOperand_ alias declaration provides a convenient shortcut to access the nested
+// \a RightOperand type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::RightOperand;
+ using Type2 = RightOperand_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using RightOperand_ = typename T::RightOperand;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c SIMDType type definitions.
+// \ingroup aliases
+//
+// The SIMDType_ alias declaration provides a convenient shortcut to access the nested
+// \a SIMDType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::SIMDType;
+ using Type2 = SIMDType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using SIMDType_ = typename T::SIMDType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c TransposeType type definitions.
+// \ingroup aliases
+//
+// The TransposeType_ alias declaration provides a convenient shortcut to access the nested
+// \a TransposeType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::TransposeType;
+ using Type2 = TransposeType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using TransposeType_ = typename T::TransposeType;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alias declaration for nested \c ValueType type definitions.
+// \ingroup aliases
+//
+// The ValueType_ alias declaration provides a convenient shortcut to access the nested
+// \a ValueType type definition of the given type \a T. The following code example shows
+// both ways to access the nested type definition:
+
+ \code
+ using Type1 = typename T::ValueType;
+ using Type2 = ValueType_<T>;
+
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( Type1, Type2 );
+ \endcode
+*/
+template< typename T >
+using ValueType_ = typename T::ValueType;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/AlignmentFlag.h b/src/cpu/blaze/math/AlignmentFlag.h
new file mode 100644
index 00000000..92c9a147
--- /dev/null
+++ b/src/cpu/blaze/math/AlignmentFlag.h
@@ -0,0 +1,90 @@
+//=================================================================================================
+/*!
+// \file blaze/math/AlignmentFlag.h
+// \brief Header file for the alignment flag values
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ALIGNMENTFLAG_H_
+#define _BLAZE_MATH_ALIGNMENTFLAG_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ALIGNMENT FLAG VALUES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Alignment flag for unaligned vectors and matrices.
+// \ingroup math
+//
+// Via this flag it is possible to specify subvectors, submatrices, custom vectors and matrices
+// as unaligned. The following example demonstrates the setup of an unaligned subvector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::unaligned;
+
+ typedef blaze::DynamicVector<int,columnVector> VectorType;
+
+ VectorType v( 100UL );
+ Subvector<VectorType,unaligned> sv = subvector<unaligned>( v, 10UL, 20UL );
+ \endcode
+*/
+const bool unaligned = false;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Alignment flag for aligned vectors and matrices.
+// \ingroup math
+//
+// Via this flag it is possible to specify subvectors, submatrices, custom vectors and matrices
+// as aligned. The following example demonstrates the setup of an aligned subvector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::aligned;
+
+ typedef blaze::DynamicVector<int,columnVector> VectorType;
+
+ VectorType v( 100UL );
+ Subvector<VectorType,aligned> sv = subvector<aligned>( v, 8UL, 32UL );
+ \endcode
+*/
+const bool aligned = true;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/BLAS.h b/src/cpu/blaze/math/BLAS.h
new file mode 100644
index 00000000..b5440de4
--- /dev/null
+++ b/src/cpu/blaze/math/BLAS.h
@@ -0,0 +1,50 @@
+//=================================================================================================
+/*!
+// \file blaze/math/BLAS.h
+// \brief Header file for BLAS functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_BLAS_H_
+#define _BLAZE_MATH_BLAS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/dot.h>
+#include <blaze/math/blas/gemm.h>
+#include <blaze/math/blas/gemv.h>
+#include <blaze/math/blas/trmm.h>
+#include <blaze/math/blas/trmv.h>
+#include <blaze/math/blas/trsm.h>
+
+#endif
diff --git a/src/cpu/blaze/math/Column.h b/src/cpu/blaze/math/Column.h
new file mode 100644
index 00000000..4ee18687
--- /dev/null
+++ b/src/cpu/blaze/math/Column.h
@@ -0,0 +1,315 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Column.h
+// \brief Header file for the complete Column implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_COLUMN_H_
+#define _BLAZE_MATH_COLUMN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/smp/DenseVector.h>
+#include <blaze/math/smp/SparseVector.h>
+#include <blaze/math/views/Column.h>
+#include <blaze/math/views/Row.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION FOR DENSE COLUMNS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for dense columns.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes dense columns.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+class Rand< Column<MT,SO,true,SF> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( Column<MT,SO,true,SF>& column ) const;
+
+ template< typename Arg >
+ inline void randomize( Column<MT,SO,true,SF>& column, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense column.
+//
+// \param column The column to be randomized.
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+inline void Rand< Column<MT,SO,true,SF> >::randomize( Column<MT,SO,true,SF>& column ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<column.size(); ++i ) {
+ randomize( column[i] );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense column.
+//
+// \param column The column to be randomized.
+// \param min The smallest possible value for a column element.
+// \param max The largest possible value for a column element.
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Column<MT,SO,true,SF> >::randomize( Column<MT,SO,true,SF>& column,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<column.size(); ++i ) {
+ randomize( column[i], min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION FOR SPARSE COLUMNS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for sparse columns.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes sparse columns.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+class Rand< Column<MT,SO,false,SF> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( Column<MT,SO,false,SF>& column ) const;
+ inline void randomize( Column<MT,SO,false,SF>& column, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( Column<MT,SO,false,SF>& column, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( Column<MT,SO,false,SF>& column, size_t nonzeros, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse column.
+//
+// \param column The column to be randomized.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+inline void Rand< Column<MT,SO,false,SF> >::randomize( Column<MT,SO,false,SF>& column ) const
+{
+ typedef ElementType_< Column<MT,SO,false,SF> > ElementType;
+
+ const size_t size( column.size() );
+
+ if( size == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*size ) ) );
+
+ column.reset();
+ column.reserve( nonzeros );
+
+ while( column.nonZeros() < nonzeros ) {
+ column[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse column.
+//
+// \param column The column to be randomized.
+// \param nonzeros The number of non-zero elements of the random column.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+inline void Rand< Column<MT,SO,false,SF> >::randomize( Column<MT,SO,false,SF>& column, size_t nonzeros ) const
+{
+ typedef ElementType_< Column<MT,SO,false,SF> > ElementType;
+
+ const size_t size( column.size() );
+
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( size == 0UL ) return;
+
+ column.reset();
+ column.reserve( nonzeros );
+
+ while( column.nonZeros() < nonzeros ) {
+ column[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse column.
+//
+// \param column The column to be randomized.
+// \param min The smallest possible value for a column element.
+// \param max The largest possible value for a column element.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Column<MT,SO,false,SF> >::randomize( Column<MT,SO,false,SF>& column,
+ const Arg& min, const Arg& max ) const
+{
+ typedef ElementType_< Column<MT,SO,false,SF> > ElementType;
+
+ const size_t size( column.size() );
+
+ if( size == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*size ) ) );
+
+ column.reset();
+ column.reserve( nonzeros );
+
+ while( column.nonZeros() < nonzeros ) {
+ column[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse column.
+//
+// \param column The column to be randomized.
+// \param nonzeros The number of non-zero elements of the random column.
+// \param min The smallest possible value for a column element.
+// \param max The largest possible value for a column element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Column<MT,SO,false,SF> >::randomize( Column<MT,SO,false,SF>& column, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ typedef ElementType_< Column<MT,SO,false,SF> > ElementType;
+
+ const size_t size( column.size() );
+
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( size == 0UL ) return;
+
+ column.reset();
+ column.reserve( nonzeros );
+
+ while( column.nonZeros() < nonzeros ) {
+ column[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/CompressedMatrix.h b/src/cpu/blaze/math/CompressedMatrix.h
new file mode 100644
index 00000000..664be067
--- /dev/null
+++ b/src/cpu/blaze/math/CompressedMatrix.h
@@ -0,0 +1,465 @@
+//=================================================================================================
+/*!
+// \file blaze/math/CompressedMatrix.h
+// \brief Header file for the complete CompressedMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_COMPRESSEDMATRIX_H_
+#define _BLAZE_MATH_COMPRESSEDMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <vector>
+#include <blaze/math/sparse/CompressedMatrix.h>
+#include <blaze/math/CompressedVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/system/Precision.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for CompressedMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of CompressedMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+class Rand< CompressedMatrix<Type,SO> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const CompressedMatrix<Type,SO> generate( size_t m, size_t n ) const;
+ inline const CompressedMatrix<Type,SO> generate( size_t m, size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const CompressedMatrix<Type,SO> generate( size_t m, size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const CompressedMatrix<Type,SO> generate( size_t m, size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( CompressedMatrix<Type,SO>& matrix ) const;
+ inline void randomize( CompressedMatrix<Type,false>& matrix, size_t nonzeros ) const;
+ inline void randomize( CompressedMatrix<Type,true>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( CompressedMatrix<Type,SO>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( CompressedMatrix<Type,false>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ template< typename Arg >
+ inline void randomize( CompressedMatrix<Type,true>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random CompressedMatrix.
+//
+// \param m The number of rows of the random matrix.
+// \param n The number of columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline const CompressedMatrix<Type,SO>
+ Rand< CompressedMatrix<Type,SO> >::generate( size_t m, size_t n ) const
+{
+ CompressedMatrix<Type,SO> matrix( m, n );
+ randomize( matrix );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random CompressedMatrix.
+//
+// \param m The number of rows of the random matrix.
+// \param n The number of columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline const CompressedMatrix<Type,SO>
+ Rand< CompressedMatrix<Type,SO> >::generate( size_t m, size_t n, size_t nonzeros ) const
+{
+ if( nonzeros > m*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ CompressedMatrix<Type,SO> matrix( m, n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random CompressedMatrix.
+//
+// \param m The number of rows of the random matrix.
+// \param n The number of columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \return The generated random matrix.
+// \param max The largest possible value for a matrix element.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline const CompressedMatrix<Type,SO>
+ Rand< CompressedMatrix<Type,SO> >::generate( size_t m, size_t n, const Arg& min, const Arg& max ) const
+{
+ CompressedMatrix<Type,SO> matrix( m, n );
+ randomize( matrix, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random CompressedMatrix.
+//
+// \param m The number of rows of the random matrix.
+// \param n The number of columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline const CompressedMatrix<Type,SO>
+ Rand< CompressedMatrix<Type,SO> >::generate( size_t m, size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ if( nonzeros > m*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ CompressedMatrix<Type,SO> matrix( m, n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CompressedMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void Rand< CompressedMatrix<Type,SO> >::randomize( CompressedMatrix<Type,SO>& matrix ) const
+{
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ if( m == 0UL || n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*m*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major CompressedMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void Rand< CompressedMatrix<Type,SO> >::randomize( CompressedMatrix<Type,false>& matrix, size_t nonzeros ) const
+{
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ if( nonzeros > m*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( m == 0UL || n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( m );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, m-1UL );
+ if( dist[index] == n ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<m; ++i ) {
+ const Indices indices( 0UL, n-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<Type>() );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major CompressedMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void Rand< CompressedMatrix<Type,SO> >::randomize( CompressedMatrix<Type,true>& matrix, size_t nonzeros ) const
+{
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ if( nonzeros > m*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( m == 0UL || n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == m ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ const Indices indices( 0UL, m-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<Type>() );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CompressedMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< CompressedMatrix<Type,SO> >::randomize( CompressedMatrix<Type,SO>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ if( m == 0UL || n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*m*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major CompressedMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< CompressedMatrix<Type,SO> >::randomize( CompressedMatrix<Type,false>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ if( nonzeros > m*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( m == 0UL || n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( m );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, m-1UL );
+ if( dist[index] == n ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<m; ++i ) {
+ const Indices indices( 0UL, n-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<Type>( min, max ) );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major CompressedMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< CompressedMatrix<Type,SO> >::randomize( CompressedMatrix<Type,true>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ if( nonzeros > m*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( m == 0UL || n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == m ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ const Indices indices( 0UL, m-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<Type>( min, max ) );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/CompressedVector.h b/src/cpu/blaze/math/CompressedVector.h
new file mode 100644
index 00000000..d929412b
--- /dev/null
+++ b/src/cpu/blaze/math/CompressedVector.h
@@ -0,0 +1,330 @@
+//=================================================================================================
+/*!
+// \file blaze/math/CompressedVector.h
+// \brief Header file for the complete CompressedVector implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_COMPRESSEDVECTOR_H_
+#define _BLAZE_MATH_COMPRESSEDVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/StaticVector.h>
+#include <blaze/math/CompressedMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/sparse/CompressedVector.h>
+#include <blaze/math/SparseVector.h>
+#include <blaze/system/Precision.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for CompressedVector.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of CompressedVector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+class Rand< CompressedVector<Type,TF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const CompressedVector<Type,TF> generate( size_t size ) const;
+ inline const CompressedVector<Type,TF> generate( size_t size, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const CompressedVector<Type,TF> generate( size_t size, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const CompressedVector<Type,TF> generate( size_t size, size_t nonzeros, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( CompressedVector<Type,TF>& vector ) const;
+ inline void randomize( CompressedVector<Type,TF>& vector, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( CompressedVector<Type,TF>& vector, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( CompressedVector<Type,TF>& vector, size_t nonzeros, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random CompressedVector.
+//
+// \param size The size of the random vector.
+// \return The generated random vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline const CompressedVector<Type,TF>
+ Rand< CompressedVector<Type,TF> >::generate( size_t size ) const
+{
+ CompressedVector<Type,TF> vector( size );
+ randomize( vector );
+
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random CompressedVector.
+//
+// \param size The size of the random vector.
+// \param nonzeros The number of non-zero elements of the random vector.
+// \return The generated random vector.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline const CompressedVector<Type,TF>
+ Rand< CompressedVector<Type,TF> >::generate( size_t size, size_t nonzeros ) const
+{
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ CompressedVector<Type,TF> vector( size, nonzeros );
+ randomize( vector, nonzeros );
+
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random CompressedVector.
+//
+// \param size The size of the random vector.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return The generated random vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline const CompressedVector<Type,TF>
+ Rand< CompressedVector<Type,TF> >::generate( size_t size, const Arg& min, const Arg& max ) const
+{
+ CompressedVector<Type,TF> vector( size );
+ randomize( vector, min, max );
+
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random CompressedVector.
+//
+// \param size The size of the random vector.
+// \param nonzeros The number of non-zero elements of the random vector.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return The generated random vector.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline const CompressedVector<Type,TF>
+ Rand< CompressedVector<Type,TF> >::generate( size_t size, size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ CompressedVector<Type,TF> vector( size, nonzeros );
+ randomize( vector, nonzeros, min, max );
+
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CompressedVector.
+//
+// \param vector The vector to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void Rand< CompressedVector<Type,TF> >::randomize( CompressedVector<Type,TF>& vector ) const
+{
+ const size_t size( vector.size() );
+
+ if( size == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*size ) ) );
+
+ randomize( vector, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CompressedVector.
+//
+// \param vector The vector to be randomized.
+// \param nonzeros The number of non-zero elements of the random vector.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void Rand< CompressedVector<Type,TF> >::randomize( CompressedVector<Type,TF>& vector, size_t nonzeros ) const
+{
+ const size_t size( vector.size() );
+
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( size == 0UL ) return;
+
+ vector.reset();
+ vector.reserve( nonzeros );
+
+ const Indices indices( 0UL, vector.size()-1UL, nonzeros );
+
+ for( size_t index : indices ) {
+ vector.append( index, rand<Type>() );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CompressedVector.
+//
+// \param vector The vector to be randomized.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< CompressedVector<Type,TF> >::randomize( CompressedVector<Type,TF>& vector,
+ const Arg& min, const Arg& max ) const
+{
+ const size_t size( vector.size() );
+
+ if( size == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*size ) ) );
+
+ randomize( vector, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CompressedVector.
+//
+// \param vector The vector to be randomized.
+// \param nonzeros The number of non-zero elements of the random vector.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< CompressedVector<Type,TF> >::randomize( CompressedVector<Type,TF>& vector,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ const size_t size( vector.size() );
+
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( size == 0UL ) return;
+
+ vector.reset();
+ vector.reserve( nonzeros );
+
+ const Indices indices( 0UL, vector.size()-1UL, nonzeros );
+
+ for( size_t index : indices ) {
+ vector.append( index, rand<Type>( min, max ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Constants.h b/src/cpu/blaze/math/Constants.h
new file mode 100644
index 00000000..8bf40c04
--- /dev/null
+++ b/src/cpu/blaze/math/Constants.h
@@ -0,0 +1,208 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Constants.h
+// \brief Header file for mathematical constants
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTANTS_H_
+#define _BLAZE_MATH_CONSTANTS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/system/Precision.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MATHEMATICAL CONSTANT E
+//
+//=================================================================================================
+
+#ifdef M_E
+# undef M_E
+#endif
+
+//*************************************************************************************************
+/*!\brief Definition of the mathematical constant \f$ e \f$.
+// \ingroup math
+*/
+const real_t M_E = 2.7182818284590452353602874713526625;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHEMATICAL CONSTANT LOG2E
+//
+//=================================================================================================
+
+#ifdef M_LOG2E
+# undef M_LOG2E
+#endif
+
+//*************************************************************************************************
+/*!\brief Definition of the mathematical constant \f$ \log_2 e \f$.
+// \ingroup math
+*/
+const real_t M_LOG2E = 1.4426950408889634073599246810018921;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHEMATICAL CONSTANT LOG10E
+//
+//=================================================================================================
+
+#ifdef M_LOG10E
+# undef M_LOG10E
+#endif
+
+//*************************************************************************************************
+/*!\brief Definition of the mathematical constant \f$ \log_{10} e \f$.
+// \ingroup math
+*/
+const real_t M_LOG10E = 0.4342944819032518276511289189166051;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHEMATICAL CONSTANT LN2
+//
+//=================================================================================================
+
+#ifdef M_LN2
+# undef M_LN2
+#endif
+
+//*************************************************************************************************
+/*!\brief Definition of the mathematical constant \f$ \ln 2 \f$.
+// \ingroup math
+*/
+const real_t M_LN2 = 0.6931471805599453094172321214581766;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHEMATICAL CONSTANT LN10
+//
+//=================================================================================================
+
+#ifdef M_LN10
+# undef M_LN10
+#endif
+
+//*************************************************************************************************
+/*!\brief Definition of the mathematical constant \f$ \ln 10 \f$.
+// \ingroup math
+*/
+const real_t M_LN10 = 2.3025850929940456840179914546843642;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHEMATICAL CONSTANT PI
+//
+//=================================================================================================
+
+#ifdef M_PI
+# undef M_PI
+#endif
+
+//*************************************************************************************************
+/*!\brief Definition of the mathematical constant \f$ \pi \f$.
+// \ingroup math
+*/
+const real_t M_PI = 3.1415926535897932384626433832795029;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHEMATICAL CONSTANT SQRT2
+//
+//=================================================================================================
+
+#ifdef M_SQRT2
+# undef M_SQRT2
+#endif
+
+//*************************************************************************************************
+/*!\brief Definition of the mathematical constant \f$ \sqrt{2} \f$.
+// \ingroup math
+*/
+const real_t M_SQRT2 = 1.4142135623730950488016887242096981;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHEMATICAL CONSTANT SQRT3
+//
+//=================================================================================================
+
+#ifdef M_SQRT3
+# undef M_SQRT3
+#endif
+
+//*************************************************************************************************
+/*!\brief Definition of the mathematical constant \f$ \sqrt{3} \f$.
+// \ingroup math
+*/
+const real_t M_SQRT3 = 1.7320508075688772935274463415058724;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Constraints.h b/src/cpu/blaze/math/Constraints.h
new file mode 100644
index 00000000..a767ea9a
--- /dev/null
+++ b/src/cpu/blaze/math/Constraints.h
@@ -0,0 +1,132 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Constraints.h
+// \brief Header file for all mathematical constraints
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_H_
+#define _BLAZE_MATH_CONSTRAINTS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/AddExpr.h>
+#include <blaze/math/constraints/Aligned.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Column.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/Columns.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/ConstDataAccess.h>
+#include <blaze/math/constraints/CrossExpr.h>
+#include <blaze/math/constraints/Custom.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/Diagonal.h>
+#include <blaze/math/constraints/DivExpr.h>
+#include <blaze/math/constraints/EvalExpr.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/ForEachExpr.h>
+#include <blaze/math/constraints/General.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Identity.h>
+#include <blaze/math/constraints/Invertible.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/MatEvalExpr.h>
+#include <blaze/math/constraints/MatForEachExpr.h>
+#include <blaze/math/constraints/MatInvExpr.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/MatScalarDivExpr.h>
+#include <blaze/math/constraints/MatScalarMultExpr.h>
+#include <blaze/math/constraints/MatSerialExpr.h>
+#include <blaze/math/constraints/MatTransExpr.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/constraints/MultExpr.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/constraints/NumericMatrix.h>
+#include <blaze/math/constraints/NumericVector.h>
+#include <blaze/math/constraints/OpposedView.h>
+#include <blaze/math/constraints/Padded.h>
+#include <blaze/math/constraints/Proxy.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/Restricted.h>
+#include <blaze/math/constraints/Row.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/Rows.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SerialExpr.h>
+#include <blaze/math/constraints/SIMDEnabled.h>
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/constraints/Size.h>
+#include <blaze/math/constraints/SMPAssignable.h>
+#include <blaze/math/constraints/SparseElement.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Square.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/StrictlyLower.h>
+#include <blaze/math/constraints/StrictlyTriangular.h>
+#include <blaze/math/constraints/StrictlyUpper.h>
+#include <blaze/math/constraints/SubExpr.h>
+#include <blaze/math/constraints/Submatrix.h>
+#include <blaze/math/constraints/Subvector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/Triangular.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/constraints/UniLower.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/UniUpper.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/constraints/VecEvalExpr.h>
+#include <blaze/math/constraints/VecForEachExpr.h>
+#include <blaze/math/constraints/VecScalarDivExpr.h>
+#include <blaze/math/constraints/VecScalarMultExpr.h>
+#include <blaze/math/constraints/VecSerialExpr.h>
+#include <blaze/math/constraints/Vector.h>
+#include <blaze/math/constraints/VecTransExpr.h>
+#include <blaze/math/constraints/VecTVecMultExpr.h>
+#include <blaze/math/constraints/VecVecAddExpr.h>
+#include <blaze/math/constraints/VecVecDivExpr.h>
+#include <blaze/math/constraints/VecVecMultExpr.h>
+#include <blaze/math/constraints/VecVecSubExpr.h>
+#include <blaze/math/constraints/View.h>
+
+#endif
diff --git a/src/cpu/blaze/math/CustomMatrix.h b/src/cpu/blaze/math/CustomMatrix.h
new file mode 100644
index 00000000..4a3e028d
--- /dev/null
+++ b/src/cpu/blaze/math/CustomMatrix.h
@@ -0,0 +1,356 @@
+//=================================================================================================
+/*!
+// \file blaze/math/CustomMatrix.h
+// \brief Header file for the complete CustomMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CUSTOMMATRIX_H_
+#define _BLAZE_MATH_CUSTOMMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/CustomMatrix.h>
+#include <blaze/math/dense/DynamicMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/DynamicVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Real.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for CustomMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of CustomMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+class Rand< CustomMatrix<Type,AF,PF,SO> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( CustomMatrix<Type,AF,PF,SO>& matrix ) const;
+
+ template< typename Arg >
+ inline void randomize( CustomMatrix<Type,AF,PF,SO>& matrix, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CustomMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void Rand< CustomMatrix<Type,AF,PF,SO> >::randomize( CustomMatrix<Type,AF,PF,SO>& matrix ) const
+{
+ using blaze::randomize;
+
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j ) {
+ randomize( matrix(i,j) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CustomMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< CustomMatrix<Type,AF,PF,SO> >::randomize( CustomMatrix<Type,AF,PF,SO>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j ) {
+ randomize( matrix(i,j), min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric CustomMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+void makeSymmetric( CustomMatrix<Type,AF,PF,SO>& matrix )
+{
+ using blaze::randomize;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j) );
+ matrix(j,i) = matrix(i,j);
+ }
+ randomize( matrix(i,i) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric CustomMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO // Storage order
+ , typename Arg > // Min/max argument type
+void makeSymmetric( CustomMatrix<Type,AF,PF,SO>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j), min, max );
+ matrix(j,i) = matrix(i,j);
+ }
+ randomize( matrix(i,i), min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian CustomMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+void makeHermitian( CustomMatrix<Type,AF,PF,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ typedef UnderlyingBuiltin_<Type> BT;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j) );
+ matrix(j,i) = conj( matrix(i,j) );
+ }
+ matrix(i,i) = rand<BT>();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian CustomMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO // Storage order
+ , typename Arg > // Min/max argument type
+void makeHermitian( CustomMatrix<Type,AF,PF,SO>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ typedef UnderlyingBuiltin_<Type> BT;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j), min, max );
+ matrix(j,i) = conj( matrix(i,j) );
+ }
+ matrix(i,i) = rand<BT>( real( min ), real( max ) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite CustomMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+void makePositiveDefinite( CustomMatrix<Type,AF,PF,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ randomize( matrix );
+ matrix *= ctrans( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) += Type(n);
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/CustomVector.h b/src/cpu/blaze/math/CustomVector.h
new file mode 100644
index 00000000..57443758
--- /dev/null
+++ b/src/cpu/blaze/math/CustomVector.h
@@ -0,0 +1,140 @@
+//=================================================================================================
+/*!
+// \file blaze/math/CustomVector.h
+// \brief Header file for the complete CustomVector implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CUSTOMVECTOR_H_
+#define _BLAZE_MATH_CUSTOMVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/CustomVector.h>
+#include <blaze/math/dense/DynamicVector.h>
+#include <blaze/math/dense/StaticVector.h>
+#include <blaze/math/DenseVector.h>
+#include <blaze/math/DynamicMatrix.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for CustomVector.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes instances of CustomVector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+class Rand< CustomVector<Type,AF,PF,TF> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( CustomVector<Type,AF,PF,TF>& vector ) const;
+
+ template< typename Arg >
+ inline void randomize( CustomVector<Type,AF,PF,TF>& vector, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CustomVector.
+//
+// \param vector The vector to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void Rand< CustomVector<Type,AF,PF,TF> >::randomize( CustomVector<Type,AF,PF,TF>& vector ) const
+{
+ using blaze::randomize;
+
+ const size_t size( vector.size() );
+ for( size_t i=0UL; i<size; ++i ) {
+ randomize( vector[i] );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a CustomVector.
+//
+// \param vector The vector to be randomized.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< CustomVector<Type,AF,PF,TF> >::randomize( CustomVector<Type,AF,PF,TF>& vector,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ const size_t size( vector.size() );
+ for( size_t i=0UL; i<size; ++i ) {
+ randomize( vector[i], min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/DenseMatrix.h b/src/cpu/blaze/math/DenseMatrix.h
new file mode 100644
index 00000000..5cc08c78
--- /dev/null
+++ b/src/cpu/blaze/math/DenseMatrix.h
@@ -0,0 +1,103 @@
+//=================================================================================================
+/*!
+// \file blaze/math/DenseMatrix.h
+// \brief Header file for all basic DenseMatrix functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSEMATRIX_H_
+#define _BLAZE_MATH_DENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/dense/Inversion.h>
+#include <blaze/math/dense/LLH.h>
+#include <blaze/math/dense/LQ.h>
+#include <blaze/math/dense/LU.h>
+#include <blaze/math/dense/QL.h>
+#include <blaze/math/dense/QR.h>
+#include <blaze/math/dense/RQ.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DMatDetExpr.h>
+#include <blaze/math/expressions/DMatDMatAddExpr.h>
+#include <blaze/math/expressions/DMatDMatMultExpr.h>
+#include <blaze/math/expressions/DMatDMatSubExpr.h>
+#include <blaze/math/expressions/DMatDVecMultExpr.h>
+#include <blaze/math/expressions/DMatEvalExpr.h>
+#include <blaze/math/expressions/DMatForEachExpr.h>
+#include <blaze/math/expressions/DMatInvExpr.h>
+#include <blaze/math/expressions/DMatScalarDivExpr.h>
+#include <blaze/math/expressions/DMatScalarMultExpr.h>
+#include <blaze/math/expressions/DMatSerialExpr.h>
+#include <blaze/math/expressions/DMatSMatAddExpr.h>
+#include <blaze/math/expressions/DMatSMatMultExpr.h>
+#include <blaze/math/expressions/DMatSMatSubExpr.h>
+#include <blaze/math/expressions/DMatSVecMultExpr.h>
+#include <blaze/math/expressions/DMatTDMatAddExpr.h>
+#include <blaze/math/expressions/DMatTDMatMultExpr.h>
+#include <blaze/math/expressions/DMatTDMatSubExpr.h>
+#include <blaze/math/expressions/DMatTransExpr.h>
+#include <blaze/math/expressions/DMatTransposer.h>
+#include <blaze/math/expressions/DMatTSMatAddExpr.h>
+#include <blaze/math/expressions/DMatTSMatMultExpr.h>
+#include <blaze/math/expressions/DMatTSMatSubExpr.h>
+#include <blaze/math/expressions/DVecTDVecMultExpr.h>
+#include <blaze/math/expressions/SMatDMatMultExpr.h>
+#include <blaze/math/expressions/SMatDMatSubExpr.h>
+#include <blaze/math/expressions/SMatTDMatMultExpr.h>
+#include <blaze/math/expressions/SMatTDMatSubExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/TDMatDMatMultExpr.h>
+#include <blaze/math/expressions/TDMatDVecMultExpr.h>
+#include <blaze/math/expressions/TDMatSMatAddExpr.h>
+#include <blaze/math/expressions/TDMatSMatMultExpr.h>
+#include <blaze/math/expressions/TDMatSMatSubExpr.h>
+#include <blaze/math/expressions/TDMatSVecMultExpr.h>
+#include <blaze/math/expressions/TDMatTDMatMultExpr.h>
+#include <blaze/math/expressions/TDMatTSMatMultExpr.h>
+#include <blaze/math/expressions/TDVecDMatMultExpr.h>
+#include <blaze/math/expressions/TDVecTDMatMultExpr.h>
+#include <blaze/math/expressions/TSMatDMatMultExpr.h>
+#include <blaze/math/expressions/TSMatDMatSubExpr.h>
+#include <blaze/math/expressions/TSMatTDMatMultExpr.h>
+#include <blaze/math/expressions/TSVecDMatMultExpr.h>
+#include <blaze/math/expressions/TSVecTDMatMultExpr.h>
+#include <blaze/math/Matrix.h>
+#include <blaze/math/smp/DenseMatrix.h>
+#include <blaze/math/smp/SparseMatrix.h>
+#include <blaze/math/views/Column.h>
+#include <blaze/math/views/Row.h>
+#include <blaze/math/views/Submatrix.h>
+
+#endif
diff --git a/src/cpu/blaze/math/DenseVector.h b/src/cpu/blaze/math/DenseVector.h
new file mode 100644
index 00000000..8bbae1f7
--- /dev/null
+++ b/src/cpu/blaze/math/DenseVector.h
@@ -0,0 +1,69 @@
+//=================================================================================================
+/*!
+// \file blaze/math/DenseVector.h
+// \brief Header file for all basic DenseVector functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSEVECTOR_H_
+#define _BLAZE_MATH_DENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/DenseVector.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/DVecDVecAddExpr.h>
+#include <blaze/math/expressions/DVecDVecDivExpr.h>
+#include <blaze/math/expressions/DVecDVecCrossExpr.h>
+#include <blaze/math/expressions/DVecDVecMultExpr.h>
+#include <blaze/math/expressions/DVecDVecSubExpr.h>
+#include <blaze/math/expressions/DVecEvalExpr.h>
+#include <blaze/math/expressions/DVecForEachExpr.h>
+#include <blaze/math/expressions/DVecScalarDivExpr.h>
+#include <blaze/math/expressions/DVecScalarMultExpr.h>
+#include <blaze/math/expressions/DVecSerialExpr.h>
+#include <blaze/math/expressions/DVecSVecAddExpr.h>
+#include <blaze/math/expressions/DVecSVecCrossExpr.h>
+#include <blaze/math/expressions/DVecSVecSubExpr.h>
+#include <blaze/math/expressions/DVecTransExpr.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/SVecDVecCrossExpr.h>
+#include <blaze/math/expressions/SVecDVecSubExpr.h>
+#include <blaze/math/expressions/SVecSVecCrossExpr.h>
+#include <blaze/math/expressions/TDVecDVecMultExpr.h>
+#include <blaze/math/smp/DenseVector.h>
+#include <blaze/math/smp/SparseVector.h>
+#include <blaze/math/Vector.h>
+#include <blaze/math/views/Subvector.h>
+
+#endif
diff --git a/src/cpu/blaze/math/DiagonalMatrix.h b/src/cpu/blaze/math/DiagonalMatrix.h
new file mode 100644
index 00000000..c90b22dd
--- /dev/null
+++ b/src/cpu/blaze/math/DiagonalMatrix.h
@@ -0,0 +1,685 @@
+//=================================================================================================
+/*!
+// \file blaze/math/DiagonalMatrix.h
+// \brief Header file for the complete DiagonalMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DIAGONALMATRIX_H_
+#define _BLAZE_MATH_DIAGONALMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/adaptors/DiagonalMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for DiagonalMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of DiagonalMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+class Rand< DiagonalMatrix<MT,SO,DF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const DiagonalMatrix<MT,SO,DF> generate() const;
+ inline const DiagonalMatrix<MT,SO,DF> generate( size_t n ) const;
+ inline const DiagonalMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const DiagonalMatrix<MT,SO,DF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const DiagonalMatrix<MT,SO,DF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const DiagonalMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( DiagonalMatrix<MT,SO,DF>& matrix ) const;
+ inline void randomize( DiagonalMatrix<MT,SO,DF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( DiagonalMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( DiagonalMatrix<MT,SO,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( DiagonalMatrix<MT,SO,DF>& matrix, TrueType ) const;
+ inline void randomize( DiagonalMatrix<MT,SO,DF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( DiagonalMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( DiagonalMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DiagonalMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const DiagonalMatrix<MT,SO,DF> Rand< DiagonalMatrix<MT,SO,DF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ DiagonalMatrix<MT,SO,DF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DiagonalMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const DiagonalMatrix<MT,SO,DF>
+ Rand< DiagonalMatrix<MT,SO,DF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ DiagonalMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DiagonalMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const DiagonalMatrix<MT,SO,DF>
+ Rand< DiagonalMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ DiagonalMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DiagonalMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const DiagonalMatrix<MT,SO,DF>
+ Rand< DiagonalMatrix<MT,SO,DF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ DiagonalMatrix<MT,SO,DF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DiagonalMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const DiagonalMatrix<MT,SO,DF>
+ Rand< DiagonalMatrix<MT,SO,DF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ DiagonalMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DiagonalMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const DiagonalMatrix<MT,SO,DF>
+ Rand< DiagonalMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > DiagonalMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ DiagonalMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< DiagonalMatrix<MT,SO,DF> >::randomize( DiagonalMatrix<MT,SO,DF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< DiagonalMatrix<MT,SO,DF> >::randomize( DiagonalMatrix<MT,SO,DF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<ET>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< DiagonalMatrix<MT,SO,DF> >::randomize( DiagonalMatrix<MT,SO,DF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, n ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< DiagonalMatrix<MT,SO,DF> >::randomize( DiagonalMatrix<MT,SO,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ Indices indices( 0UL, n-1UL, nonzeros );
+ size_t i( 0UL );
+
+ for( size_t index : indices ) {
+ for( ; i<index; ++i )
+ matrix.finalize( i );
+ matrix.append( i, i, rand<ET>() );
+ }
+
+ for( ; i<n; ++i ) {
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< DiagonalMatrix<MT,SO,DF> >::randomize( DiagonalMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< DiagonalMatrix<MT,SO,DF> >::randomize( DiagonalMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<ET>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< DiagonalMatrix<MT,SO,DF> >::randomize( DiagonalMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, n ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< DiagonalMatrix<MT,SO,DF> >::randomize( DiagonalMatrix<MT,SO,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ Indices indices( 0UL, n-1UL, nonzeros );
+ size_t i( 0UL );
+
+ for( size_t index : indices ) {
+ for( ; i<index; ++i )
+ matrix.finalize( i );
+ matrix.append( i, i, rand<ET>( min, max ) );
+ }
+
+ for( ; i<n; ++i ) {
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeSymmetric( DiagonalMatrix<MT,SO,DF>& matrix )
+{
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand< ElementType_<MT> >();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeSymmetric( DiagonalMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ typedef ElementType_<MT> Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>( min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeHermitian( DiagonalMatrix<MT,SO,DF>& matrix )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeHermitian( DiagonalMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>( min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite DiagonalMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makePositiveDefinite( DiagonalMatrix<MT,SO,DF>& matrix )
+{
+ makeHermitian( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/DynamicMatrix.h b/src/cpu/blaze/math/DynamicMatrix.h
new file mode 100644
index 00000000..4ca3e4aa
--- /dev/null
+++ b/src/cpu/blaze/math/DynamicMatrix.h
@@ -0,0 +1,395 @@
+//=================================================================================================
+/*!
+// \file blaze/math/DynamicMatrix.h
+// \brief Header file for the complete DynamicMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DYNAMICMATRIX_H_
+#define _BLAZE_MATH_DYNAMICMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/DynamicMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/DynamicVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Real.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/system/Precision.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for DynamicMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of DynamicMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+class Rand< DynamicMatrix<Type,SO> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const DynamicMatrix<Type,SO> generate( size_t m, size_t n ) const;
+
+ template< typename Arg >
+ inline const DynamicMatrix<Type,SO> generate( size_t m, size_t n, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( DynamicMatrix<Type,SO>& matrix ) const;
+
+ template< typename Arg >
+ inline void randomize( DynamicMatrix<Type,SO>& matrix, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DynamicMatrix.
+//
+// \param m The number of rows of the random matrix.
+// \param n The number of columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline const DynamicMatrix<Type,SO>
+ Rand< DynamicMatrix<Type,SO> >::generate( size_t m, size_t n ) const
+{
+ DynamicMatrix<Type,SO> matrix( m, n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DynamicMatrix.
+//
+// \param m The number of rows of the random matrix.
+// \param n The number of columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline const DynamicMatrix<Type,SO>
+ Rand< DynamicMatrix<Type,SO> >::generate( size_t m, size_t n, const Arg& min, const Arg& max ) const
+{
+ DynamicMatrix<Type,SO> matrix( m, n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a DynamicMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void Rand< DynamicMatrix<Type,SO> >::randomize( DynamicMatrix<Type,SO>& matrix ) const
+{
+ using blaze::randomize;
+
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j ) {
+ randomize( matrix(i,j) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a DynamicMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< DynamicMatrix<Type,SO> >::randomize( DynamicMatrix<Type,SO>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j ) {
+ randomize( matrix(i,j), min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric DynamicMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+void makeSymmetric( DynamicMatrix<Type,SO>& matrix )
+{
+ using blaze::randomize;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j) );
+ matrix(j,i) = matrix(i,j);
+ }
+ randomize( matrix(i,i) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric DynamicMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO // Storage order
+ , typename Arg > // Min/max argument type
+void makeSymmetric( DynamicMatrix<Type,SO>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j), min, max );
+ matrix(j,i) = matrix(i,j);
+ }
+ randomize( matrix(i,i), min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian DynamicMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+void makeHermitian( DynamicMatrix<Type,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ typedef UnderlyingBuiltin_<Type> BT;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j) );
+ matrix(j,i) = conj( matrix(i,j) );
+ }
+ matrix(i,i) = rand<BT>();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian DynamicMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO // Storage order
+ , typename Arg > // Min/max argument type
+void makeHermitian( DynamicMatrix<Type,SO>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ typedef UnderlyingBuiltin_<Type> BT;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j), min, max );
+ matrix(j,i) = conj( matrix(i,j) );
+ }
+ matrix(i,i) = rand<BT>( real( min ), real( max ) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite DynamicMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+void makePositiveDefinite( DynamicMatrix<Type,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ randomize( matrix );
+ matrix *= ctrans( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) += Type(n);
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/DynamicVector.h b/src/cpu/blaze/math/DynamicVector.h
new file mode 100644
index 00000000..a2848d1f
--- /dev/null
+++ b/src/cpu/blaze/math/DynamicVector.h
@@ -0,0 +1,186 @@
+//=================================================================================================
+/*!
+// \file blaze/math/DynamicVector.h
+// \brief Header file for the complete DynamicVector implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DYNAMICVECTOR_H_
+#define _BLAZE_MATH_DYNAMICVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/DynamicVector.h>
+#include <blaze/math/dense/StaticVector.h>
+#include <blaze/math/DenseVector.h>
+#include <blaze/math/DynamicMatrix.h>
+#include <blaze/system/Precision.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for DynamicVector.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of DynamicVector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+class Rand< DynamicVector<Type,TF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const DynamicVector<Type,TF> generate( size_t n ) const;
+
+ template< typename Arg >
+ inline const DynamicVector<Type,TF> generate( size_t n, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( DynamicVector<Type,TF>& vector ) const;
+
+ template< typename Arg >
+ inline void randomize( DynamicVector<Type,TF>& vector, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DynamicVector.
+//
+// \param n The size of the random vector.
+// \return The generated random vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline const DynamicVector<Type,TF> Rand< DynamicVector<Type,TF> >::generate( size_t n ) const
+{
+ DynamicVector<Type,TF> vector( n );
+ randomize( vector );
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random DynamicVector.
+//
+// \param n The size of the random vector.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return The generated random vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline const DynamicVector<Type,TF>
+ Rand< DynamicVector<Type,TF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ DynamicVector<Type,TF> vector( n );
+ randomize( vector, min, max );
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a DynamicVector.
+//
+// \param vector The vector to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void Rand< DynamicVector<Type,TF> >::randomize( DynamicVector<Type,TF>& vector ) const
+{
+ using blaze::randomize;
+
+ const size_t size( vector.size() );
+ for( size_t i=0UL; i<size; ++i ) {
+ randomize( vector[i] );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a DynamicVector.
+//
+// \param vector The vector to be randomized.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< DynamicVector<Type,TF> >::randomize( DynamicVector<Type,TF>& vector,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ const size_t size( vector.size() );
+ for( size_t i=0UL; i<size; ++i ) {
+ randomize( vector[i], min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Epsilon.h b/src/cpu/blaze/math/Epsilon.h
new file mode 100644
index 00000000..7d503f4b
--- /dev/null
+++ b/src/cpu/blaze/math/Epsilon.h
@@ -0,0 +1,906 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Epsilon.h
+// \brief Numerical epsilon value for floating point data types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EPSILON_H_
+#define _BLAZE_MATH_EPSILON_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/Limits.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Negative epsilon value for floating point data types.
+// \ingroup math
+//
+// The NegativeEpsilon class is a wrapper class around the functionality of the blaze::Limits
+// class. It represents the negative smallest difference between two values of any floating
+// point data type. In order to assign a negative epsilon value, the Epsilon class can be
+// implicitly converted to the three built-in floating point data types float, double and
+// long double.
+//
+// \note The NegativeEpsilon class is a helper class for the Epsilon class. It cannot be
+// instantiated on its own, but can only be used by the Epsilon class.
+*/
+template< typename E > // Positive epsilon type
+class NegativeEpsilon
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef E PositiveType; //!< The positive epsilon type.
+ //**********************************************************************************************
+
+ private:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline NegativeEpsilon();
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Unary plus/minus operators******************************************************************
+ /*!\name Unary plus/minus operators */
+ //@{
+ inline const NegativeEpsilon& operator+() const;
+ inline const PositiveType operator-() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ template< typename T >
+ inline operator const T() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ NegativeEpsilon& operator=( const NegativeEpsilon& ); //!< Copy assignment operator (private & undefined)
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend class Epsilon;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor of the NegativeEpsilon class.
+*/
+template< typename E > // Positive epsilon type
+inline NegativeEpsilon<E>::NegativeEpsilon()
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UNARY PLUS/MINUS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the negative epsilon value for all floating point data types.
+//
+// \return The negative epsilon value.
+*/
+template< typename E > // Positive epsilon type
+inline const NegativeEpsilon<E>& NegativeEpsilon<E>::operator+() const
+{
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the positive epsilon value for all floating point data types.
+//
+// \return The positive epsilon value.
+*/
+template< typename E > // Positive epsilon type
+inline const typename NegativeEpsilon<E>::PositiveType NegativeEpsilon<E>::operator-() const
+{
+ return PositiveType();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the required floating point data type.
+//
+// The conversion operator returns the negative epsilon value for the floating point
+// data type \a T.
+*/
+template< typename E > // Positive epsilon type
+template< typename T > // Floating point data type
+inline NegativeEpsilon<E>::operator const T() const
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name NegativeEpsilon operators */
+//@{
+template< typename E, typename T >
+inline bool operator==( const NegativeEpsilon<E>& lhs, const T& rhs );
+
+template< typename E, typename T >
+inline bool operator==( const T& lhs, const NegativeEpsilon<E>& rhs );
+
+template< typename E, typename T >
+inline bool operator!=( const NegativeEpsilon<E>& lhs, const T& rhs );
+
+template< typename E, typename T >
+inline bool operator!=( const T& lhs, const NegativeEpsilon<E>& rhs );
+
+template< typename E, typename T >
+inline bool operator<( const NegativeEpsilon<E>& lhs, const T& rhs );
+
+template< typename E, typename T >
+inline bool operator<( const T& lhs, const NegativeEpsilon<E>& rhs );
+
+template< typename E, typename T >
+inline bool operator>( const NegativeEpsilon<E>& lhs, const T& rhs );
+
+template< typename E, typename T >
+inline bool operator>( const T& lhs, const NegativeEpsilon<E>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a NegativeEpsilon object and a floating point value.
+// \ingroup math
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is equal to the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator==( const NegativeEpsilon<E>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::epsilon() == rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a floating point value and a NegativeEpsilon object.
+// \ingroup math
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is equal to the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator==( const T& lhs, const NegativeEpsilon<E>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs == -Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a NegativeEpsilon object and a floating point value.
+// \ingroup math
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is unequal to the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator!=( const NegativeEpsilon<E>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::epsilon() != rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a floating point value and a NegativeEpsilon object.
+// \ingroup math
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is unequal to the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator!=( const T& lhs, const NegativeEpsilon<E>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs != -Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between a NegativeEpsilon object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is greater than the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator<( const NegativeEpsilon<E>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::epsilon() < rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between a floating point value and a NegativeEpsilon object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is smaller than the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator<( const T& lhs, const NegativeEpsilon<E>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs < -Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between a NegativeEpsilon object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is smaller than the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator>( const NegativeEpsilon<E>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::epsilon() > rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between a floating point value and a NegativeEpsilon object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is greater than the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator>( const T& lhs, const NegativeEpsilon<E>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs > -Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a NegativeEpsilon object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is greater than or equal to the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator<=( const NegativeEpsilon<E>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::epsilon() <= rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a floating point value and a NegativeEpsilon object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is smaller than or equal to the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator<=( const T& lhs, const NegativeEpsilon<E>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs <= -Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between a NegativeEpsilon object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the value is smaller than or equal to the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator>=( const NegativeEpsilon<E>& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return -Limits<T>::epsilon() >= rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a floating point value and a NegativeEpsilon object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the value is greater than or equal to the negative epsilon, \a false if not.
+//
+// This operator exclusively works for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename E // Positive epsilon type
+ , typename T > // Floating point data type
+inline bool operator>=( const T& lhs, const NegativeEpsilon<E>& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs >= -Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Numerical epsilon value for floating point data types.
+// \ingroup math
+//
+// The Epsilon class is a wrapper class around the functionality of the blaze::Limits class.
+// It represents the smallest difference between two values of any floating point data type.
+// In order to assign an epsilon value, the Epsilon class can be implicitly converted to the
+// three built-in floating point data types float, double and long double.\n
+// In order to handle epsilon values conveniently, the global Epsilon instance blaze::epsilon
+// is provided, which can be used wherever a floating point data type is required.
+
+ \code
+ float f = epsilon; // Assigns the positive epsilon for single precision values
+ double d = -epsilon; // Assigns the negative epsilon for double precision values
+ \endcode
+*/
+class Epsilon
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef NegativeEpsilon<Epsilon> NegativeType; //!< The negative epsilon type.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline Epsilon();
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Unary plus/minus operators******************************************************************
+ /*!\name Unary plus/minus operators */
+ //@{
+ inline const Epsilon& operator+() const;
+ inline const NegativeType operator-() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operators************************************************************************
+ /*!\name Conversion operators */
+ //@{
+ template< typename T >
+ inline operator const T() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ Epsilon& operator=( const Epsilon& ); //!< Copy assignment operator (private & undefined)
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor of the Epsilon class.
+*/
+inline Epsilon::Epsilon()
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UNARY PLUS/MINUS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the positive epsilon value for all floating point data types.
+//
+// \return The positive epsilon value.
+*/
+inline const Epsilon& Epsilon::operator+() const
+{
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the negative epsilon value for all floating point data types.
+//
+// \return The negative epsilon value.
+*/
+inline const Epsilon::NegativeType Epsilon::operator-() const
+{
+ return NegativeType();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the required floating point data type.
+//
+// The conversion operator returns the smallest possible difference between values of the
+// floating point data type \a T.
+*/
+template< typename T >
+inline Epsilon::operator const T() const
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Epsilon operators */
+//@{
+template< typename T >
+inline bool operator==( const Epsilon& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator==( const T& lhs, const Epsilon& rhs );
+
+template< typename T >
+inline bool operator!=( const Epsilon& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator!=( const T& lhs, const Epsilon& rhs );
+
+template< typename T >
+inline bool operator<( const Epsilon& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator<( const T& lhs, const Epsilon& rhs );
+
+template< typename T >
+inline bool operator>( const Epsilon& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator>( const T& lhs, const Epsilon& rhs );
+
+template< typename T >
+inline bool operator<=( const Epsilon& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator<=( const T& lhs, const Epsilon& rhs );
+
+template< typename T >
+inline bool operator>=( const Epsilon& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator>=( const T& lhs, const Epsilon& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between an Epsilon object and a floating point value.
+// \ingroup math
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is equal to epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator==( const Epsilon& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::epsilon() == rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a floating point value and an Epsilon object.
+// \ingroup math
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is equal to epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator==( const T& lhs, const Epsilon& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs == Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between an Epsilon object and a floating point value.
+// \ingroup math
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is unequal to epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator!=( const Epsilon& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::epsilon() != rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a floating point value and an Epsilon object.
+// \ingroup math
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is unequal to epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator!=( const T& lhs, const Epsilon& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs != Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between an Epsilon object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is greater than epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator<( const Epsilon& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::epsilon() < rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between a floating point value and an Epsilon object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is smaller than epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator<( const T& lhs, const Epsilon& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs < Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between an Epsilon object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is smaller than epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator>( const Epsilon& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::epsilon() > rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between a floating point value and an Epsilon object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is greater than epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator>( const T& lhs, const Epsilon& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs > Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between an Epsilon object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is greater than or equal to epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator<=( const Epsilon& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::epsilon() <= rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a floating point value and an Epsilon object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is smaller than or equal to epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator<=( const T& lhs, const Epsilon& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs <= Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between an Epsilon object and a floating point value.
+//
+// \param rhs The right-hand side floating point value.
+// \return \a true if the floating point value is smaller than or equal to epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator>=( const Epsilon& /*lhs*/, const T& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return Limits<T>::epsilon() >= rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a floating point value and an Epsilon object.
+//
+// \param lhs The left-hand side floating point value.
+// \return \a true if the floating point value is greater than or equal to epsilon, \a false if not.
+//
+// This operator works only for floating point data types. The attempt to compare any
+// integral data type or user-defined class types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator>=( const T& lhs, const Epsilon& /*rhs*/ )
+{
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ return lhs >= Limits<T>::epsilon();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL EPSILON VALUE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Global Epsilon instance.
+// \ingroup math
+//
+// The blaze::epsilon instance can be used wherever a floating point data type is expected.
+// It is implicitly converted to the corresponding floating point data type and represents
+// the smallest possible difference between two values of the according data type.
+*/
+const Epsilon epsilon;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Exception.h b/src/cpu/blaze/math/Exception.h
new file mode 100644
index 00000000..6179b434
--- /dev/null
+++ b/src/cpu/blaze/math/Exception.h
@@ -0,0 +1,150 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Exception.h
+// \brief Header file for the exception macros of the math module
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXCEPTION_H_
+#define _BLAZE_MATH_EXCEPTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Exception.h>
+
+
+
+
+//=================================================================================================
+//
+// EXCEPTION MACROS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW_DIVISION_BY_ZERO
+// \brief Macro for the emission of an exception on detection of a division by zero.
+// \ingroup math
+//
+// This macro encapsulates the default way of \b Blaze to throw an exception on detection of
+// a division by zero. Also, since it may be desirable to replace the type of exception by a
+// custom exception type this macro provides an opportunity to customize the behavior.
+//
+// The macro excepts a single argument, which specifies the message of the exception:
+
+ \code
+ #define BLAZE_THROW_DIVISION_BY_ZERO( MESSAGE ) \
+ BLAZE_THROW_RUNTIME_ERROR( MESSAGE )
+ \endcode
+
+// In order to customize the type of exception all that needs to be done is to define the macro
+// prior to including any \a Blaze header file. This will override the \b Blaze default behavior.
+// The following example demonstrates this by replacing \a std::runtime_error by a custom
+// exception type:
+
+ \code
+ class DivisionByZero
+ {
+ public:
+ DivisionByZero();
+ explicit DivisionByZero( const std::string& message );
+ // ...
+ };
+
+ #define BLAZE_THROW_DIVISION_BY_ZERO( MESSAGE ) \
+ throw DivisionByZero( MESSAGE )
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is recommended to define the macro such that a subsequent semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the type of exception via this
+// macro may have an effect on the library. Thus be advised to use the macro with due care!
+*/
+#ifndef BLAZE_THROW_DIVISION_BY_ZERO
+# define BLAZE_THROW_DIVISION_BY_ZERO( MESSAGE ) BLAZE_THROW_RUNTIME_ERROR( MESSAGE )
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW_LAPACK_ERROR
+// \brief Macro for the emission of an exception on detection of a LAPACK error.
+// \ingroup math
+//
+// This macro encapsulates the default way of \b Blaze to throw an exception when encountering
+// a LAPACK error (for instance when trying to invert a singular matrix). Also, since it may be
+// desirable to replace the type of exception by a custom exception type this macro provides an
+// opportunity to customize the behavior.
+//
+// The macro excepts a single argument, which specifies the message of the exception:
+
+ \code
+ #define BLAZE_THROW_LAPACK_ERROR( MESSAGE ) \
+ BLAZE_THROW_RUNTIME_ERROR( MESSAGE )
+ \endcode
+
+// In order to customize the type of exception all that needs to be done is to define the macro
+// prior to including any \a Blaze header file. This will override the \b Blaze default behavior.
+// The following example demonstrates this by replacing \a std::runtime_error by a custom
+// exception type:
+
+ \code
+ class LapackError
+ {
+ public:
+ LapackError();
+ explicit LapackError( const std::string& message );
+ // ...
+ };
+
+ #define BLAZE_THROW_LAPACK_ERROR( MESSAGE ) \
+ throw LapackError( MESSAGE )
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is recommended to define the macro such that a subsequent semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the type of exception via this
+// macro may have an effect on the library. Thus be advised to use the macro with due care!
+*/
+#ifndef BLAZE_THROW_LAPACK_ERROR
+# define BLAZE_THROW_LAPACK_ERROR( MESSAGE ) BLAZE_THROW_RUNTIME_ERROR( MESSAGE )
+#endif
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/Forward.h b/src/cpu/blaze/math/Forward.h
new file mode 100644
index 00000000..70e15ad1
--- /dev/null
+++ b/src/cpu/blaze/math/Forward.h
@@ -0,0 +1,49 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Forward.h
+// \brief Header file for all forward declarations of the math module
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FORWARD_H_
+#define _BLAZE_MATH_FORWARD_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/dense/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/sparse/Forward.h>
+#include <blaze/math/views/Forward.h>
+
+#endif
diff --git a/src/cpu/blaze/math/Functions.h b/src/cpu/blaze/math/Functions.h
new file mode 100644
index 00000000..7949fbb7
--- /dev/null
+++ b/src/cpu/blaze/math/Functions.h
@@ -0,0 +1,462 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Functions.h
+// \brief Header file for mathematical functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTIONS_H_
+#define _BLAZE_MATH_FUNCTIONS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/system/Inline.h>
+#include <blaze/util/constraints/Builtin.h>
+#include <blaze/util/constraints/Integral.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/All.h>
+#include <blaze/util/typetraits/CommonType.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MATHEMATICAL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Mathematical utility functions */
+//@{
+template< typename T >
+inline constexpr int sign( T a ) noexcept;
+
+template< typename T >
+inline size_t digits( T a ) noexcept;
+
+template< typename T1, typename T2 >
+BLAZE_ALWAYS_INLINE constexpr CommonType_<T1,T2>
+ min( const T1& a, const T2& b ) noexcept( All<IsNumeric,T1,T2>::value );
+
+template< typename T1, typename T2, typename... Ts >
+BLAZE_ALWAYS_INLINE constexpr CommonType_<T1,T2,Ts...>
+ min( const T1& a, const T2& b, const Ts&... args ) noexcept( All<IsNumeric,T1,T2,Ts...>::value );
+
+template< typename T1, typename T2 >
+BLAZE_ALWAYS_INLINE constexpr CommonType_<T1,T2>
+ max( const T1& a, const T2& b ) noexcept( All<IsNumeric,T1,T2>::value );
+
+template< typename T1, typename T2, typename... Ts >
+BLAZE_ALWAYS_INLINE constexpr CommonType_<T1,T2,Ts...>
+ max( const T1& a, const T2& b, const Ts&... args ) noexcept( All<IsNumeric,T1,T2,Ts...>::value );
+
+template< typename T >
+BLAZE_ALWAYS_INLINE T round( T a ) noexcept;
+
+template< typename T >
+BLAZE_ALWAYS_INLINE constexpr T nextMultiple( T value, T factor ) noexcept;
+
+template< typename T1, typename T2 >
+BLAZE_ALWAYS_INLINE constexpr bool lessThan( T1 a, T2 b )
+ noexcept( IsBuiltin< CommonType_<T1,T2> >::value );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sign function.
+// \ingroup math
+//
+// \param a The given value.
+// \return 1 if the value is greater than zero, 0 if it is zero, and -1 if it is smaller than zero.
+//
+// The sign function only works for built-in data types. The attempt to use any user-defined class
+// type will result in a compile time error.
+*/
+template< typename T >
+inline constexpr int sign( T a ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( T );
+
+ return ( IsSigned<T>::value || IsFloatingPoint<T>::value )
+ ?( T(0) < a ) - ( a < T(0) )
+ :( T(0) < a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of valid digits of an integral value.
+// \ingroup math
+//
+// \param a The integral value.
+// \return The number of valid digits.
+//
+// This function counts the number of valid digits in the given integral value.
+
+ \code
+ digits( 100 ); // Returns 3
+ digits( 12345 ); // Returns 5
+ digits( 0 ); // Returns 0
+ \endcode
+
+// The digits function only works for integral built-in data types. The attempt to use any
+// other type will result in a compile time error.
+*/
+template< typename T >
+inline size_t digits( T a ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_INTEGRAL_TYPE( T );
+
+ size_t count( 0 );
+
+ while( a != 0 ) {
+ a /= 10;
+ ++count;
+ }
+
+ return count;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Minimum function for two data values.
+// \ingroup math
+//
+// \param a The first value.
+// \param b The second value.
+// \return The minimum of the two values.
+//
+// This function returns the minimum of the two given data values. The return type of the function
+// is determined by the data types of the given arguments (for further detail see the CommonType
+// class description).
+*/
+template< typename T1, typename T2 >
+BLAZE_ALWAYS_INLINE constexpr CommonType_<T1,T2>
+ min( const T1& a, const T2& b ) noexcept( All<IsNumeric,T1,T2>::value )
+{
+ return ( a < b )?( a ):( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Minimum function for at least three data values.
+// \ingroup math
+//
+// \param a The first value.
+// \param b The second value.
+// \param args The pack of additional values.
+// \return The minimum of the given values.
+//
+// This function returns the minimum of the given data values. The return type of the function
+// is determined by the data types of the given arguments (for further detail see the CommonType
+// class description).
+*/
+template< typename T1, typename T2, typename... Ts >
+BLAZE_ALWAYS_INLINE constexpr CommonType_<T1,T2,Ts...>
+ min( const T1& a, const T2& b, const Ts&... args ) noexcept( All<IsNumeric,T1,T2,Ts...>::value )
+{
+ return min( a, min( b, args... ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Maximum function for two data values.
+// \ingroup math
+//
+// \param a The first value.
+// \param b The second value.
+// \return The maximum of the two values.
+//
+// This function returns the maximum of the two given data values. The return type of the function
+// is determined by the data types of the given arguments (for further detail see the CommonType
+// class description).
+*/
+template< typename T1, typename T2 >
+BLAZE_ALWAYS_INLINE constexpr CommonType_<T1,T2>
+ max( const T1& a, const T2& b ) noexcept( All<IsNumeric,T1,T2>::value )
+{
+ return ( a < b )?( b ):( a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Maximum function for at least three data values.
+// \ingroup math
+//
+// \param a The first value.
+// \param b The second value.
+// \param args The pack of additional values.
+// \return The maximum of the given values.
+//
+// This function returns the maximum of the given data values. The return type of the function
+// is determined by the data types of the given arguments (for further detail see the CommonType
+// class description).
+*/
+template< typename T1, typename T2, typename... Ts >
+BLAZE_ALWAYS_INLINE constexpr CommonType_<T1,T2,Ts...>
+ max( const T1& a, const T2& b, const Ts&... args ) noexcept( All<IsNumeric,T1,T2,Ts...>::value )
+{
+ return max( a, max( b, args... ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Rounds the given input value.
+// \ingroup math
+//
+// \param a Value to be rounded.
+// \return The rounded value.
+//
+// This function rounds the given input value. In case the first digit after the comma
+// is smaller than five the value is rounded down. Otherwise it is rounded up. Note that
+// this function only works for integral and floating point types. The attempt to use the
+// function for any other type will result in a compile time error.
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE T round( T a ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_INTEGRAL_TYPE( T );
+ return a;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Rounds the given single precision floating point value.
+// \ingroup math
+//
+// \param a Value to be rounded.
+// \return The rounded value.
+//
+// This function rounds the given single precision floating point value. In case the first
+// digit after the comma is smaller than five the value is rounded down. Otherwise it is
+// rounded up.
+*/
+BLAZE_ALWAYS_INLINE float round( float a ) noexcept
+{
+ return std::floor( a + 0.5F );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Rounds the given double precision floating point value.
+// \ingroup math
+//
+// \param a Value to be rounded.
+// \return The rounded value.
+//
+// This function rounds the given double precision floating point value. In case the first
+// digit after the comma is smaller than five the value is rounded down. Otherwise it is
+// rounded up.
+*/
+BLAZE_ALWAYS_INLINE double round( double a ) noexcept
+{
+ return std::floor( a + 0.5 );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Rounds the given long double precision floating point value.
+// \ingroup math
+//
+// \param a Value to be rounded.
+// \return The rounded value.
+//
+// This function rounds the given long double precision floating point value. In case the
+// first digit after the comma is smaller than five the value is rounded down. Otherwise
+// it is rounded up.
+*/
+BLAZE_ALWAYS_INLINE long double round( long double a ) noexcept
+{
+ return std::floor( a + 0.5L );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Rounds up an integral value to the next multiple of a given factor.
+// \ingroup math
+//
+// \param value The integral value to be rounded up \f$[1..\infty)\f$.
+// \param factor The factor of the multiple \f$[1..\infty)\f$.
+// \return The multiple of the given factor.
+//
+// This function rounds up the given integral value to the next multiple of the given factor.
+// In case the integral value is already a multiple of the given factor, the value itself is
+// returned. Note that both \a value and \a factor are expected to be positive integrals. In
+// case any of them is negative, the function returns 0. Note that the attempt to use the
+// function with non-integral types results in a compilation error!
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE constexpr T nextMultiple( T value, T factor ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_INTEGRAL_TYPE( T );
+
+ return ( value > T(0) && factor > T(0) )
+ ?( value + ( factor - ( value % factor ) ) % factor )
+ :( T(0) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default less-than comparison for any data type.
+// \ingroup math
+//
+// \param a First value.
+// \param b Second value.
+// \return \a true if the first value is smaller than the second, \a false if not.
+//
+// Default implementation of a less-than comparison of two data values.
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE constexpr bool lessThan_backend( const T& a, const T& b )
+ noexcept( IsBuiltin<T>::value )
+{
+ return a < b;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Less-than comparison for single precision floating point values.
+// \ingroup math
+//
+// \param a First value.
+// \param b Second value.
+// \return \a true if the first value is smaller than the second, \a false if not.
+//
+// Less-than function for the comparison of two single precision floating point numbers. Due
+// to the limited machine accuracy, a direct comparison of two floating point numbers should
+// be avoided. This functions offers the possibility to compare two floating-point values with
+// a certain accuracy margin.
+*/
+BLAZE_ALWAYS_INLINE constexpr bool lessThan_backend( float a, float b ) noexcept
+{
+ return ( b - a ) > 1E-8F;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Less-than comparison for double precision floating point values.
+// \ingroup math
+//
+// \param a First value.
+// \param b Second value.
+// \return \a true if the first value is smaller than the second, \a false if not.
+//
+// Less-than function for the comparison of two double precision floating point numbers. Due
+// to the limited machine accuracy, a direct comparison of two floating point numbers should
+// be avoided. This functions offers the possibility to compare two floating-point values with
+// a certain accuracy margin.
+*/
+BLAZE_ALWAYS_INLINE constexpr bool lessThan_backend( double a, double b ) noexcept
+{
+ return ( b - a ) > 1E-8;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Less-than comparison for long double precision floating point values.
+// \ingroup math
+//
+// \param a First value.
+// \param b Second value.
+// \return \a true if the first value is smaller than the second, \a false if not.
+//
+// Less-than function for the comparison of two long double precision floating point numbers. Due
+// to the limited machine accuracy, a direct comparison of two floating point numbers should be
+// avoided. This functions offers the possibility to compare two floating-point values with a
+// certain accuracy margin.
+*/
+BLAZE_ALWAYS_INLINE constexpr bool lessThan_backend( long double a, long double b ) noexcept
+{
+ return ( b - a ) > 1E-10;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Generic less-than comparison.
+// \ingroup math
+//
+// \param a First value.
+// \param b Second value.
+// \return \a true if the first value is smaller than the second, \a false if not.
+//
+// Generic less-than comparison between to numeric values. Depending on the types of the
+// two arguments, a special comparison for floating point values is selected that takes
+// the limited machine accuracy into account.
+*/
+template< typename T1, typename T2 >
+BLAZE_ALWAYS_INLINE constexpr bool lessThan( const T1& a, const T2& b )
+ noexcept( IsBuiltin< CommonType_<T1,T2> >::value )
+{
+ return lessThan_backend< CommonType_<T1,T2> >( a, b );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Functors.h b/src/cpu/blaze/math/Functors.h
new file mode 100644
index 00000000..b14b93de
--- /dev/null
+++ b/src/cpu/blaze/math/Functors.h
@@ -0,0 +1,77 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Functors.h
+// \brief Header file for all functors
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_H_
+#define _BLAZE_MATH_FUNCTORS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/functors/Abs.h>
+#include <blaze/math/functors/Acos.h>
+#include <blaze/math/functors/Acosh.h>
+#include <blaze/math/functors/Asin.h>
+#include <blaze/math/functors/Asinh.h>
+#include <blaze/math/functors/Atan.h>
+#include <blaze/math/functors/Atanh.h>
+#include <blaze/math/functors/Cbrt.h>
+#include <blaze/math/functors/Ceil.h>
+#include <blaze/math/functors/Conj.h>
+#include <blaze/math/functors/Cos.h>
+#include <blaze/math/functors/Cosh.h>
+#include <blaze/math/functors/CTrans.h>
+#include <blaze/math/functors/Erf.h>
+#include <blaze/math/functors/Erfc.h>
+#include <blaze/math/functors/Eval.h>
+#include <blaze/math/functors/Exp.h>
+#include <blaze/math/functors/Floor.h>
+#include <blaze/math/functors/Imag.h>
+#include <blaze/math/functors/Inv.h>
+#include <blaze/math/functors/InvCbrt.h>
+#include <blaze/math/functors/InvSqrt.h>
+#include <blaze/math/functors/Log.h>
+#include <blaze/math/functors/Log10.h>
+#include <blaze/math/functors/Pow.h>
+#include <blaze/math/functors/Real.h>
+#include <blaze/math/functors/Serial.h>
+#include <blaze/math/functors/Sin.h>
+#include <blaze/math/functors/Sinh.h>
+#include <blaze/math/functors/Sqrt.h>
+#include <blaze/math/functors/Tan.h>
+#include <blaze/math/functors/Tanh.h>
+#include <blaze/math/functors/Trans.h>
+
+#endif
diff --git a/src/cpu/blaze/math/HermitianMatrix.h b/src/cpu/blaze/math/HermitianMatrix.h
new file mode 100644
index 00000000..60dfabf5
--- /dev/null
+++ b/src/cpu/blaze/math/HermitianMatrix.h
@@ -0,0 +1,687 @@
+//=================================================================================================
+/*!
+// \file blaze/math/HermitianMatrix.h
+// \brief Header file for the complete HermitianMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_HERMITIANMATRIX_H_
+#define _BLAZE_MATH_HERMITIANMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <stdexcept>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/HermitianMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/shims/Real.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for HermitianMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of HermitianMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+class Rand< HermitianMatrix<MT,SO,DF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const HermitianMatrix<MT,SO,DF> generate() const;
+ inline const HermitianMatrix<MT,SO,DF> generate( size_t n ) const;
+ inline const HermitianMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const HermitianMatrix<MT,SO,DF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const HermitianMatrix<MT,SO,DF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const HermitianMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( HermitianMatrix<MT,SO,DF>& matrix ) const;
+ inline void randomize( HermitianMatrix<MT,SO,DF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( HermitianMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( HermitianMatrix<MT,SO,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( HermitianMatrix<MT,SO,DF>& matrix, TrueType ) const;
+ inline void randomize( HermitianMatrix<MT,SO,DF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( HermitianMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( HermitianMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HermitianMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline const HermitianMatrix<MT,SO,DF> Rand< HermitianMatrix<MT,SO,DF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ HermitianMatrix<MT,SO,DF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HermitianMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline const HermitianMatrix<MT,SO,DF>
+ Rand< HermitianMatrix<MT,SO,DF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ HermitianMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HermitianMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline const HermitianMatrix<MT,SO,DF>
+ Rand< HermitianMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > n*n )
+ throw std::invalid_argument( "Invalid number of non-zero elements" );
+
+ HermitianMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HermitianMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+template< typename Arg > // Min/max argument type
+inline const HermitianMatrix<MT,SO,DF>
+ Rand< HermitianMatrix<MT,SO,DF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ HermitianMatrix<MT,SO,DF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HermitianMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+template< typename Arg > // Min/max argument type
+inline const HermitianMatrix<MT,SO,DF>
+ Rand< HermitianMatrix<MT,SO,DF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ HermitianMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HermitianMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+template< typename Arg > // Min/max argument type
+inline const HermitianMatrix<MT,SO,DF>
+ Rand< HermitianMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > n*n )
+ throw std::invalid_argument( "Invalid number of non-zero elements" );
+
+ HermitianMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void Rand< HermitianMatrix<MT,SO,DF> >::randomize( HermitianMatrix<MT,SO,DF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void Rand< HermitianMatrix<MT,SO,DF> >::randomize( HermitianMatrix<MT,SO,DF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+ typedef UnderlyingBuiltin_<ET> BT;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ matrix(i,j) = rand<ET>();
+ }
+ matrix(i,i) = rand<BT>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void Rand< HermitianMatrix<MT,SO,DF> >::randomize( HermitianMatrix<MT,SO,DF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*n*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void Rand< HermitianMatrix<MT,SO,DF> >::randomize( HermitianMatrix<MT,SO,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+ typedef UnderlyingBuiltin_<ET> BT;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > n*n )
+ throw std::invalid_argument( "Invalid number of non-zero elements" );
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ while( matrix.nonZeros() < nonzeros )
+ {
+ const size_t row ( rand<size_t>( 0UL, n-1UL ) );
+ const size_t column( rand<size_t>( 0UL, n-1UL ) );
+
+ if( row == column )
+ matrix(row,column) = rand<BT>();
+ else
+ matrix(row,column) = rand<ET>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+template< typename Arg > // Min/max argument type
+inline void Rand< HermitianMatrix<MT,SO,DF> >::randomize( HermitianMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+template< typename Arg > // Min/max argument type
+inline void Rand< HermitianMatrix<MT,SO,DF> >::randomize( HermitianMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+ typedef UnderlyingBuiltin_<ET> BT;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ matrix(i,j) = rand<ET>( min, max );
+ }
+ matrix(i,i) = rand<BT>( real( min ), real( max ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+template< typename Arg > // Min/max argument type
+inline void Rand< HermitianMatrix<MT,SO,DF> >::randomize( HermitianMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*n*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+template< typename Arg > // Min/max argument type
+inline void Rand< HermitianMatrix<MT,SO,DF> >::randomize( HermitianMatrix<MT,SO,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+ typedef UnderlyingBuiltin_<ET> BT;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > n*n )
+ throw std::invalid_argument( "Invalid number of non-zero elements" );
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ while( matrix.nonZeros() < nonzeros )
+ {
+ const size_t row ( rand<size_t>( 0UL, n-1UL ) );
+ const size_t column( rand<size_t>( 0UL, n-1UL ) );
+
+ if( row == column )
+ matrix(row,column) = rand<BT>( real( min ), real( max ) );
+ else
+ matrix(row,column) = rand<ET>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeSymmetric( HermitianMatrix<MT,SO,DF>& matrix )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > BT;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ matrix(i,j) = rand<BT>();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeSymmetric( HermitianMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > BT;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ matrix(i,j) = rand<BT>( real( min ), real( max ) );
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeHermitian( HermitianMatrix<MT,SO,DF>& matrix )
+{
+ using blaze::randomize;
+
+ randomize( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeHermitian( HermitianMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ randomize( matrix, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite HermitianMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makePositiveDefinite( HermitianMatrix<MT,SO,DF>& matrix )
+{
+ using blaze::randomize;
+
+ typedef UnderlyingBuiltin_< ElementType_<MT> > BT;
+
+ const size_t n( matrix.rows() );
+
+ randomize( matrix );
+ matrix *= matrix;
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) += BT(n);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/HybridMatrix.h b/src/cpu/blaze/math/HybridMatrix.h
new file mode 100644
index 00000000..f6dc634d
--- /dev/null
+++ b/src/cpu/blaze/math/HybridMatrix.h
@@ -0,0 +1,412 @@
+//=================================================================================================
+/*!
+// \file blaze/math/HybridMatrix.h
+// \brief Header file for the complete HybridMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_HYBRIDMATRIX_H_
+#define _BLAZE_MATH_HYBRIDMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/HybridMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/HybridVector.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Real.h>
+#include <blaze/math/StaticMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/system/Precision.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for HybridMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of HybridMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+class Rand< HybridMatrix<Type,M,N,SO> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const HybridMatrix<Type,M,N,SO> generate( size_t m, size_t n ) const;
+
+ template< typename Arg >
+ inline const HybridMatrix<Type,M,N,SO> generate( size_t m, size_t n, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( HybridMatrix<Type,M,N,SO>& matrix ) const;
+
+ template< typename Arg >
+ inline void randomize( HybridMatrix<Type,M,N,SO>& matrix, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HybridMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline const HybridMatrix<Type,M,N,SO>
+ Rand< HybridMatrix<Type,M,N,SO> >::generate( size_t m, size_t n ) const
+{
+ HybridMatrix<Type,M,N,SO> matrix( m, n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HybridMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline const HybridMatrix<Type,M,N,SO>
+ Rand< HybridMatrix<Type,M,N,SO> >::generate( size_t m, size_t n, const Arg& min, const Arg& max ) const
+{
+ HybridMatrix<Type,M,N,SO> matrix( m, n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a HybridMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void Rand< HybridMatrix<Type,M,N,SO> >::randomize( HybridMatrix<Type,M,N,SO>& matrix ) const
+{
+ using blaze::randomize;
+
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j ) {
+ randomize( matrix(i,j) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a HybridMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< HybridMatrix<Type,M,N,SO> >::randomize( HybridMatrix<Type,M,N,SO>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ const size_t m( matrix.rows() );
+ const size_t n( matrix.columns() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j ) {
+ randomize( matrix(i,j), min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric HybridMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+void makeSymmetric( HybridMatrix<Type,M,N,SO>& matrix )
+{
+ using blaze::randomize;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j) );
+ matrix(j,i) = matrix(i,j);
+ }
+ randomize( matrix(i,i) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric HybridMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO // Storage order
+ , typename Arg > // Min/max argument type
+void makeSymmetric( HybridMatrix<Type,M,N,SO>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j), min, max );
+ matrix(j,i) = matrix(i,j);
+ }
+ randomize( matrix(i,i), min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian HybridMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+void makeHermitian( HybridMatrix<Type,M,N,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ typedef UnderlyingBuiltin_<Type> BT;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j) );
+ matrix(j,i) = conj( matrix(i,j) );
+ }
+ matrix(i,i) = rand<BT>();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian HybridMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO // Storage order
+ , typename Arg > // Min/max argument type
+void makeHermitian( HybridMatrix<Type,M,N,SO>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ typedef UnderlyingBuiltin_<Type> BT;
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j), min, max );
+ matrix(j,i) = conj( matrix(i,j) );
+ }
+ matrix(i,i) = rand<BT>( real( min ), real( max ) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite HybridMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+void makePositiveDefinite( HybridMatrix<Type,M,N,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ if( !isSquare( ~matrix ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( matrix.rows() );
+
+ randomize( matrix );
+ matrix *= ctrans( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) += Type(n);
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/HybridVector.h b/src/cpu/blaze/math/HybridVector.h
new file mode 100644
index 00000000..8873d8be
--- /dev/null
+++ b/src/cpu/blaze/math/HybridVector.h
@@ -0,0 +1,188 @@
+//=================================================================================================
+/*!
+// \file blaze/math/HybridVector.h
+// \brief Header file for the complete HybridVector implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_HYBRIDVECTOR_H_
+#define _BLAZE_MATH_HYBRIDVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/HybridVector.h>
+#include <blaze/math/dense/StaticVector.h>
+#include <blaze/math/DenseVector.h>
+#include <blaze/math/DynamicMatrix.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for HybridVector.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of HybridVector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+class Rand< HybridVector<Type,N,TF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const HybridVector<Type,N,TF> generate( size_t n ) const;
+
+ template< typename Arg >
+ inline const HybridVector<Type,N,TF> generate( size_t n, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( HybridVector<Type,N,TF>& vector ) const;
+
+ template< typename Arg >
+ inline void randomize( HybridVector<Type,N,TF>& vector, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HybridVector.
+//
+// \param n The size of the random vector.
+// \return The generated random vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline const HybridVector<Type,N,TF> Rand< HybridVector<Type,N,TF> >::generate( size_t n ) const
+{
+ HybridVector<Type,N,TF> vector( n );
+ randomize( vector );
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random HybridVector.
+//
+// \param n The size of the random vector.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return The generated random vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline const HybridVector<Type,N,TF>
+ Rand< HybridVector<Type,N,TF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ HybridVector<Type,N,TF> vector( n );
+ randomize( vector, min, max );
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a HybridVector.
+//
+// \param vector The vector to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void Rand< HybridVector<Type,N,TF> >::randomize( HybridVector<Type,N,TF>& vector ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<vector.size(); ++i ) {
+ randomize( vector[i] );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a HybridVector.
+//
+// \param vector The vector to be randomized.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< HybridVector<Type,N,TF> >::randomize( HybridVector<Type,N,TF>& vector,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<vector.size(); ++i ) {
+ randomize( vector[i], min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Infinity.h b/src/cpu/blaze/math/Infinity.h
new file mode 100644
index 00000000..4121e664
--- /dev/null
+++ b/src/cpu/blaze/math/Infinity.h
@@ -0,0 +1,1103 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Infinity.h
+// \brief Numerical infinity for built-in data types.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_INFINITY_H_
+#define _BLAZE_MATH_INFINITY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/constraints/Builtin.h>
+#include <blaze/util/Limits.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Negative infinity for built-in data types.
+// \ingroup math
+//
+// The NegativeInfinity class is a wrapper class around the functionality of the blaze::Limits
+// class to provide the possibility to assign negative infinity values to built-in data types.
+// As negative infinity value, the largest possible negative value of the corresponding data
+// type is used. In order to assign the negative infinity value, the NegativeInfinity class
+// can be implicitly converted to all signed integral and floating point data types:
+//
+// <ul>
+// <li>integers</li>
+// <ul>
+// <li>signed char, char, wchar_t</li>
+// <li>short</li>
+// <li>int</li>
+// <li>long</li>
+// <li>ptrdiff_t (for certain 64-bit compilers)</li>
+// </ul>
+// <li>floating points</li>
+// <ul>
+// <li>float</li>
+// <li>double</li>
+// <li>long double</li>
+// </ul>
+// </ul>
+//
+// \note The NegativeInfinity class is a helper class for the Infinity class. It cannot be
+// instantiated on its own, but can only be used by the Infinity class.
+*/
+template< typename I > // Positive infinity type
+class NegativeInfinity
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef I PositiveType; //!< The positive infinity type.
+ //**********************************************************************************************
+
+ private:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline NegativeInfinity();
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Conversion operators************************************************************************
+ /*!\name Conversion operators */
+ //@{
+ inline operator signed char() const;
+ inline operator char() const;
+ inline operator wchar_t() const;
+ inline operator short() const;
+ inline operator int() const;
+ inline operator long() const;
+#if defined(_WIN64)
+ inline operator ptrdiff_t() const;
+#endif
+ inline operator float() const;
+ inline operator double() const;
+ inline operator long double() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ template< typename T >
+ inline bool equal( const T& rhs ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ NegativeInfinity& operator=( const NegativeInfinity& ninf ); //!< Copy assignment operator (private & undefined)
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend class Infinity;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor of the NegativeInfinity class.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::NegativeInfinity()
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the signed char built-in type.
+//
+// The conversion operator returns the smallest possible signed char value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator signed char() const
+{
+ return Limits<signed char>::ninf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the char built-in type.
+//
+// The conversion operator returns the smallest possible char value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator char() const
+{
+ return Limits<char>::ninf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the wchar_t built-in type.
+//
+// The conversion operator returns the smallest possible wchar_t value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator wchar_t() const
+{
+ return Limits<wchar_t>::ninf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the short built-in type.
+//
+// The conversion operator returns the smallest possible short value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator short() const
+{
+ return Limits<short>::ninf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the int built-in type.
+//
+// The conversion operator returns the smallest possible int value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator int() const
+{
+ return Limits<int>::ninf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the long built-in type.
+//
+// The conversion operator returns the smallest possible long value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator long() const
+{
+ return Limits<long>::ninf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if defined(_WIN64)
+/*!\brief Conversion operator to the ptrdiff_t built-in type.
+//
+// The conversion operator returns the smallest possible ptrdiff_t value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator ptrdiff_t() const
+{
+ return Limits<ptrdiff_t>::ninf();
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the float built-in type.
+//
+// The conversion operator returns the smallest possible float value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator float() const
+{
+ return Limits<float>::ninf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the double built-in type.
+//
+// The conversion operator returns the smallest possible double value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator double() const
+{
+ return Limits<double>::ninf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the long double built-in type.
+//
+// The conversion operator returns the smallest possible long double value.
+*/
+template< typename I > // Positive infinity type
+inline NegativeInfinity<I>::operator long double() const
+{
+ return Limits<long double>::ninf();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Equality comparison to a built-in data type.
+//
+// This function compares built-in data types with their largest possible value. The function
+// only works for built-in data types. The attempt to compare user-defined class types will
+// result in a compile time error.
+*/
+template< typename I > // Positive infinity type
+template< typename T > // Built-in data type
+inline bool NegativeInfinity<I>::equal( const T& rhs ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( T );
+ return Limits<T>::ninf() == rhs;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name NegativeInfinity operators */
+//@{
+template< typename I1, typename I2 >
+inline bool operator==( const NegativeInfinity<I1>& lhs, const NegativeInfinity<I2>& rhs );
+
+template< typename I, typename T >
+inline bool operator==( const NegativeInfinity<I>& lhs, const T& rhs );
+
+template< typename I, typename T >
+inline bool operator==( const T& lhs, const NegativeInfinity<I>& rhs );
+
+template< typename I1, typename I2 >
+inline bool operator!=( const NegativeInfinity<I1>& lhs, const NegativeInfinity<I2>& rhs );
+
+template< typename I, typename T >
+inline bool operator!=( const NegativeInfinity<I>& lhs, const T& rhs );
+
+template< typename I, typename T >
+inline bool operator!=( const T& lhs, const NegativeInfinity<I>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two NegativeInfinity objects.
+// \ingroup math
+//
+// \param lhs The left-hand side NegativeInfinity object.
+// \param rhs The right-hand side NegativeInfinity object.
+// \return \a true.
+*/
+template< typename I1 // Left-hand side positive infinity type
+ , typename I2 > // Right-hand side positive infinity type
+inline bool operator==( const NegativeInfinity<I1>& lhs, const NegativeInfinity<I2>& rhs )
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between an NegativeInfinity object and a built-in data type.
+// \ingroup math
+//
+// \param lhs The left-hand side NegativeInfinity object.
+// \param rhs The right-hand side built-in data value.
+// \return \a true if the built-in data value is negative infinity, \a false if not.
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename I // Positive infinity type
+ , typename T > // Built-in data type
+inline bool operator==( const NegativeInfinity<I>& lhs, const T& rhs )
+{
+ return lhs.equal( rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a built-in data type and an NegativeInfinity object.
+// \ingroup math
+//
+// \param lhs The left-hand side built-in data value.
+// \param rhs The right-hand side NegativeInfinity object.
+// \return \a true if the built-in data value is negative infinity, \a false if not.
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename I // Positive infinity type
+ , typename T > // Built-in data type
+inline bool operator==( const T& lhs, const NegativeInfinity<I>& rhs )
+{
+ return rhs.equal( lhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two NegativeInfinity objects.
+// \ingroup math
+//
+// \param lhs The left-hand side NegativeInfinity object.
+// \param rhs The right-hand side NegativeInfinity object.
+// \return \a false.
+*/
+template< typename I1 // Left-hand side positive infinity type
+ , typename I2 > // Right-hand side positive infinity type
+inline bool operator!=( const NegativeInfinity<I1>& lhs, const NegativeInfinity<I2>& rhs )
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between an NegativeInfinity object and a built-in data type.
+// \ingroup math
+//
+// \param lhs The left-hand side NegativeInfinity object.
+// \param rhs The right-hand side built-in data value.
+// \return \a true if the built-in data value is not negative infinity, \a false if it is.
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename I // Positive infinity type
+ , typename T > // Built-in data type
+inline bool operator!=( const NegativeInfinity<I>& lhs, const T& rhs )
+{
+ return !lhs.equal( rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a built-in data type and an NegativeInfinity object.
+// \ingroup math
+//
+// \param lhs The left-hand side built-in data value.
+// \param rhs The right-hand side NegativeInfinity object.
+// \return \a true if the built-in data value is not negative infinity, \a false if it is.
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename I // Positive infinity type
+ , typename T > // Built-in data type
+inline bool operator!=( const T& lhs, const NegativeInfinity<I>& rhs )
+{
+ return !rhs.equal( lhs );
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Positive infinity for built-in data types.
+// \ingroup math
+//
+// The Infinity class is a wrapper class around the functionality of the blaze::Limits class
+// to provide the possiblity to assign a positive infinity value to built-in data types.
+// As positive infinity value, the largest possible positive value of the corresponding
+// data type is used. In order to assign the positive infinity value, the Infinity class
+// can be implicitly converted to the following 13 built-in integral and floating point
+// data types:
+//
+// <ul>
+// <li>integers</li>
+// <ul>
+// <li>unsigned char, signed char, char, wchar_t</li>
+// <li>unsigned short, short</li>
+// <li>unsigned int, int</li>
+// <li>unsigned long, long</li>
+// </ul>
+// <li>floating points</li>
+// <ul>
+// <li>float</li>
+// <li>double</li>
+// <li>long double</li>
+// </ul>
+// </ul>
+//
+// In order to be able to assign infinity values, the global Infinity instance blaze::inf
+// is provided, which can be used wherever a built-in data type is required.
+
+ \code
+ int i = inf; // Assigns a positive infinity value
+ double d = -inf; // Assigns a negative infinity value
+ ...
+ \endcode
+*/
+class Infinity
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef NegativeInfinity<Infinity> NegativeType; //!< The negative infinity type.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline Infinity();
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Conversion operators************************************************************************
+ /*!\name Conversion operators */
+ //@{
+ inline operator unsigned char() const;
+ inline operator signed char() const;
+ inline operator char() const;
+ inline operator wchar_t() const;
+ inline operator unsigned short() const;
+ inline operator short() const;
+ inline operator unsigned int() const;
+ inline operator int() const;
+ inline operator unsigned long() const;
+ inline operator long() const;
+#if defined(_WIN64)
+ inline operator size_t() const;
+ inline operator ptrdiff_t() const;
+#endif
+ inline operator float() const;
+ inline operator double() const;
+ inline operator long double() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Arithmetic operators************************************************************************
+ /*!\name Arithmetic operators */
+ //@{
+ inline const Infinity& operator+() const;
+ inline const NegativeType operator-() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ template< typename T >
+ inline bool equal( const T& rhs ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ Infinity& operator=( const Infinity& inf ); //!< Copy assignment operator (private & undefined)
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor of the Infinity class.
+*/
+inline Infinity::Infinity()
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the unsigned char built-in type.
+//
+// The conversion operator returns the largest possible unsigned char value.
+*/
+inline Infinity::operator unsigned char() const
+{
+ return Limits<unsigned char>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the char built-in type.
+//
+// The conversion operator returns the largest possible char value.
+*/
+inline Infinity::operator char() const
+{
+ return Limits<char>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the signed char built-in type.
+//
+// The conversion operator returns the largest possible signed char value.
+*/
+inline Infinity::operator signed char() const
+{
+ return Limits<signed char>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the wchar_t built-in type.
+//
+// The conversion operator returns the largest possible wchar_t value.
+*/
+inline Infinity::operator wchar_t() const
+{
+ return Limits<wchar_t>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the unsigned short built-in type.
+//
+// The conversion operator returns the largest possible unsigned short value.
+*/
+inline Infinity::operator unsigned short() const
+{
+ return Limits<unsigned short>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the short built-in type.
+//
+// The conversion operator returns the largest possible short value.
+*/
+inline Infinity::operator short() const
+{
+ return Limits<short>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the unsigned int built-in type.
+//
+// The conversion operator returns the largest possible unsigned int value.
+*/
+inline Infinity::operator unsigned int() const
+{
+ return Limits<unsigned int>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the int built-in type.
+//
+// The conversion operator returns the largest possible int value.
+*/
+inline Infinity::operator int() const
+{
+ return Limits<int>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the unsigned long built-in type.
+//
+// The conversion operator returns the largest possible unsigned long value.
+*/
+inline Infinity::operator unsigned long() const
+{
+ return Limits<unsigned long>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the long built-in type.
+//
+// The conversion operator returns the largest possible long value.
+*/
+inline Infinity::operator long() const
+{
+ return Limits<long>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if defined(_WIN64)
+/*!\brief Conversion operator to the size_t built-in type.
+//
+// The conversion operator returns the largest possible size_t value.
+*/
+inline Infinity::operator size_t() const
+{
+ return Limits<size_t>::inf();
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if defined(_WIN64)
+/*!\brief Conversion operator to the ptrdiff_t built-in type.
+//
+// The conversion operator returns the largest possible ptrdiff_t value.
+*/
+inline Infinity::operator ptrdiff_t() const
+{
+ return Limits<ptrdiff_t>::inf();
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the float built-in type.
+//
+// The conversion operator returns the largest possible float value.
+*/
+inline Infinity::operator float() const
+{
+ return Limits<float>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the double built-in type.
+//
+// The conversion operator returns the largest possible double value.
+*/
+inline Infinity::operator double() const
+{
+ return Limits<double>::inf();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to the long double built-in type.
+//
+// The conversion operator returns the largest possible long double value.
+*/
+inline Infinity::operator long double() const
+{
+ return Limits<long double>::inf();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the positive infinity value for all built-in data types.
+//
+// \return The positive infinity value.
+*/
+inline const Infinity& Infinity::operator+() const
+{
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the negative infinity value for all built-in data types.
+//
+// \return The negative infinity value.
+*/
+inline const Infinity::NegativeType Infinity::operator-() const
+{
+ return NegativeType();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Equality comparison to a built-in data type.
+//
+// This function compares built-in data types with their largest possible value. The function
+// only works for built-in data types. The attempt to compare user-defined class types will
+// result in a compile time error.
+*/
+template< typename T >
+inline bool Infinity::equal( const T& rhs ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( T );
+ return Limits<T>::inf() == rhs;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Infinity operators */
+//@{
+inline bool operator==( const Infinity& lhs, const Infinity& rhs );
+
+template< typename I >
+inline bool operator==( const Infinity& lhs, const NegativeInfinity<I>& rhs );
+
+template< typename I >
+inline bool operator==( const NegativeInfinity<I>& lhs, const Infinity& rhs );
+
+template< typename T >
+inline bool operator==( const Infinity& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator==( const T& lhs, const Infinity& rhs );
+
+inline bool operator!=( const Infinity& lhs, const Infinity& rhs );
+
+template< typename I >
+inline bool operator!=( const Infinity& lhs, const NegativeInfinity<I>& rhs );
+
+template< typename I >
+inline bool operator!=( const NegativeInfinity<I>& lhs, const Infinity& rhs );
+
+template< typename T >
+inline bool operator!=( const Infinity& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator!=( const T& lhs, const Infinity& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two Infinity objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Infinity object.
+// \param rhs The right-hand side Infinity object.
+// \return \a true.
+*/
+inline bool operator==( const Infinity& lhs, const Infinity& rhs )
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between an Infinity object and a NegativeInfinity object.
+// \ingroup math
+//
+// \param lhs The left-hand side Infinity object.
+// \param rhs The right-hand side NegativeInfinity object.
+// \return \a false.
+*/
+template< typename I > // Positive infinity type
+inline bool operator==( const Infinity& lhs, const NegativeInfinity<I>& rhs )
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a NegativeInfinity object and an Infinity object.
+// \ingroup math
+//
+// \param rhs The left-hand side NegativeInfinity object.
+// \param lhs The right-hand side Infinity object.
+// \return \a false.
+*/
+template< typename I > // Positive infinity type
+inline bool operator==( const NegativeInfinity<I>& lhs, const Infinity& rhs )
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between an Infinity object and a built-in data type.
+// \ingroup math
+//
+// \param lhs The left-hand side Infinity object.
+// \param rhs The right-hand side built-in data value.
+// \return \a true if the built-in data value is infinity, \a false if not.
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator==( const Infinity& lhs, const T& rhs )
+{
+ return lhs.equal( rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a built-in data type and an Infinity object.
+// \ingroup math
+//
+// \param lhs The left-hand side built-in data value.
+// \param rhs The right-hand side Infinity object.
+// \return \a true if the built-in data value is infinity, \a false if not.
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator==( const T& lhs, const Infinity& rhs )
+{
+ return rhs.equal( lhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two Infinity objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Infinity object.
+// \param rhs The right-hand side Infinity object.
+// \return \a false.
+*/
+inline bool operator!=( const Infinity& lhs, const Infinity& rhs )
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between an Infinity object and a NegativeInfinity object.
+// \ingroup math
+//
+// \param lhs The left-hand side Infinity object.
+// \param rhs The right-hand side NegativeInfinity object.
+// \return \a true.
+*/
+template< typename I > // Positive infinity type
+inline bool operator!=( const Infinity& lhs, const NegativeInfinity<I>& rhs )
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a NegativeInfinity object and an Infinity object.
+// \ingroup math
+//
+// \param rhs The left-hand side NegativeInfinity object.
+// \param lhs The right-hand side Infinity object.
+// \return \a true.
+*/
+template< typename I > // Positive infinity type
+inline bool operator!=( const NegativeInfinity<I>& lhs, const Infinity& rhs )
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between an Infinity object and a built-in data type.
+// \ingroup math
+//
+// \param lhs The left-hand side Infinity object.
+// \param rhs The right-hand side built-in data value.
+// \return \a true if the built-in data value is not infinity, \a false if it is.
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator!=( const Infinity& lhs, const T& rhs )
+{
+ return !lhs.equal( rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a built-in data type and an Infinity object.
+// \ingroup math
+//
+// \param lhs The left-hand side built-in data value.
+// \param rhs The right-hand side Infinity object.
+// \return \a true if the built-in data value is not infinity, \a false if it is.
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator!=( const T& lhs, const Infinity& rhs )
+{
+ return !rhs.equal( lhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL INFINITY VALUE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Global Infinity instance.
+// \ingroup math
+//
+// The blaze::inf instance can be used wherever a built-in data type is expected. It is implicitly
+// converted to the corresponding built-in data type and represents its largest possible data
+// value.
+*/
+const Infinity inf;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/InitializerList.h b/src/cpu/blaze/math/InitializerList.h
new file mode 100644
index 00000000..745ec8f5
--- /dev/null
+++ b/src/cpu/blaze/math/InitializerList.h
@@ -0,0 +1,91 @@
+//=================================================================================================
+/*!
+// \file blaze/math/InitializerList.h
+// \brief Header file for the std::initializer_list aliases
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_INITIALIZERLIST_H_
+#define _BLAZE_MATH_INITIALIZERLIST_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <initializer_list>
+#include <blaze/math/Functions.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// TYPE DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::initializer_list
+// \brief Initializer list type of the Blaze library.
+// \ingroup math
+*/
+using std::initializer_list;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Determine the maximum number of columns specified by the given initializer list.
+// \ingroup math
+//
+// \param list The given initializer list
+// \return The maximum number of columns.
+*/
+template< typename Type >
+inline size_t determineColumns( initializer_list< initializer_list<Type> > list ) noexcept
+{
+ size_t cols( 0UL );
+ for( const auto& rowList : list )
+ cols = max( cols, rowList.size() );
+ return cols;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/InversionFlag.h b/src/cpu/blaze/math/InversionFlag.h
new file mode 100644
index 00000000..b0790fca
--- /dev/null
+++ b/src/cpu/blaze/math/InversionFlag.h
@@ -0,0 +1,88 @@
+//=================================================================================================
+/*!
+// \file blaze/math/InversionFlag.h
+// \brief Header file for the dense matrix inversion flags
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_INVERSIONFLAG_H_
+#define _BLAZE_MATH_INVERSIONFLAG_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DECOMPOSITION FLAG VALUES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inversion flag.
+// \ingroup dense_matrix
+//
+// The InversionFlag type enumeration represents the different types of matrix inversion algorithms
+// that are available within the Blaze library. The following flags are available:
+//
+// - \a byDefault: The default algorithm for each type of matrix. In case of general square
+// matrices an LU decomposition is used, in case of symmetric and Hermitian matrices
+// the Bunch-Kaufman diagonal pivoting method is applied, and in case of triangular
+// matrices a direct inversion via backward substitution is performed.
+// - \a byLU: The default inversion algorithm for general square matrices. It uses the LU
+// algorithm to decompose a matrix into a lower unitriangular matrix \c L, an upper
+// triangular matrix \c U, and a permutation matrix \c P (\f$ A = P L U \f$). If no
+// permutations are required, \c P is the identity matrix.
+// - \a byLDLT: The Bunch-Kaufman inversion algorithm for symmetric indefinite matrices. It
+// decomposes the given matrix into either \f$ A = U D U^{T} \f$ or \f$ A = L D L^{T} \f$,
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular
+// matrices, and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal
+// blocks.
+// - \a byLDLH: The Bunch-Kaufman inversion algorithm for Hermitian indefinite matrices. It
+// decomposes the given matrix into either \f$ A = U D U^{H} \f$ or \f$ A = L D L^{H} \f$,
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular
+// matrices, and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal
+// blocks.
+// - \a byLLH: The Cholesky inversion algorithm for Hermitian positive definite matrices. It
+// decomposes a given matrix into either \f$ A = L L^H \f$, where \c L is a lower
+// triangular matrix, or \f$ A = U^H U \f$, where \c U is an upper triangular matrix.
+*/
+enum InversionFlag
+{
+ byDefault = 0, //!< Flag for the default, optimal inversion algorithm.
+ byLU = 1, //!< Flag for the LU-based matrix inversion.
+ byLDLT = 2, //!< Flag for the Bunch-Kaufman-based inversion for symmetric matrices.
+ byLDLH = 3, //!< Flag for the Bunch-Kaufman-based inversion for Hermitian matrices.
+ byLLH = 4 //!< Flag for the Cholesky-based inversion for positive-definite matrices.
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/LAPACK.h b/src/cpu/blaze/math/LAPACK.h
new file mode 100644
index 00000000..e54fc4a3
--- /dev/null
+++ b/src/cpu/blaze/math/LAPACK.h
@@ -0,0 +1,84 @@
+//=================================================================================================
+/*!
+// \file blaze/math/LAPACK.h
+// \brief Header file for the LAPACK functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_H_
+#define _BLAZE_MATH_LAPACK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/lapack/gelqf.h>
+#include <blaze/math/lapack/geqlf.h>
+#include <blaze/math/lapack/geqp3.h>
+#include <blaze/math/lapack/geqrf.h>
+#include <blaze/math/lapack/gerqf.h>
+#include <blaze/math/lapack/gesv.h>
+#include <blaze/math/lapack/getrf.h>
+#include <blaze/math/lapack/getri.h>
+#include <blaze/math/lapack/getrs.h>
+#include <blaze/math/lapack/hesv.h>
+#include <blaze/math/lapack/hetrf.h>
+#include <blaze/math/lapack/hetri.h>
+#include <blaze/math/lapack/hetrs.h>
+#include <blaze/math/lapack/orglq.h>
+#include <blaze/math/lapack/orgql.h>
+#include <blaze/math/lapack/orgqr.h>
+#include <blaze/math/lapack/orgrq.h>
+#include <blaze/math/lapack/ormlq.h>
+#include <blaze/math/lapack/ormql.h>
+#include <blaze/math/lapack/ormqr.h>
+#include <blaze/math/lapack/ormrq.h>
+#include <blaze/math/lapack/posv.h>
+#include <blaze/math/lapack/potrf.h>
+#include <blaze/math/lapack/potri.h>
+#include <blaze/math/lapack/potrs.h>
+#include <blaze/math/lapack/sysv.h>
+#include <blaze/math/lapack/sytrf.h>
+#include <blaze/math/lapack/sytri.h>
+#include <blaze/math/lapack/sytrs.h>
+#include <blaze/math/lapack/trsv.h>
+#include <blaze/math/lapack/trtri.h>
+#include <blaze/math/lapack/trtrs.h>
+#include <blaze/math/lapack/unglq.h>
+#include <blaze/math/lapack/ungql.h>
+#include <blaze/math/lapack/ungqr.h>
+#include <blaze/math/lapack/ungrq.h>
+#include <blaze/math/lapack/unmlq.h>
+#include <blaze/math/lapack/unmql.h>
+#include <blaze/math/lapack/unmqr.h>
+#include <blaze/math/lapack/unmrq.h>
+
+#endif
diff --git a/src/cpu/blaze/math/LowerMatrix.h b/src/cpu/blaze/math/LowerMatrix.h
new file mode 100644
index 00000000..1bafb215
--- /dev/null
+++ b/src/cpu/blaze/math/LowerMatrix.h
@@ -0,0 +1,810 @@
+//=================================================================================================
+/*!
+// \file blaze/math/LowerMatrix.h
+// \brief Header file for the complete LowerMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LOWERMATRIX_H_
+#define _BLAZE_MATH_LOWERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/LowerMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/UpperMatrix.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for LowerMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of LowerMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+class Rand< LowerMatrix<MT,SO,DF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const LowerMatrix<MT,SO,DF> generate() const;
+ inline const LowerMatrix<MT,SO,DF> generate( size_t n ) const;
+ inline const LowerMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const LowerMatrix<MT,SO,DF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const LowerMatrix<MT,SO,DF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const LowerMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( LowerMatrix<MT,SO,DF>& matrix ) const;
+ inline void randomize( LowerMatrix<MT,false,DF>& matrix, size_t nonzeros ) const;
+ inline void randomize( LowerMatrix<MT,true,DF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( LowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( LowerMatrix<MT,false,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( LowerMatrix<MT,true,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( LowerMatrix<MT,SO,DF>& matrix, TrueType ) const;
+ inline void randomize( LowerMatrix<MT,SO,DF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( LowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( LowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random LowerMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const LowerMatrix<MT,SO,DF> Rand< LowerMatrix<MT,SO,DF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ LowerMatrix<MT,SO,DF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random LowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const LowerMatrix<MT,SO,DF>
+ Rand< LowerMatrix<MT,SO,DF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ LowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random LowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const LowerMatrix<MT,SO,DF>
+ Rand< LowerMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > LowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ LowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random LowerMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const LowerMatrix<MT,SO,DF>
+ Rand< LowerMatrix<MT,SO,DF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ LowerMatrix<MT,SO,DF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random LowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const LowerMatrix<MT,SO,DF>
+ Rand< LowerMatrix<MT,SO,DF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ LowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random LowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const LowerMatrix<MT,SO,DF>
+ Rand< LowerMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > LowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ LowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,SO,DF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,SO,DF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ matrix(i,j) = rand<ET>();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,SO,DF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.3*n*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,false,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > LowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == index+1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<n; ++i ) {
+ const Indices indices( 0UL, i, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,true,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > LowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == n - index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ const Indices indices( j, n-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ matrix(i,j) = rand<ET>( min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.3*n*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,false,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > LowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == index+1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<n; ++i ) {
+ const Indices indices( 0UL, i, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< LowerMatrix<MT,SO,DF> >::randomize( LowerMatrix<MT,true,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > LowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == n - index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ const Indices indices( j, n-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeSymmetric( LowerMatrix<MT,SO,DF>& matrix )
+{
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand< ElementType_<MT> >();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeSymmetric( LowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ typedef ElementType_<MT> Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>( min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeHermitian( LowerMatrix<MT,SO,DF>& matrix )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeHermitian( LowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>( min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite LowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makePositiveDefinite( LowerMatrix<MT,SO,DF>& matrix )
+{
+ makeHermitian( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Math.h b/src/cpu/blaze/math/Math.h
new file mode 100644
index 00000000..2433dd65
--- /dev/null
+++ b/src/cpu/blaze/math/Math.h
@@ -0,0 +1,49 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Math.h
+// \brief Math module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_MATH_H_
+#define _BLAZE_MATH_MATH_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup math Math module */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/Matrix.h b/src/cpu/blaze/math/Matrix.h
new file mode 100644
index 00000000..80a53b82
--- /dev/null
+++ b/src/cpu/blaze/math/Matrix.h
@@ -0,0 +1,94 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Matrix.h
+// \brief Header file for all basic Matrix functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_MATRIX_H_
+#define _BLAZE_MATH_MATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iomanip>
+#include <ostream>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/expressions/Matrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Matrix operators */
+//@{
+template< typename MT, bool SO >
+inline std::ostream& operator<<( std::ostream& os, const Matrix<MT,SO>& m );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Global output operator for dense and sparse matrices.
+// \ingroup matrix
+//
+// \param os Reference to the output stream.
+// \param m Reference to a constant matrix object.
+// \return Reference to the output stream.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline std::ostream& operator<<( std::ostream& os, const Matrix<MT,SO>& m )
+{
+ CompositeType_<MT> tmp( ~m );
+
+ for( size_t i=0UL; i<tmp.rows(); ++i ) {
+ os << "( ";
+ for( size_t j=0UL; j<tmp.columns(); ++j ) {
+ os << std::setw(12) << tmp(i,j) << " ";
+ }
+ os << ")\n";
+ }
+
+ return os;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/PaddingFlag.h b/src/cpu/blaze/math/PaddingFlag.h
new file mode 100644
index 00000000..fee1d35f
--- /dev/null
+++ b/src/cpu/blaze/math/PaddingFlag.h
@@ -0,0 +1,91 @@
+//=================================================================================================
+/*!
+// \file blaze/math/PaddingFlag.h
+// \brief Header file for the padding flag values
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PADDINGFLAG_H_
+#define _BLAZE_MATH_PADDINGFLAG_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// PADDING FLAG VALUES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Padding flag for unpadded vectors and matrices.
+// \ingroup math
+//
+// Via this flag it is possible to specify custom vectors and matrices as unpadded. The following
+// example demonstrates the setup of an unaligned, unpadded custom row vector of size 7:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::columnVector;
+
+ std::vector<int> vec( 7UL );
+ CustomVector<int,unaligned,unpadded,columnVector> a( &vec[0], 7UL );
+ \endcode
+*/
+const bool unpadded = false;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Padding flag for padded vectors and matrices.
+// \ingroup math
+//
+// Via this flag it is possible to specify custom vectors and matrices as aligned. The following
+// example demonstrates the setup of an aligned, padded custom row vector of size 7:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::ArrayDelete;
+ using blaze::aligned;
+ using blaze::padded;
+ using blaze::columnVector;
+
+ std::vector<int> vec( 16UL );
+ CustomVector<int,unaligned,padded,columnVector> a( &vec[0], 7UL, 16UL );
+ \endcode
+*/
+const bool padded = true;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Row.h b/src/cpu/blaze/math/Row.h
new file mode 100644
index 00000000..f262fcba
--- /dev/null
+++ b/src/cpu/blaze/math/Row.h
@@ -0,0 +1,315 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Row.h
+// \brief Header file for the complete Row implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ROW_H_
+#define _BLAZE_MATH_ROW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/smp/DenseVector.h>
+#include <blaze/math/smp/SparseVector.h>
+#include <blaze/math/views/Column.h>
+#include <blaze/math/views/Row.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION FOR DENSE ROWS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for dense rows.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes dense rows.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+class Rand< Row<MT,SO,true,SF> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( Row<MT,SO,true,SF>& row ) const;
+
+ template< typename Arg >
+ inline void randomize( Row<MT,SO,true,SF>& row, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense row.
+//
+// \param row The row to be randomized.
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+inline void Rand< Row<MT,SO,true,SF> >::randomize( Row<MT,SO,true,SF>& row ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<row.size(); ++i ) {
+ randomize( row[i] );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense row.
+//
+// \param row The row to be randomized.
+// \param min The smallest possible value for a row element.
+// \param max The largest possible value for a row element.
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Row<MT,SO,true,SF> >::randomize( Row<MT,SO,true,SF>& row,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<row.size(); ++i ) {
+ randomize( row[i], min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for sparse rows.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes sparse rows.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+class Rand< Row<MT,SO,false,SF> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( Row<MT,SO,false,SF>& row ) const;
+ inline void randomize( Row<MT,SO,false,SF>& row, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( Row<MT,SO,false,SF>& row, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( Row<MT,SO,false,SF>& row, size_t nonzeros, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse row.
+//
+// \param row The row to be randomized.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+inline void Rand< Row<MT,SO,false,SF> >::randomize( Row<MT,SO,false,SF>& row ) const
+{
+ typedef ElementType_< Row<MT,SO,false,SF> > ElementType;
+
+ const size_t size( row.size() );
+
+ if( size == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*size ) ) );
+
+ row.reset();
+ row.reserve( nonzeros );
+
+ while( row.nonZeros() < nonzeros ) {
+ row[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse row.
+//
+// \param row The row to be randomized.
+// \param nonzeros The number of non-zero elements of the random row.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+inline void Rand< Row<MT,SO,false,SF> >::randomize( Row<MT,SO,false,SF>& row, size_t nonzeros ) const
+{
+ typedef ElementType_< Row<MT,SO,false,SF> > ElementType;
+
+ const size_t size( row.size() );
+
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( size == 0UL ) return;
+
+ row.reset();
+ row.reserve( nonzeros );
+
+ while( row.nonZeros() < nonzeros ) {
+ row[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse row.
+//
+// \param row The row to be randomized.
+// \param min The smallest possible value for a row element.
+// \param max The largest possible value for a row element.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Row<MT,SO,false,SF> >::randomize( Row<MT,SO,false,SF>& row,
+ const Arg& min, const Arg& max ) const
+{
+ typedef ElementType_< Row<MT,SO,false,SF> > ElementType;
+
+ const size_t size( row.size() );
+
+ if( size == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*size ) ) );
+
+ row.reset();
+ row.reserve( nonzeros );
+
+ while( row.nonZeros() < nonzeros ) {
+ row[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse row.
+//
+// \param row The row to be randomized.
+// \param nonzeros The number of non-zero elements of the random row.
+// \param min The smallest possible value for a row element.
+// \param max The largest possible value for a row element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Row<MT,SO,false,SF> >::randomize( Row<MT,SO,false,SF>& row, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ typedef ElementType_< Row<MT,SO,false,SF> > ElementType;
+
+ const size_t size( row.size() );
+
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( size == 0UL ) return;
+
+ row.reset();
+ row.reserve( nonzeros );
+
+ while( row.nonZeros() < nonzeros ) {
+ row[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/SIMD.h b/src/cpu/blaze/math/SIMD.h
new file mode 100644
index 00000000..45ad0182
--- /dev/null
+++ b/src/cpu/blaze/math/SIMD.h
@@ -0,0 +1,48 @@
+//=================================================================================================
+/*!
+// \file blaze/math/SIMD.h
+// \brief Header file for all SIMD functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_H_
+#define _BLAZE_MATH_SIMD_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/math/simd/DerivedTypes.h>
+#include <blaze/math/simd/Functions.h>
+#include <blaze/math/simd/SIMDTrait.h>
+
+#endif
diff --git a/src/cpu/blaze/math/SMP.h b/src/cpu/blaze/math/SMP.h
new file mode 100644
index 00000000..4400a358
--- /dev/null
+++ b/src/cpu/blaze/math/SMP.h
@@ -0,0 +1,50 @@
+//=================================================================================================
+/*!
+// \file blaze/math/SMP.h
+// \brief Header file for the shared memory parallelization
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_H_
+#define _BLAZE_MATH_SMP_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/smp/DenseMatrix.h>
+#include <blaze/math/smp/DenseVector.h>
+#include <blaze/math/smp/Functions.h>
+#include <blaze/math/smp/SerialSection.h>
+#include <blaze/math/smp/SparseMatrix.h>
+#include <blaze/math/smp/SparseVector.h>
+
+#endif
diff --git a/src/cpu/blaze/math/Serialization.h b/src/cpu/blaze/math/Serialization.h
new file mode 100644
index 00000000..8e4592d4
--- /dev/null
+++ b/src/cpu/blaze/math/Serialization.h
@@ -0,0 +1,47 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Serialization.h
+// \brief Header file for the serialization functionality for vectors and matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SERIALIZATION_H_
+#define _BLAZE_MATH_SERIALIZATION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/serialization/MatrixSerializer.h>
+#include <blaze/math/serialization/TypeValueMapping.h>
+#include <blaze/math/serialization/VectorSerializer.h>
+
+#endif
diff --git a/src/cpu/blaze/math/Shims.h b/src/cpu/blaze/math/Shims.h
new file mode 100644
index 00000000..37bd3fb4
--- /dev/null
+++ b/src/cpu/blaze/math/Shims.h
@@ -0,0 +1,84 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Shims.h
+// \brief Header file for the mathematical shims
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_H_
+#define _BLAZE_MATH_SHIMS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Abs.h>
+#include <blaze/math/shims/Acos.h>
+#include <blaze/math/shims/Acosh.h>
+#include <blaze/math/shims/Asin.h>
+#include <blaze/math/shims/Asinh.h>
+#include <blaze/math/shims/Atan.h>
+#include <blaze/math/shims/Atanh.h>
+#include <blaze/math/shims/Cbrt.h>
+#include <blaze/math/shims/Ceil.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Cos.h>
+#include <blaze/math/shims/Cosh.h>
+#include <blaze/math/shims/Equal.h>
+#include <blaze/math/shims/Erf.h>
+#include <blaze/math/shims/Erfc.h>
+#include <blaze/math/shims/Exp.h>
+#include <blaze/math/shims/Floor.h>
+#include <blaze/math/shims/Imaginary.h>
+#include <blaze/math/shims/InvCbrt.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/InvSqrt.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsDivisor.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Log.h>
+#include <blaze/math/shims/Log10.h>
+#include <blaze/math/shims/Pow.h>
+#include <blaze/math/shims/Real.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/shims/Sin.h>
+#include <blaze/math/shims/Sinh.h>
+#include <blaze/math/shims/Sqrt.h>
+#include <blaze/math/shims/Square.h>
+#include <blaze/math/shims/Tan.h>
+#include <blaze/math/shims/Tanh.h>
+
+#endif
diff --git a/src/cpu/blaze/math/SparseMatrix.h b/src/cpu/blaze/math/SparseMatrix.h
new file mode 100644
index 00000000..badddbd3
--- /dev/null
+++ b/src/cpu/blaze/math/SparseMatrix.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/math/SparseMatrix.h
+// \brief Header file for all basic SparseMatrix functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSEMATRIX_H_
+#define _BLAZE_MATH_SPARSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DVecTSVecMultExpr.h>
+#include <blaze/math/expressions/SMatDVecMultExpr.h>
+#include <blaze/math/expressions/SMatEvalExpr.h>
+#include <blaze/math/expressions/SMatForEachExpr.h>
+#include <blaze/math/expressions/SMatScalarDivExpr.h>
+#include <blaze/math/expressions/SMatScalarMultExpr.h>
+#include <blaze/math/expressions/SMatSerialExpr.h>
+#include <blaze/math/expressions/SMatSMatAddExpr.h>
+#include <blaze/math/expressions/SMatSMatMultExpr.h>
+#include <blaze/math/expressions/SMatSMatSubExpr.h>
+#include <blaze/math/expressions/SMatSVecMultExpr.h>
+#include <blaze/math/expressions/SMatTransExpr.h>
+#include <blaze/math/expressions/SMatTSMatAddExpr.h>
+#include <blaze/math/expressions/SMatTSMatMultExpr.h>
+#include <blaze/math/expressions/SMatTSMatSubExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/SVecTDVecMultExpr.h>
+#include <blaze/math/expressions/SVecTSVecMultExpr.h>
+#include <blaze/math/expressions/TDVecSMatMultExpr.h>
+#include <blaze/math/expressions/TDVecTSMatMultExpr.h>
+#include <blaze/math/expressions/TSMatDVecMultExpr.h>
+#include <blaze/math/expressions/TSMatSMatMultExpr.h>
+#include <blaze/math/expressions/TSMatSMatSubExpr.h>
+#include <blaze/math/expressions/TSMatSVecMultExpr.h>
+#include <blaze/math/expressions/TSMatTSMatAddExpr.h>
+#include <blaze/math/expressions/TSMatTSMatMultExpr.h>
+#include <blaze/math/expressions/TSMatTSMatSubExpr.h>
+#include <blaze/math/expressions/TSVecSMatMultExpr.h>
+#include <blaze/math/expressions/TSVecTSMatMultExpr.h>
+#include <blaze/math/Matrix.h>
+#include <blaze/math/smp/DenseMatrix.h>
+#include <blaze/math/smp/SparseMatrix.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/views/Column.h>
+#include <blaze/math/views/Row.h>
+#include <blaze/math/views/Submatrix.h>
+
+#endif
diff --git a/src/cpu/blaze/math/SparseVector.h b/src/cpu/blaze/math/SparseVector.h
new file mode 100644
index 00000000..b99a6d30
--- /dev/null
+++ b/src/cpu/blaze/math/SparseVector.h
@@ -0,0 +1,66 @@
+//=================================================================================================
+/*!
+// \file blaze/math/SparseVector.h
+// \brief Header file for all basic SparseVector functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSEVECTOR_H_
+#define _BLAZE_MATH_SPARSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/DVecSVecMultExpr.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/SVecDVecDivExpr.h>
+#include <blaze/math/expressions/SVecDVecMultExpr.h>
+#include <blaze/math/expressions/SVecEvalExpr.h>
+#include <blaze/math/expressions/SVecForEachExpr.h>
+#include <blaze/math/expressions/SVecScalarDivExpr.h>
+#include <blaze/math/expressions/SVecScalarMultExpr.h>
+#include <blaze/math/expressions/SVecSerialExpr.h>
+#include <blaze/math/expressions/SVecSVecAddExpr.h>
+#include <blaze/math/expressions/SVecSVecMultExpr.h>
+#include <blaze/math/expressions/SVecSVecSubExpr.h>
+#include <blaze/math/expressions/SVecTransExpr.h>
+#include <blaze/math/expressions/TDVecSVecMultExpr.h>
+#include <blaze/math/expressions/TSVecSVecMultExpr.h>
+#include <blaze/math/expressions/TSVecDVecMultExpr.h>
+#include <blaze/math/smp/DenseVector.h>
+#include <blaze/math/smp/SparseVector.h>
+#include <blaze/math/sparse/SparseVector.h>
+#include <blaze/math/Vector.h>
+#include <blaze/math/views/Subvector.h>
+
+#endif
diff --git a/src/cpu/blaze/math/StaticMatrix.h b/src/cpu/blaze/math/StaticMatrix.h
new file mode 100644
index 00000000..9e052647
--- /dev/null
+++ b/src/cpu/blaze/math/StaticMatrix.h
@@ -0,0 +1,382 @@
+//=================================================================================================
+/*!
+// \file blaze/math/StaticMatrix.h
+// \brief Header file for the complete StaticMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_STATICMATRIX_H_
+#define _BLAZE_MATH_STATICMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/StaticMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/HybridMatrix.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Real.h>
+#include <blaze/math/StaticVector.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/system/Precision.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for StaticMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of StaticMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+class Rand< StaticMatrix<Type,M,N,SO> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const StaticMatrix<Type,M,N,SO> generate() const;
+
+ template< typename Arg >
+ inline const StaticMatrix<Type,M,N,SO> generate( const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( StaticMatrix<Type,M,N,SO>& matrix ) const;
+
+ template< typename Arg >
+ inline void randomize( StaticMatrix<Type,M,N,SO>& matrix, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StaticMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline const StaticMatrix<Type,M,N,SO> Rand< StaticMatrix<Type,M,N,SO> >::generate() const
+{
+ StaticMatrix<Type,M,N,SO> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StaticMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline const StaticMatrix<Type,M,N,SO>
+ Rand< StaticMatrix<Type,M,N,SO> >::generate( const Arg& min, const Arg& max ) const
+{
+ StaticMatrix<Type,M,N,SO> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a StaticMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void Rand< StaticMatrix<Type,M,N,SO> >::randomize( StaticMatrix<Type,M,N,SO>& matrix ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ randomize( matrix(i,j) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a StaticMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< StaticMatrix<Type,M,N,SO> >::randomize( StaticMatrix<Type,M,N,SO>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ randomize( matrix(i,j), min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric StaticMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+void makeSymmetric( StaticMatrix<Type,M,N,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_STATIC_ASSERT( M == N );
+
+ for( size_t i=0UL; i<N; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j) );
+ matrix(j,i) = matrix(i,j);
+ }
+ randomize( matrix(i,i) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric StaticMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO // Storage order
+ , typename Arg > // Min/max argument type
+void makeSymmetric( StaticMatrix<Type,M,N,SO>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ BLAZE_STATIC_ASSERT( M == N );
+
+ for( size_t i=0UL; i<N; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j), min, max );
+ matrix(j,i) = matrix(i,j);
+ }
+ randomize( matrix(i,i), min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian StaticMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+void makeHermitian( StaticMatrix<Type,M,N,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_STATIC_ASSERT( M == N );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ typedef UnderlyingBuiltin_<Type> BT;
+
+ for( size_t i=0UL; i<N; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j) );
+ matrix(j,i) = conj( matrix(i,j) );
+ }
+ matrix(i,i) = rand<BT>();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian StaticMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO // Storage order
+ , typename Arg > // Min/max argument type
+void makeHermitian( StaticMatrix<Type,M,N,SO>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ BLAZE_STATIC_ASSERT( M == N );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ typedef UnderlyingBuiltin_<Type> BT;
+
+ for( size_t i=0UL; i<N; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ randomize( matrix(i,j), min, max );
+ matrix(j,i) = conj( matrix(i,j) );
+ }
+ matrix(i,i) = rand<BT>( real( min ), real( max ) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite StaticMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+void makePositiveDefinite( StaticMatrix<Type,M,N,SO>& matrix )
+{
+ using blaze::randomize;
+
+ BLAZE_STATIC_ASSERT( M == N );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type );
+
+ randomize( matrix );
+ matrix *= ctrans( matrix );
+
+ for( size_t i=0UL; i<N; ++i ) {
+ matrix(i,i) += Type(N);
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/StaticVector.h b/src/cpu/blaze/math/StaticVector.h
new file mode 100644
index 00000000..aa017bae
--- /dev/null
+++ b/src/cpu/blaze/math/StaticVector.h
@@ -0,0 +1,187 @@
+//=================================================================================================
+/*!
+// \file blaze/math/StaticVector.h
+// \brief Header file for the complete StaticVector implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_STATICVECTOR_H_
+#define _BLAZE_MATH_STATICVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/dense/StaticVector.h>
+#include <blaze/math/DenseVector.h>
+#include <blaze/math/DynamicVector.h>
+#include <blaze/math/StaticMatrix.h>
+#include <blaze/system/Precision.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for StaticVector.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of StaticVector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+class Rand< StaticVector<Type,N,TF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const StaticVector<Type,N,TF> generate() const;
+
+ template< typename Arg >
+ inline const StaticVector<Type,N,TF> generate( const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( StaticVector<Type,N,TF>& vector ) const;
+
+ template< typename Arg >
+ inline void randomize( StaticVector<Type,N,TF>& vector, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StaticVector.
+//
+// \return The generated random vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline const StaticVector<Type,N,TF> Rand< StaticVector<Type,N,TF> >::generate() const
+{
+ StaticVector<Type,N,TF> vector;
+ randomize( vector );
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StaticVector.
+//
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return The generated random vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline const StaticVector<Type,N,TF>
+ Rand< StaticVector<Type,N,TF> >::generate( const Arg& min, const Arg& max ) const
+{
+ StaticVector<Type,N,TF> vector;
+ randomize( vector, min, max );
+ return vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a StaticVector.
+//
+// \param vector The vector to be randomized.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void Rand< StaticVector<Type,N,TF> >::randomize( StaticVector<Type,N,TF>& vector ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<N; ++i ) {
+ randomize( vector[i] );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a StaticVector.
+//
+// \param vector The vector to be randomized.
+// \param min The smallest possible value for a vector element.
+// \param max The largest possible value for a vector element.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StaticVector<Type,N,TF> >::randomize( StaticVector<Type,N,TF>& vector,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<N; ++i ) {
+ randomize( vector[i], min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/StorageOrder.h b/src/cpu/blaze/math/StorageOrder.h
new file mode 100644
index 00000000..96da06e8
--- /dev/null
+++ b/src/cpu/blaze/math/StorageOrder.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/StorageOrder.h
+// \brief Header file for the matrix storage order types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_STORAGEORDER_H_
+#define _BLAZE_MATH_STORAGEORDER_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MATRIX STORAGE ORDER TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Storage order flag for row-major matrices.
+//
+// Via this flag it is possible to specify the storage order of matrices as row-major. For
+// instance, given the following matrix
+
+ \f[\left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 4 & 5 & 6 \\
+ \end{array}\right)\f]\n
+
+// in case of row-major order the elements are stored in the order
+
+ \f[\left(\begin{array}{*{6}{c}}
+ 1 & 2 & 3 & 4 & 5 & 6. \\
+ \end{array}\right)\f]
+
+// The following example demonstrates the setup of this \f$ 2 \times 3 \f$ matrix:
+
+ \code
+ using blaze::rowMajor;
+ blaze::StaticMatrix<int,2UL,3UL,rowMajor> A( { { 1, 2, 3 }, { 4, 5, 6 } } );
+ \endcode
+*/
+const bool rowMajor = false;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Storage order flag for column-major matrices.
+//
+// Via this flag it is possible to specify the storage order of matrices as column-major. For
+// instance, given the following matrix
+
+ \f[\left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 4 & 5 & 6 \\
+ \end{array}\right)\f]\n
+
+// in case of column-major order the elements are stored in the order
+
+ \f[\left(\begin{array}{*{6}{c}}
+ 1 & 4 & 2 & 5 & 3 & 6. \\
+ \end{array}\right)\f]
+
+// The following example demonstrates the setup of this \f$ 2 \times 3 \f$ matrix:
+
+ \code
+ using blaze::columnMajor;
+ blaze::StaticMatrix<int,2UL,3UL,columnMajor> A( { { 1, 2, 3 }, { 4, 5, 6 } } );
+ \endcode
+*/
+const bool columnMajor = true;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/StrictlyLowerMatrix.h b/src/cpu/blaze/math/StrictlyLowerMatrix.h
new file mode 100644
index 00000000..b5227471
--- /dev/null
+++ b/src/cpu/blaze/math/StrictlyLowerMatrix.h
@@ -0,0 +1,673 @@
+//=================================================================================================
+/*!
+// \file blaze/math/StrictlyLowerMatrix.h
+// \brief Header file for the complete StrictlyLowerMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_STRICTLYLOWERMATRIX_H_
+#define _BLAZE_MATH_STRICTLYLOWERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/StrictlyLowerMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/StrictlyUpperMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for StrictlyLowerMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of StrictlyLowerMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+class Rand< StrictlyLowerMatrix<MT,SO,DF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const StrictlyLowerMatrix<MT,SO,DF> generate() const;
+ inline const StrictlyLowerMatrix<MT,SO,DF> generate( size_t n ) const;
+ inline const StrictlyLowerMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const StrictlyLowerMatrix<MT,SO,DF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const StrictlyLowerMatrix<MT,SO,DF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const StrictlyLowerMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix ) const;
+ inline void randomize( StrictlyLowerMatrix<MT,false,DF>& matrix, size_t nonzeros ) const;
+ inline void randomize( StrictlyLowerMatrix<MT,true,DF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyLowerMatrix<MT,false,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyLowerMatrix<MT,true,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix, TrueType ) const;
+ inline void randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyLowerMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const StrictlyLowerMatrix<MT,SO,DF> Rand< StrictlyLowerMatrix<MT,SO,DF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ StrictlyLowerMatrix<MT,SO,DF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyLowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const StrictlyLowerMatrix<MT,SO,DF>
+ Rand< StrictlyLowerMatrix<MT,SO,DF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ StrictlyLowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyLowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const StrictlyLowerMatrix<MT,SO,DF>
+ Rand< StrictlyLowerMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > StrictlyLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ StrictlyLowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyLowerMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const StrictlyLowerMatrix<MT,SO,DF>
+ Rand< StrictlyLowerMatrix<MT,SO,DF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ StrictlyLowerMatrix<MT,SO,DF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyLowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const StrictlyLowerMatrix<MT,SO,DF>
+ Rand< StrictlyLowerMatrix<MT,SO,DF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ StrictlyLowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyLowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const StrictlyLowerMatrix<MT,SO,DF>
+ Rand< StrictlyLowerMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > StrictlyLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ StrictlyLowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=1UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ matrix(i,j) = rand<ET>();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL || n == 1UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.2*n*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,false,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > StrictlyLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+ matrix.finalize( 0UL );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 1UL, n-1UL );
+ if( dist[index] == index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=1UL; i<n; ++i ) {
+ const Indices indices( 0UL, i-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,true,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > StrictlyLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n-1UL );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-2UL );
+ if( dist[index] == n - index - 1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n-1UL; ++j ) {
+ const Indices indices( j+1UL, n-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( j );
+ }
+
+ matrix.finalize( n-1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=1UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ matrix(i,j) = rand<ET>( min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL || n == 1UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.2*n*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,false,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > StrictlyLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+ matrix.finalize( 0UL );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 1UL, n-1UL );
+ if( dist[index] == index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=1UL; i<n; ++i ) {
+ const Indices indices( 0UL, i-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse StrictlyLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyLowerMatrix<MT,SO,DF> >::randomize( StrictlyLowerMatrix<MT,true,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > StrictlyLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n-1UL );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-2UL );
+ if( dist[index] == n - index - 1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n-1UL; ++j ) {
+ const Indices indices( j+1UL, n-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( j );
+ }
+
+ matrix.finalize( n-1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/StrictlyUpperMatrix.h b/src/cpu/blaze/math/StrictlyUpperMatrix.h
new file mode 100644
index 00000000..9fa3d163
--- /dev/null
+++ b/src/cpu/blaze/math/StrictlyUpperMatrix.h
@@ -0,0 +1,673 @@
+//=================================================================================================
+/*!
+// \file blaze/math/StrictlyUpperMatrix.h
+// \brief Header file for the complete StrictlyUpperMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_STRICTLYUPPERMATRIX_H_
+#define _BLAZE_MATH_STRICTLYUPPERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/StrictlyUpperMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/StrictlyLowerMatrix.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for StrictlyUpperMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of StrictlyUpperMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+class Rand< StrictlyUpperMatrix<MT,SO,DF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const StrictlyUpperMatrix<MT,SO,DF> generate() const;
+ inline const StrictlyUpperMatrix<MT,SO,DF> generate( size_t n ) const;
+ inline const StrictlyUpperMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const StrictlyUpperMatrix<MT,SO,DF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const StrictlyUpperMatrix<MT,SO,DF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const StrictlyUpperMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix ) const;
+ inline void randomize( StrictlyUpperMatrix<MT,false,DF>& matrix, size_t nonzeros ) const;
+ inline void randomize( StrictlyUpperMatrix<MT,true,DF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyUpperMatrix<MT,false,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyUpperMatrix<MT,true,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix, TrueType ) const;
+ inline void randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyUpperMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const StrictlyUpperMatrix<MT,SO,DF> Rand< StrictlyUpperMatrix<MT,SO,DF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ StrictlyUpperMatrix<MT,SO,DF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyUpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const StrictlyUpperMatrix<MT,SO,DF>
+ Rand< StrictlyUpperMatrix<MT,SO,DF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ StrictlyUpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyUpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const StrictlyUpperMatrix<MT,SO,DF>
+ Rand< StrictlyUpperMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > StrictlyUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ StrictlyUpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyUpperMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const StrictlyUpperMatrix<MT,SO,DF>
+ Rand< StrictlyUpperMatrix<MT,SO,DF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ StrictlyUpperMatrix<MT,SO,DF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyUpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const StrictlyUpperMatrix<MT,SO,DF>
+ Rand< StrictlyUpperMatrix<MT,SO,DF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ StrictlyUpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random StrictlyUpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const StrictlyUpperMatrix<MT,SO,DF>
+ Rand< StrictlyUpperMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > StrictlyUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ StrictlyUpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=i+1UL; j<n; ++j ) {
+ matrix(i,j) = rand<ET>();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL || n == 1UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.2*n*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,false,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > StrictlyUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n-1UL );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-2UL );
+ if( dist[index] == n - index - 1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<n-1UL; ++i ) {
+ const Indices indices( i+1UL, n-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( i );
+ }
+
+ matrix.finalize( n-1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,true,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > StrictlyUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+ matrix.finalize( 0UL );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 1UL, n-1UL );
+ if( dist[index] == index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=1UL; j<n; ++j ) {
+ const Indices indices( 0UL, j-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=i+1UL; j<n; ++j ) {
+ matrix(i,j) = rand<ET>( min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL || n == 1UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.2*n*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,false,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > StrictlyUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n-1UL );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-2UL );
+ if( dist[index] == n - index - 1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<n-1UL; ++i ) {
+ const Indices indices( i+1UL, n-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( i );
+ }
+
+ matrix.finalize( n-1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse StrictlyUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< StrictlyUpperMatrix<MT,SO,DF> >::randomize( StrictlyUpperMatrix<MT,true,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > StrictlyUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+ matrix.finalize( 0UL );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 1UL, n-1UL );
+ if( dist[index] == index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=1UL; j<n; ++j ) {
+ const Indices indices( 0UL, j-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Submatrix.h b/src/cpu/blaze/math/Submatrix.h
new file mode 100644
index 00000000..57836872
--- /dev/null
+++ b/src/cpu/blaze/math/Submatrix.h
@@ -0,0 +1,342 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Submatrix.h
+// \brief Header file for the complete Submatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SUBMATRIX_H_
+#define _BLAZE_MATH_SUBMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/smp/DenseMatrix.h>
+#include <blaze/math/smp/SparseMatrix.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/math/views/Subvector.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION FOR DENSE SUBMATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for dense submatrices.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes dense submatrices.
+*/
+template< typename MT // Type of the dense matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+class Rand< Submatrix<MT,AF,SO,true> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( Submatrix<MT,AF,SO,true>& submatrix ) const;
+
+ template< typename Arg >
+ inline void randomize( Submatrix<MT,AF,SO,true>& submatrix, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense submatrix.
+//
+// \param submatrix The submatrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+inline void Rand< Submatrix<MT,AF,SO,true> >::randomize( Submatrix<MT,AF,SO,true>& submatrix ) const
+{
+ using blaze::randomize;
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<submatrix.rows(); ++i ) {
+ for( size_t j=0UL; j<submatrix.columns(); ++j ) {
+ randomize( submatrix(i,j) );
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<submatrix.columns(); ++j ) {
+ for( size_t i=0UL; i<submatrix.rows(); ++i ) {
+ randomize( submatrix(i,j) );
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense submatrix.
+//
+// \param submatrix The submatrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< Submatrix<MT,AF,SO,true> >::randomize( Submatrix<MT,AF,SO,true>& submatrix,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<submatrix.rows(); ++i ) {
+ for( size_t j=0UL; j<submatrix.columns(); ++j ) {
+ randomize( submatrix(i,j), min, max );
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<submatrix.columns(); ++j ) {
+ for( size_t i=0UL; i<submatrix.rows(); ++i ) {
+ randomize( submatrix(i,j), min, max );
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION FOR SPARSE SUBMATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for sparse submatrices.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes sparse submatrices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+class Rand< Submatrix<MT,AF,SO,false> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( Submatrix<MT,AF,SO,false>& submatrix ) const;
+ inline void randomize( Submatrix<MT,AF,SO,false>& submatrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( Submatrix<MT,AF,SO,false>& submatrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( Submatrix<MT,AF,SO,false>& submatrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse submatrix.
+//
+// \param submatrix The submatrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+inline void Rand< Submatrix<MT,AF,SO,false> >::randomize( Submatrix<MT,AF,SO,false>& submatrix ) const
+{
+ typedef ElementType_< Submatrix<MT,AF,SO,false> > ElementType;
+
+ const size_t m( submatrix.rows() );
+ const size_t n( submatrix.columns() );
+
+ if( m == 0UL || n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*m*n ) ) );
+
+ submatrix.reset();
+ submatrix.reserve( nonzeros );
+
+ while( submatrix.nonZeros() < nonzeros ) {
+ submatrix( rand<size_t>( 0UL, m-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ElementType>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse submatrix.
+//
+// \param submatrix The submatrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random submatrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+inline void Rand< Submatrix<MT,AF,SO,false> >::randomize( Submatrix<MT,AF,SO,false>& submatrix, size_t nonzeros ) const
+{
+ typedef ElementType_< Submatrix<MT,AF,SO,false> > ElementType;
+
+ const size_t m( submatrix.rows() );
+ const size_t n( submatrix.columns() );
+
+ if( nonzeros > m*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( m == 0UL || n == 0UL ) return;
+
+ submatrix.reset();
+ submatrix.reserve( nonzeros );
+
+ while( submatrix.nonZeros() < nonzeros ) {
+ submatrix( rand<size_t>( 0UL, m-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ElementType>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse submatrix.
+//
+// \param submatrix The submatrix to be randomized.
+// \param min The smallest possible value for a submatrix element.
+// \param max The largest possible value for a submatrix element.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< Submatrix<MT,AF,SO,false> >::randomize( Submatrix<MT,AF,SO,false>& submatrix,
+ const Arg& min, const Arg& max ) const
+{
+ typedef ElementType_< Submatrix<MT,AF,SO,false> > ElementType;
+
+ const size_t m( submatrix.rows() );
+ const size_t n( submatrix.columns() );
+
+ if( m == 0UL || n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*m*n ) ) );
+
+ submatrix.reset();
+ submatrix.reserve( nonzeros );
+
+ while( submatrix.nonZeros() < nonzeros ) {
+ submatrix( rand<size_t>( 0UL, m-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ElementType>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse submatrix.
+//
+// \param submatrix The submatrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random submatrix.
+// \param min The smallest possible value for a submatrix element.
+// \param max The largest possible value for a submatrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+template< typename Arg > // Min/max argument type
+inline void Rand< Submatrix<MT,AF,SO,false> >::randomize( Submatrix<MT,AF,SO,false>& submatrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ typedef ElementType_< Submatrix<MT,AF,SO,false> > ElementType;
+
+ const size_t m( submatrix.rows() );
+ const size_t n( submatrix.columns() );
+
+ if( nonzeros > m*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( m == 0UL || n == 0UL ) return;
+
+ submatrix.reset();
+ submatrix.reserve( nonzeros );
+
+ while( submatrix.nonZeros() < nonzeros ) {
+ submatrix( rand<size_t>( 0UL, m-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ElementType>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Subvector.h b/src/cpu/blaze/math/Subvector.h
new file mode 100644
index 00000000..7a41a72c
--- /dev/null
+++ b/src/cpu/blaze/math/Subvector.h
@@ -0,0 +1,315 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Subvector.h
+// \brief Header file for the complete Subvector implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSESUBVECTOR_H_
+#define _BLAZE_MATH_DENSESUBVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/smp/DenseVector.h>
+#include <blaze/math/smp/SparseVector.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/math/views/Subvector.h>
+#include <blaze/util/Random.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION FOR DENSE SUBVECTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for dense subvectors.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes dense subvectors.
+*/
+template< typename VT // Type of the dense vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+class Rand< Subvector<VT,AF,TF,true> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( Subvector<VT,AF,TF,true>& subvector ) const;
+
+ template< typename Arg >
+ inline void randomize( Subvector<VT,AF,TF,true>& subvector, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense subvector.
+//
+// \param subvector The subvector to be randomized.
+// \return void
+*/
+template< typename VT // Type of the dense vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void Rand< Subvector<VT,AF,TF,true> >::randomize( Subvector<VT,AF,TF,true>& subvector ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<subvector.size(); ++i ) {
+ randomize( subvector[i] );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense subvector.
+//
+// \param subvector The subvector to be randomized.
+// \param min The smallest possible value for a subvector element.
+// \param max The largest possible value for a subvector element.
+// \return void
+*/
+template< typename VT // Type of the dense vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Subvector<VT,AF,TF,true> >::randomize( Subvector<VT,AF,TF,true>& subvector,
+ const Arg& min, const Arg& max ) const
+{
+ using blaze::randomize;
+
+ for( size_t i=0UL; i<subvector.size(); ++i ) {
+ randomize( subvector[i], min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION FOR SPARSE SUBVECTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for sparse subvectors.
+// \ingroup random
+//
+// This specialization of the Rand class randomizes sparse subvectors.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+class Rand< Subvector<VT,AF,TF,false> >
+{
+ public:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( Subvector<VT,AF,TF,false>& subvector ) const;
+ inline void randomize( Subvector<VT,AF,TF,false>& subvector, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( Subvector<VT,AF,TF,false>& subvector, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( Subvector<VT,AF,TF,false>& subvector, size_t nonzeros, const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse subvector.
+//
+// \param subvector The subvector to be randomized.
+// \return void
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void Rand< Subvector<VT,AF,TF,false> >::randomize( Subvector<VT,AF,TF,false>& subvector ) const
+{
+ typedef ElementType_< Subvector<VT,AF,TF,false> > ElementType;
+
+ const size_t size( subvector.size() );
+
+ if( size == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*size ) ) );
+
+ subvector.reset();
+ subvector.reserve( nonzeros );
+
+ while( subvector.nonZeros() < nonzeros ) {
+ subvector[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse subvector.
+//
+// \param subvector The subvector to be randomized.
+// \param nonzeros The number of non-zero elements of the random subvector.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void Rand< Subvector<VT,AF,TF,false> >::randomize( Subvector<VT,AF,TF,false>& subvector, size_t nonzeros ) const
+{
+ typedef ElementType_< Subvector<VT,AF,TF,false> > ElementType;
+
+ const size_t size( subvector.size() );
+
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( size == 0UL ) return;
+
+ subvector.reset();
+ subvector.reserve( nonzeros );
+
+ while( subvector.nonZeros() < nonzeros ) {
+ subvector[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse subvector.
+//
+// \param subvector The subvector to be randomized.
+// \param min The smallest possible value for a subvector element.
+// \param max The largest possible value for a subvector element.
+// \return void
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Subvector<VT,AF,TF,false> >::randomize( Subvector<VT,AF,TF,false>& subvector,
+ const Arg& min, const Arg& max ) const
+{
+ typedef ElementType_< Subvector<VT,AF,TF,false> > ElementType;
+
+ const size_t size( subvector.size() );
+
+ if( size == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*size ) ) );
+
+ subvector.reset();
+ subvector.reserve( nonzeros );
+
+ while( subvector.nonZeros() < nonzeros ) {
+ subvector[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse subvector.
+//
+// \param subvector The subvector to be randomized.
+// \param nonzeros The number of non-zero elements of the random subvector.
+// \param min The smallest possible value for a subvector element.
+// \param max The largest possible value for a subvector element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Arg > // Min/max argument type
+inline void Rand< Subvector<VT,AF,TF,false> >::randomize( Subvector<VT,AF,TF,false>& subvector,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ typedef ElementType_< Subvector<VT,AF,TF,false> > ElementType;
+
+ const size_t size( subvector.size() );
+
+ if( nonzeros > size ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( size == 0UL ) return;
+
+ subvector.reset();
+ subvector.reserve( nonzeros );
+
+ while( subvector.nonZeros() < nonzeros ) {
+ subvector[ rand<size_t>( 0UL, size-1UL ) ] = rand<ElementType>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/SymmetricMatrix.h b/src/cpu/blaze/math/SymmetricMatrix.h
new file mode 100644
index 00000000..5ef7e4d5
--- /dev/null
+++ b/src/cpu/blaze/math/SymmetricMatrix.h
@@ -0,0 +1,686 @@
+//=================================================================================================
+/*!
+// \file blaze/math/SymmetricMatrix.h
+// \brief Header file for the complete SymmetricMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SYMMETRICMATRIX_H_
+#define _BLAZE_MATH_SYMMETRICMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/SymmetricMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/shims/Real.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for SymmetricMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of SymmetricMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+class Rand< SymmetricMatrix<MT,SO,DF,NF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const SymmetricMatrix<MT,SO,DF,NF> generate() const;
+ inline const SymmetricMatrix<MT,SO,DF,NF> generate( size_t n ) const;
+ inline const SymmetricMatrix<MT,SO,DF,NF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const SymmetricMatrix<MT,SO,DF,NF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const SymmetricMatrix<MT,SO,DF,NF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const SymmetricMatrix<MT,SO,DF,NF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix ) const;
+ inline void randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, TrueType ) const;
+ inline void randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random SymmetricMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline const SymmetricMatrix<MT,SO,DF,NF> Rand< SymmetricMatrix<MT,SO,DF,NF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ SymmetricMatrix<MT,SO,DF,NF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random SymmetricMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline const SymmetricMatrix<MT,SO,DF,NF>
+ Rand< SymmetricMatrix<MT,SO,DF,NF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ SymmetricMatrix<MT,SO,DF,NF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random SymmetricMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline const SymmetricMatrix<MT,SO,DF,NF>
+ Rand< SymmetricMatrix<MT,SO,DF,NF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > n*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ SymmetricMatrix<MT,SO,DF,NF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random SymmetricMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const SymmetricMatrix<MT,SO,DF,NF>
+ Rand< SymmetricMatrix<MT,SO,DF,NF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ SymmetricMatrix<MT,SO,DF,NF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random SymmetricMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const SymmetricMatrix<MT,SO,DF,NF>
+ Rand< SymmetricMatrix<MT,SO,DF,NF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ SymmetricMatrix<MT,SO,DF,NF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random SymmetricMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const SymmetricMatrix<MT,SO,DF,NF>
+ Rand< SymmetricMatrix<MT,SO,DF,NF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > n*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ SymmetricMatrix<MT,SO,DF,NF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline void Rand< SymmetricMatrix<MT,SO,DF,NF> >::randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline void Rand< SymmetricMatrix<MT,SO,DF,NF> >::randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ matrix(i,j) = rand<ET>();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline void Rand< SymmetricMatrix<MT,SO,DF,NF> >::randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*n*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline void Rand< SymmetricMatrix<MT,SO,DF,NF> >::randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > n*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros+1UL );
+
+ while( matrix.nonZeros() < nonzeros ) {
+ matrix( rand<size_t>( 0UL, n-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ET>();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< SymmetricMatrix<MT,SO,DF,NF> >::randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< SymmetricMatrix<MT,SO,DF,NF> >::randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ matrix(i,j) = rand<ET>( min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< SymmetricMatrix<MT,SO,DF,NF> >::randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*n*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< SymmetricMatrix<MT,SO,DF,NF> >::randomize( SymmetricMatrix<MT,SO,DF,NF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > n*n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros+1UL );
+
+ while( matrix.nonZeros() < nonzeros ) {
+ matrix( rand<size_t>( 0UL, n-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ET>( min, max );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool NF > // Numeric flag
+void makeSymmetric( SymmetricMatrix<MT,SO,true,NF>& matrix )
+{
+ using blaze::randomize;
+
+ randomize( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool NF // Numeric flag
+ , typename Arg > // Min/max argument type
+void makeSymmetric( SymmetricMatrix<MT,SO,true,NF>& matrix, const Arg& min, const Arg& max )
+{
+ using blaze::randomize;
+
+ randomize( matrix, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool NF > // Numeric flag
+void makeHermitian( SymmetricMatrix<MT,SO,true,NF>& matrix )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > BT;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ matrix(i,j) = rand<BT>();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool NF // Numeric flag
+ , typename Arg > // Min/max argument type
+void makeHermitian( SymmetricMatrix<MT,SO,true,NF>& matrix, const Arg& min, const Arg& max )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > BT;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ matrix(i,j) = rand<BT>( real( min ), real( max ) );
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite SymmetricMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool NF > // Numeric flag
+void makePositiveDefinite( SymmetricMatrix<MT,SO,true,NF>& matrix )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > BT;
+
+ const size_t n( matrix.rows() );
+
+ makeHermitian( matrix );
+ matrix *= matrix;
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) += BT(n);
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Traits.h b/src/cpu/blaze/math/Traits.h
new file mode 100644
index 00000000..35604469
--- /dev/null
+++ b/src/cpu/blaze/math/Traits.h
@@ -0,0 +1,235 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Traits.h
+// \brief Header file for all expression traits
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_H_
+#define _BLAZE_MATH_TRAITS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/CrossExprTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/DMatCTransExprTrait.h>
+#include <blaze/math/traits/DMatDMatAddExprTrait.h>
+#include <blaze/math/traits/DMatDMatMultExprTrait.h>
+#include <blaze/math/traits/DMatDMatSubExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatEvalExprTrait.h>
+#include <blaze/math/traits/DMatForEachExprTrait.h>
+#include <blaze/math/traits/DMatInvExprTrait.h>
+#include <blaze/math/traits/DMatScalarDivExprTrait.h>
+#include <blaze/math/traits/DMatScalarMultExprTrait.h>
+#include <blaze/math/traits/DMatSerialExprTrait.h>
+#include <blaze/math/traits/DMatSMatAddExprTrait.h>
+#include <blaze/math/traits/DMatSMatMultExprTrait.h>
+#include <blaze/math/traits/DMatSMatSubExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/DMatTDMatAddExprTrait.h>
+#include <blaze/math/traits/DMatTDMatMultExprTrait.h>
+#include <blaze/math/traits/DMatTDMatSubExprTrait.h>
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/traits/DMatTSMatAddExprTrait.h>
+#include <blaze/math/traits/DMatTSMatMultExprTrait.h>
+#include <blaze/math/traits/DMatTSMatSubExprTrait.h>
+#include <blaze/math/traits/DVecCTransExprTrait.h>
+#include <blaze/math/traits/DVecDVecAddExprTrait.h>
+#include <blaze/math/traits/DVecDVecCrossExprTrait.h>
+#include <blaze/math/traits/DVecDVecDivExprTrait.h>
+#include <blaze/math/traits/DVecDVecMultExprTrait.h>
+#include <blaze/math/traits/DVecDVecSubExprTrait.h>
+#include <blaze/math/traits/DVecEvalExprTrait.h>
+#include <blaze/math/traits/DVecForEachExprTrait.h>
+#include <blaze/math/traits/DVecScalarDivExprTrait.h>
+#include <blaze/math/traits/DVecScalarMultExprTrait.h>
+#include <blaze/math/traits/DVecSerialExprTrait.h>
+#include <blaze/math/traits/DVecSVecAddExprTrait.h>
+#include <blaze/math/traits/DVecSVecCrossExprTrait.h>
+#include <blaze/math/traits/DVecSVecMultExprTrait.h>
+#include <blaze/math/traits/DVecSVecSubExprTrait.h>
+#include <blaze/math/traits/DVecTDVecMultExprTrait.h>
+#include <blaze/math/traits/DVecTransExprTrait.h>
+#include <blaze/math/traits/DVecTSVecMultExprTrait.h>
+#include <blaze/math/traits/EvalExprTrait.h>
+#include <blaze/math/traits/ForEachExprTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/ImagTrait.h>
+#include <blaze/math/traits/InvExprTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RealTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SerialExprTrait.h>
+#include <blaze/math/traits/SMatCTransExprTrait.h>
+#include <blaze/math/traits/SMatDMatAddExprTrait.h>
+#include <blaze/math/traits/SMatDMatMultExprTrait.h>
+#include <blaze/math/traits/SMatDMatSubExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SMatEvalExprTrait.h>
+#include <blaze/math/traits/SMatForEachExprTrait.h>
+#include <blaze/math/traits/SMatScalarDivExprTrait.h>
+#include <blaze/math/traits/SMatScalarMultExprTrait.h>
+#include <blaze/math/traits/SMatSerialExprTrait.h>
+#include <blaze/math/traits/SMatSMatAddExprTrait.h>
+#include <blaze/math/traits/SMatSMatMultExprTrait.h>
+#include <blaze/math/traits/SMatSMatSubExprTrait.h>
+#include <blaze/math/traits/SMatSVecMultExprTrait.h>
+#include <blaze/math/traits/SMatTDMatAddExprTrait.h>
+#include <blaze/math/traits/SMatTDMatMultExprTrait.h>
+#include <blaze/math/traits/SMatTDMatSubExprTrait.h>
+#include <blaze/math/traits/SMatTransExprTrait.h>
+#include <blaze/math/traits/SMatTSMatAddExprTrait.h>
+#include <blaze/math/traits/SMatTSMatMultExprTrait.h>
+#include <blaze/math/traits/SMatTSMatSubExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/traits/SVecCTransExprTrait.h>
+#include <blaze/math/traits/SVecDVecAddExprTrait.h>
+#include <blaze/math/traits/SVecDVecCrossExprTrait.h>
+#include <blaze/math/traits/SVecDVecDivExprTrait.h>
+#include <blaze/math/traits/SVecDVecMultExprTrait.h>
+#include <blaze/math/traits/SVecDVecSubExprTrait.h>
+#include <blaze/math/traits/SVecEvalExprTrait.h>
+#include <blaze/math/traits/SVecForEachExprTrait.h>
+#include <blaze/math/traits/SVecScalarDivExprTrait.h>
+#include <blaze/math/traits/SVecScalarMultExprTrait.h>
+#include <blaze/math/traits/SVecSerialExprTrait.h>
+#include <blaze/math/traits/SVecSVecAddExprTrait.h>
+#include <blaze/math/traits/SVecSVecCrossExprTrait.h>
+#include <blaze/math/traits/SVecSVecMultExprTrait.h>
+#include <blaze/math/traits/SVecSVecSubExprTrait.h>
+#include <blaze/math/traits/SVecTDVecMultExprTrait.h>
+#include <blaze/math/traits/SVecTransExprTrait.h>
+#include <blaze/math/traits/SVecTSVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatCTransExprTrait.h>
+#include <blaze/math/traits/TDMatDMatAddExprTrait.h>
+#include <blaze/math/traits/TDMatDMatMultExprTrait.h>
+#include <blaze/math/traits/TDMatDMatSubExprTrait.h>
+#include <blaze/math/traits/TDMatEvalExprTrait.h>
+#include <blaze/math/traits/TDMatForEachExprTrait.h>
+#include <blaze/math/traits/TDMatInvExprTrait.h>
+#include <blaze/math/traits/TDMatScalarDivExprTrait.h>
+#include <blaze/math/traits/TDMatScalarMultExprTrait.h>
+#include <blaze/math/traits/TDMatSerialExprTrait.h>
+#include <blaze/math/traits/TDMatSMatAddExprTrait.h>
+#include <blaze/math/traits/TDMatSMatMultExprTrait.h>
+#include <blaze/math/traits/TDMatSMatSubExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatTDMatAddExprTrait.h>
+#include <blaze/math/traits/TDMatTDMatMultExprTrait.h>
+#include <blaze/math/traits/TDMatTDMatSubExprTrait.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/traits/TDMatTSMatAddExprTrait.h>
+#include <blaze/math/traits/TDMatTSMatMultExprTrait.h>
+#include <blaze/math/traits/TDMatTSMatSubExprTrait.h>
+#include <blaze/math/traits/TDVecCTransExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecDVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecEvalExprTrait.h>
+#include <blaze/math/traits/TDVecForEachExprTrait.h>
+#include <blaze/math/traits/TDVecScalarDivExprTrait.h>
+#include <blaze/math/traits/TDVecScalarMultExprTrait.h>
+#include <blaze/math/traits/TDVecSerialExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecAddExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecCrossExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecDivExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecSubExprTrait.h>
+#include <blaze/math/traits/TDVecTransExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSVecAddExprTrait.h>
+#include <blaze/math/traits/TDVecTSVecCrossExprTrait.h>
+#include <blaze/math/traits/TDVecTSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSVecSubExprTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/traits/TSMatCTransExprTrait.h>
+#include <blaze/math/traits/TSMatDMatAddExprTrait.h>
+#include <blaze/math/traits/TSMatDMatMultExprTrait.h>
+#include <blaze/math/traits/TSMatDMatSubExprTrait.h>
+#include <blaze/math/traits/TSMatEvalExprTrait.h>
+#include <blaze/math/traits/TSMatForEachExprTrait.h>
+#include <blaze/math/traits/TSMatScalarDivExprTrait.h>
+#include <blaze/math/traits/TSMatScalarMultExprTrait.h>
+#include <blaze/math/traits/TSMatSerialExprTrait.h>
+#include <blaze/math/traits/TSMatSMatAddExprTrait.h>
+#include <blaze/math/traits/TSMatSMatMultExprTrait.h>
+#include <blaze/math/traits/TSMatSMatSubExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatTDMatAddExprTrait.h>
+#include <blaze/math/traits/TSMatTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSMatTDMatSubExprTrait.h>
+#include <blaze/math/traits/TSMatTransExprTrait.h>
+#include <blaze/math/traits/TSMatTSMatAddExprTrait.h>
+#include <blaze/math/traits/TSMatTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSMatTSMatSubExprTrait.h>
+#include <blaze/math/traits/TSVecCTransExprTrait.h>
+#include <blaze/math/traits/TSVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDVecMultExprTrait.h>
+#include <blaze/math/traits/TSVecEvalExprTrait.h>
+#include <blaze/math/traits/TSVecForEachExprTrait.h>
+#include <blaze/math/traits/TSVecScalarDivExprTrait.h>
+#include <blaze/math/traits/TSVecScalarMultExprTrait.h>
+#include <blaze/math/traits/TSVecSerialExprTrait.h>
+#include <blaze/math/traits/TSVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecSVecMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecAddExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecCrossExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecDivExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecSubExprTrait.h>
+#include <blaze/math/traits/TSVecTransExprTrait.h>
+#include <blaze/math/traits/TSVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSVecAddExprTrait.h>
+#include <blaze/math/traits/TSVecTSVecCrossExprTrait.h>
+#include <blaze/math/traits/TSVecTSVecMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSVecSubExprTrait.h>
+
+#endif
diff --git a/src/cpu/blaze/math/TransposeFlag.h b/src/cpu/blaze/math/TransposeFlag.h
new file mode 100644
index 00000000..cdd523f9
--- /dev/null
+++ b/src/cpu/blaze/math/TransposeFlag.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/TransposeFlag.h
+// \brief Header file for the vector transpose flag types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRANSPOSEFLAG_H_
+#define _BLAZE_MATH_TRANSPOSEFLAG_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// VECTOR TRANSPOSE FLAG TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Transpose flag for column vectors.
+//
+// Via this flag it is possible to specify vectors as column vectors. The following example
+// demonstrates the setup of a 3-dimensional column vector:
+
+ \code
+ using blaze::columnVector;
+ blaze::StaticVector<int,3UL,columnVector> v( 1, 2, 3 );
+ \endcode
+*/
+const bool columnVector = false;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Transpose flag for row vectors.
+//
+// Via this flag it is possible to specify vectors as row vectors. The following example
+// demonstrates the setup of a 3-dimensional row vector:
+
+ \code
+ using blaze::rowVector;
+ blaze::StaticVector<int,3UL,rowVector> v( 1, 2, 3 );
+ \endcode
+*/
+const bool rowVector = true;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/TypeTraits.h b/src/cpu/blaze/math/TypeTraits.h
new file mode 100644
index 00000000..71637bf1
--- /dev/null
+++ b/src/cpu/blaze/math/TypeTraits.h
@@ -0,0 +1,168 @@
+//=================================================================================================
+/*!
+// \file blaze/math/TypeTraits.h
+// \brief Header file for all type traits
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_H_
+#define _BLAZE_MATH_TYPETRAITS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAbs.h>
+#include <blaze/math/typetraits/HasSIMDAcos.h>
+#include <blaze/math/typetraits/HasSIMDAcosh.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDAsin.h>
+#include <blaze/math/typetraits/HasSIMDAsinh.h>
+#include <blaze/math/typetraits/HasSIMDAtan.h>
+#include <blaze/math/typetraits/HasSIMDAtanh.h>
+#include <blaze/math/typetraits/HasSIMDCbrt.h>
+#include <blaze/math/typetraits/HasSIMDCeil.h>
+#include <blaze/math/typetraits/HasSIMDConj.h>
+#include <blaze/math/typetraits/HasSIMDCos.h>
+#include <blaze/math/typetraits/HasSIMDCosh.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/HasSIMDErf.h>
+#include <blaze/math/typetraits/HasSIMDErfc.h>
+#include <blaze/math/typetraits/HasSIMDExp.h>
+#include <blaze/math/typetraits/HasSIMDFloor.h>
+#include <blaze/math/typetraits/HasSIMDInvCbrt.h>
+#include <blaze/math/typetraits/HasSIMDInvSqrt.h>
+#include <blaze/math/typetraits/HasSIMDLog.h>
+#include <blaze/math/typetraits/HasSIMDLog10.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/HasSIMDPow.h>
+#include <blaze/math/typetraits/HasSIMDSin.h>
+#include <blaze/math/typetraits/HasSIMDSinh.h>
+#include <blaze/math/typetraits/HasSIMDSqrt.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/HasSIMDTan.h>
+#include <blaze/math/typetraits/HasSIMDTanh.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAddExpr.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsColumn.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsCrossExpr.h>
+#include <blaze/math/typetraits/IsCustom.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsDivExpr.h>
+#include <blaze/math/typetraits/IsEvalExpr.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsForEachExpr.h>
+#include <blaze/math/typetraits/IsGeneral.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsIdentity.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatEvalExpr.h>
+#include <blaze/math/typetraits/IsMatForEachExpr.h>
+#include <blaze/math/typetraits/IsMatInvExpr.h>
+#include <blaze/math/typetraits/IsMatMatAddExpr.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsMatMatSubExpr.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsMatScalarDivExpr.h>
+#include <blaze/math/typetraits/IsMatScalarMultExpr.h>
+#include <blaze/math/typetraits/IsMatSerialExpr.h>
+#include <blaze/math/typetraits/IsMatTransExpr.h>
+#include <blaze/math/typetraits/IsMatVecMultExpr.h>
+#include <blaze/math/typetraits/IsMultExpr.h>
+#include <blaze/math/typetraits/IsNumericMatrix.h>
+#include <blaze/math/typetraits/IsNumericVector.h>
+#include <blaze/math/typetraits/IsOpposedView.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsProxy.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsRow.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSerialExpr.h>
+#include <blaze/math/typetraits/IsSIMDEnabled.h>
+#include <blaze/math/typetraits/IsSIMDPack.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/math/typetraits/IsSparseElement.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSubExpr.h>
+#include <blaze/math/typetraits/IsSubmatrix.h>
+#include <blaze/math/typetraits/IsSubvector.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsTVecMatMultExpr.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/IsVecEvalExpr.h>
+#include <blaze/math/typetraits/IsVecForEachExpr.h>
+#include <blaze/math/typetraits/IsVecScalarDivExpr.h>
+#include <blaze/math/typetraits/IsVecScalarMultExpr.h>
+#include <blaze/math/typetraits/IsVecSerialExpr.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/math/typetraits/IsVecTransExpr.h>
+#include <blaze/math/typetraits/IsVecTVecMultExpr.h>
+#include <blaze/math/typetraits/IsVecVecAddExpr.h>
+#include <blaze/math/typetraits/IsVecVecDivExpr.h>
+#include <blaze/math/typetraits/IsVecVecMultExpr.h>
+#include <blaze/math/typetraits/IsVecVecSubExpr.h>
+#include <blaze/math/typetraits/IsView.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/math/typetraits/StorageOrder.h>
+#include <blaze/math/typetraits/TransposeFlag.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingElement.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+
+#endif
diff --git a/src/cpu/blaze/math/UniLowerMatrix.h b/src/cpu/blaze/math/UniLowerMatrix.h
new file mode 100644
index 00000000..869cacb7
--- /dev/null
+++ b/src/cpu/blaze/math/UniLowerMatrix.h
@@ -0,0 +1,786 @@
+//=================================================================================================
+/*!
+// \file blaze/math/UniLowerMatrix.h
+// \brief Header file for the complete UniLowerMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_UNILOWERMATRIX_H_
+#define _BLAZE_MATH_UNILOWERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/UniLowerMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/UniUpperMatrix.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for UniLowerMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of UniLowerMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+class Rand< UniLowerMatrix<MT,SO,DF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const UniLowerMatrix<MT,SO,DF> generate() const;
+ inline const UniLowerMatrix<MT,SO,DF> generate( size_t n ) const;
+ inline const UniLowerMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const UniLowerMatrix<MT,SO,DF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const UniLowerMatrix<MT,SO,DF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const UniLowerMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( UniLowerMatrix<MT,SO,DF>& matrix ) const;
+ inline void randomize( UniLowerMatrix<MT,false,DF>& matrix, size_t nonzeros ) const;
+ inline void randomize( UniLowerMatrix<MT,true,DF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( UniLowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( UniLowerMatrix<MT,false,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( UniLowerMatrix<MT,true,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( UniLowerMatrix<MT,SO,DF>& matrix, TrueType ) const;
+ inline void randomize( UniLowerMatrix<MT,SO,DF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( UniLowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( UniLowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniLowerMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UniLowerMatrix<MT,SO,DF> Rand< UniLowerMatrix<MT,SO,DF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ UniLowerMatrix<MT,SO,DF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniLowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UniLowerMatrix<MT,SO,DF>
+ Rand< UniLowerMatrix<MT,SO,DF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UniLowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniLowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UniLowerMatrix<MT,SO,DF>
+ Rand< UniLowerMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > UniLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ UniLowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniLowerMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UniLowerMatrix<MT,SO,DF>
+ Rand< UniLowerMatrix<MT,SO,DF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ UniLowerMatrix<MT,SO,DF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniLowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UniLowerMatrix<MT,SO,DF>
+ Rand< UniLowerMatrix<MT,SO,DF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UniLowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniLowerMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UniLowerMatrix<MT,SO,DF>
+ Rand< UniLowerMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > UniLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ UniLowerMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,SO,DF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,SO,DF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=1UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ matrix(i,j) = rand<ET>();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,SO,DF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL || n == 1UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.2*n*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,false,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UniLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+ matrix.finalize( 0UL );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 1UL, n-1UL );
+ if( dist[index] == index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=1UL; i<n; ++i ) {
+ const Indices indices( 0UL, i-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,true,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UniLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n-1UL );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-2UL );
+ if( dist[index] == n - index - 1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n-1UL; ++j ) {
+ const Indices indices( j+1UL, n-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( j );
+ }
+
+ matrix.finalize( n-1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=1UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ matrix(i,j) = rand<ET>( min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL || n == 1UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.2*n*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,false,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UniLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+ matrix.finalize( 0UL );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 1UL, n-1UL );
+ if( dist[index] == index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=1UL; i<n; ++i ) {
+ const Indices indices( 0UL, i-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniLowerMatrix<MT,SO,DF> >::randomize( UniLowerMatrix<MT,true,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UniLowerMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n-1UL );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-2UL );
+ if( dist[index] == n - index - 1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n-1UL; ++j ) {
+ const Indices indices( j+1UL, n-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( j );
+ }
+
+ matrix.finalize( n-1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeSymmetric( UniLowerMatrix<MT,SO,DF>& matrix )
+{
+ reset( matrix );
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeSymmetric( UniLowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ UNUSED_PARAMETER( min, max );
+
+ makeSymmetric( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeHermitian( UniLowerMatrix<MT,SO,DF>& matrix )
+{
+ reset( matrix );
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeHermitian( UniLowerMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ UNUSED_PARAMETER( min, max );
+
+ makeHermitian( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite UniLowerMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makePositiveDefinite( UniLowerMatrix<MT,SO,DF>& matrix )
+{
+ makeHermitian( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/UniUpperMatrix.h b/src/cpu/blaze/math/UniUpperMatrix.h
new file mode 100644
index 00000000..62c165a9
--- /dev/null
+++ b/src/cpu/blaze/math/UniUpperMatrix.h
@@ -0,0 +1,785 @@
+//=================================================================================================
+/*!
+// \file blaze/math/UniUpperMatrix.h
+// \brief Header file for the complete UniUpperMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_UNIUPPERMATRIX_H_
+#define _BLAZE_MATH_UNIUPPERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/UniUpperMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/UniLowerMatrix.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for UniUpperMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of UniUpperMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+class Rand< UniUpperMatrix<MT,SO,DF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const UniUpperMatrix<MT,SO,DF> generate() const;
+ inline const UniUpperMatrix<MT,SO,DF> generate( size_t n ) const;
+ inline const UniUpperMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const UniUpperMatrix<MT,SO,DF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const UniUpperMatrix<MT,SO,DF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const UniUpperMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( UniUpperMatrix<MT,SO,DF>& matrix ) const;
+ inline void randomize( UniUpperMatrix<MT,false,DF>& matrix, size_t nonzeros ) const;
+ inline void randomize( UniUpperMatrix<MT,true,DF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( UniUpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( UniUpperMatrix<MT,false,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( UniUpperMatrix<MT,true,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( UniUpperMatrix<MT,SO,DF>& matrix, TrueType ) const;
+ inline void randomize( UniUpperMatrix<MT,SO,DF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( UniUpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( UniUpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniUpperMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UniUpperMatrix<MT,SO,DF> Rand< UniUpperMatrix<MT,SO,DF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ UniUpperMatrix<MT,SO,DF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniUpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UniUpperMatrix<MT,SO,DF>
+ Rand< UniUpperMatrix<MT,SO,DF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UniUpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniUpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UniUpperMatrix<MT,SO,DF>
+ Rand< UniUpperMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > UniUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ UniUpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniUpperMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UniUpperMatrix<MT,SO,DF>
+ Rand< UniUpperMatrix<MT,SO,DF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ UniUpperMatrix<MT,SO,DF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniUpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UniUpperMatrix<MT,SO,DF>
+ Rand< UniUpperMatrix<MT,SO,DF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UniUpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UniUpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UniUpperMatrix<MT,SO,DF>
+ Rand< UniUpperMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > UniUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ UniUpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,SO,DF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,SO,DF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=i+1UL; j<n; ++j ) {
+ matrix(i,j) = rand<ET>();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,SO,DF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL || n == 1UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.2*n*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,false,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UniUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n-1UL );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-2UL );
+ if( dist[index] == n - index - 1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<n-1UL; ++i ) {
+ const Indices indices( i+1UL, n-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( i );
+ }
+
+ matrix.finalize( n-1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,true,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UniUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+ matrix.finalize( 0UL );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 1UL, n-1UL );
+ if( dist[index] == index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=1UL; j<n; ++j ) {
+ const Indices indices( 0UL, j-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=i+1UL; j<n; ++j ) {
+ matrix(i,j) = rand<ET>( min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL || n == 1UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.2*n*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,false,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UniUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n-1UL );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-2UL );
+ if( dist[index] == n - index - 1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<n-1UL; ++i ) {
+ const Indices indices( i+1UL, n-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( i );
+ }
+
+ matrix.finalize( n-1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UniUpperMatrix<MT,SO,DF> >::randomize( UniUpperMatrix<MT,true,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UniUpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL || n == 1UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+ matrix.finalize( 0UL );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 1UL, n-1UL );
+ if( dist[index] == index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=1UL; j<n; ++j ) {
+ const Indices indices( 0UL, j-1UL, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeSymmetric( UniUpperMatrix<MT,SO,DF>& matrix )
+{
+ reset( matrix );
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeSymmetric( UniUpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ UNUSED_PARAMETER( min, max );
+
+ makeSymmetric( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeHermitian( UniUpperMatrix<MT,SO,DF>& matrix )
+{
+ reset( matrix );
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeHermitian( UniUpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ UNUSED_PARAMETER( min, max );
+
+ makeHermitian( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite UniUpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makePositiveDefinite( UniUpperMatrix<MT,SO,DF>& matrix )
+{
+ makeHermitian( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/UpperMatrix.h b/src/cpu/blaze/math/UpperMatrix.h
new file mode 100644
index 00000000..ae821c2a
--- /dev/null
+++ b/src/cpu/blaze/math/UpperMatrix.h
@@ -0,0 +1,810 @@
+//=================================================================================================
+/*!
+// \file blaze/math/UpperMatrix.h
+// \brief Header file for the complete UpperMatrix implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_UPPERMATRIX_H_
+#define _BLAZE_MATH_UPPERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/UpperMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/LowerMatrix.h>
+#include <blaze/math/SparseMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/Indices.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for UpperMatrix.
+// \ingroup random
+//
+// This specialization of the Rand class creates random instances of UpperMatrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+class Rand< UpperMatrix<MT,SO,DF> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const UpperMatrix<MT,SO,DF> generate() const;
+ inline const UpperMatrix<MT,SO,DF> generate( size_t n ) const;
+ inline const UpperMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline const UpperMatrix<MT,SO,DF> generate( const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const UpperMatrix<MT,SO,DF> generate( size_t n, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline const UpperMatrix<MT,SO,DF> generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( UpperMatrix<MT,SO,DF>& matrix ) const;
+ inline void randomize( UpperMatrix<MT,false,DF>& matrix, size_t nonzeros ) const;
+ inline void randomize( UpperMatrix<MT,true,DF>& matrix, size_t nonzeros ) const;
+
+ template< typename Arg >
+ inline void randomize( UpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( UpperMatrix<MT,false,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+
+ template< typename Arg >
+ inline void randomize( UpperMatrix<MT,true,DF>& matrix, size_t nonzeros,
+ const Arg& min, const Arg& max ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( UpperMatrix<MT,SO,DF>& matrix, TrueType ) const;
+ inline void randomize( UpperMatrix<MT,SO,DF>& matrix, FalseType ) const;
+
+ template< typename Arg >
+ inline void randomize( UpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, TrueType ) const;
+
+ template< typename Arg >
+ inline void randomize( UpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max, FalseType ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UpperMatrix.
+//
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UpperMatrix<MT,SO,DF> Rand< UpperMatrix<MT,SO,DF> >::generate() const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ UpperMatrix<MT,SO,DF> matrix;
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UpperMatrix<MT,SO,DF>
+ Rand< UpperMatrix<MT,SO,DF> >::generate( size_t n ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline const UpperMatrix<MT,SO,DF>
+ Rand< UpperMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > UpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ UpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UpperMatrix.
+//
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UpperMatrix<MT,SO,DF>
+ Rand< UpperMatrix<MT,SO,DF> >::generate( const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ UpperMatrix<MT,SO,DF> matrix;
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UpperMatrix<MT,SO,DF>
+ Rand< UpperMatrix<MT,SO,DF> >::generate( size_t n, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, min, max );
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random UpperMatrix.
+//
+// \param n The number of rows and columns of the random matrix.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return The generated random matrix.
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline const UpperMatrix<MT,SO,DF>
+ Rand< UpperMatrix<MT,SO,DF> >::generate( size_t n, size_t nonzeros,
+ const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ if( nonzeros > UpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ UpperMatrix<MT,SO,DF> matrix( n );
+ randomize( matrix, nonzeros, min, max );
+
+ return matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,SO,DF>& matrix ) const
+{
+ randomize( matrix, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,SO,DF>& matrix, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=i; j<n; ++j ) {
+ matrix(i,j) = rand<ET>();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,SO,DF>& matrix, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.3*n*n ) ) );
+
+ randomize( matrix, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,false,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == n - index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<n; ++i ) {
+ const Indices indices( i, n-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,true,DF>& matrix, size_t nonzeros ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == index+1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ const Indices indices( 0UL, j, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>() );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max ) const
+{
+ randomize( matrix, min, max, typename IsDenseMatrix<MT>::Type() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a dense UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, TrueType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=i; j<n; ++j ) {
+ matrix(i,j) = rand<ET>( min, max );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a sparse UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,SO,DF>& matrix,
+ const Arg& min, const Arg& max, FalseType ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ const size_t n( matrix.rows() );
+
+ if( n == 0UL ) return;
+
+ const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.3*n*n ) ) );
+
+ randomize( matrix, nonzeros, min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a row-major sparse UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,false,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == n - index ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t i=0UL; i<n; ++i ) {
+ const Indices indices( i, n-1UL, dist[i] );
+ for( size_t j : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a column-major sparse UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param nonzeros The number of non-zero elements of the random matrix.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+// \exception std::invalid_argument Invalid number of non-zero elements.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Numeric flag
+template< typename Arg > // Min/max argument type
+inline void Rand< UpperMatrix<MT,SO,DF> >::randomize( UpperMatrix<MT,true,DF>& matrix,
+ size_t nonzeros, const Arg& min, const Arg& max ) const
+{
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+
+ typedef ElementType_<MT> ET;
+
+ const size_t n( matrix.rows() );
+
+ if( nonzeros > UpperMatrix<MT,SO,DF>::maxNonZeros( n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
+ }
+
+ if( n == 0UL ) return;
+
+ matrix.reset();
+ matrix.reserve( nonzeros );
+
+ std::vector<size_t> dist( n );
+
+ for( size_t nz=0UL; nz<nonzeros; ) {
+ const size_t index = rand<size_t>( 0UL, n-1UL );
+ if( dist[index] == index+1UL ) continue;
+ ++dist[index];
+ ++nz;
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ const Indices indices( 0UL, j, dist[j] );
+ for( size_t i : indices ) {
+ matrix.append( i, j, rand<ET>( min, max ) );
+ }
+ matrix.finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MAKE FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeSymmetric( UpperMatrix<MT,SO,DF>& matrix )
+{
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand< ElementType_<MT> >();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random symmetric UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeSymmetric( UpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ typedef ElementType_<MT> Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>( min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makeHermitian( UpperMatrix<MT,SO,DF>& matrix )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random Hermitian UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \param min The smallest possible value for a matrix element.
+// \param max The largest possible value for a matrix element.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename Arg > // Min/max argument type
+void makeHermitian( UpperMatrix<MT,SO,DF>& matrix, const Arg& min, const Arg& max )
+{
+ typedef UnderlyingBuiltin_< ElementType_<MT> > Type;
+
+ const size_t n( matrix.rows() );
+
+ reset( matrix );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix(i,i) = rand<Type>( min, max );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setup of a random (Hermitian) positive definite UpperMatrix.
+//
+// \param matrix The matrix to be randomized.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+void makePositiveDefinite( UpperMatrix<MT,SO,DF>& matrix )
+{
+ makeHermitian( matrix );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Vector.h b/src/cpu/blaze/math/Vector.h
new file mode 100644
index 00000000..430c7093
--- /dev/null
+++ b/src/cpu/blaze/math/Vector.h
@@ -0,0 +1,378 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Vector.h
+// \brief Header file for all basic Vector functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VECTOR_H_
+#define _BLAZE_MATH_VECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iomanip>
+#include <ostream>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/expressions/Vector.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/TransposeFlag.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Vector operators */
+//@{
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator,( const Vector<T1,false>& lhs, const Vector<T2,false>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator,( const Vector<T1,false>& lhs, const Vector<T2,true>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator,( const Vector<T1,true>& lhs, const Vector<T2,false>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator,( const Vector<T1,true>& lhs, const Vector<T2,true>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ dot( const Vector<T1,false>& lhs, const Vector<T2,false>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ dot( const Vector<T1,false>& lhs, const Vector<T2,true>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ dot( const Vector<T1,true>& lhs, const Vector<T2,false>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ dot( const Vector<T1,true>& lhs, const Vector<T2,true>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ outer( const Vector<T1,false>& lhs, const Vector<T2,false>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ outer( const Vector<T1,false>& lhs, const Vector<T2,true>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ outer( const Vector<T1,true>& lhs, const Vector<T2,false>& rhs );
+
+template< typename T1, typename T2 >
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ outer( const Vector<T1,true>& lhs, const Vector<T2,true>& rhs );
+
+template< typename VT, bool TF >
+inline std::ostream& operator<<( std::ostream& os, const Vector<VT,TF>& v );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (dot product) of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the scalar product.
+// \param rhs The right-hand side vector for the scalar product.
+// \return The scalar product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator,( const Vector<T1,false>& lhs, const Vector<T2,false>& rhs )
+{
+ return trans(~lhs) * (~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (dot product) of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the scalar product.
+// \param rhs The right-hand side vector for the scalar product.
+// \return The scalar product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator,( const Vector<T1,false>& lhs, const Vector<T2,true>& rhs )
+{
+ return trans(~lhs) * trans(~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (dot product) of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the scalar product.
+// \param rhs The right-hand side vector for the scalar product.
+// \return The scalar product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator,( const Vector<T1,true>& lhs, const Vector<T2,false>& rhs )
+{
+ return (~lhs) * (~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (dot product) of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the scalar product.
+// \param rhs The right-hand side vector for the scalar product.
+// \return The scalar product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator,( const Vector<T1,true>& lhs, const Vector<T2,true>& rhs )
+{
+ return (~lhs) * trans(~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (dot product) of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the scalar product.
+// \param rhs The right-hand side vector for the scalar product.
+// \return The scalar product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ dot( const Vector<T1,false>& lhs, const Vector<T2,false>& rhs )
+{
+ return trans(~lhs) * (~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (dot product) of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the scalar product.
+// \param rhs The right-hand side vector for the scalar product.
+// \return The scalar product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ dot( const Vector<T1,false>& lhs, const Vector<T2,true>& rhs )
+{
+ return trans(~lhs) * trans(~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (dot product) of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the scalar product.
+// \param rhs The right-hand side vector for the scalar product.
+// \return The scalar product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ dot( const Vector<T1,true>& lhs, const Vector<T2,false>& rhs )
+{
+ return (~lhs) * (~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (dot product) of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the scalar product.
+// \param rhs The right-hand side vector for the scalar product.
+// \return The scalar product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ dot( const Vector<T1,true>& lhs, const Vector<T2,true>& rhs )
+{
+ return (~lhs) * trans(~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the outer product of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the outer product.
+// \param rhs The right-hand side vector for the outer product.
+// \return The outer product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ outer( const Vector<T1,false>& lhs, const Vector<T2,false>& rhs )
+{
+ return (~lhs) * trans(~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the outer product of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the outer product.
+// \param rhs The right-hand side vector for the outer product.
+// \return The outer product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ outer( const Vector<T1,false>& lhs, const Vector<T2,true>& rhs )
+{
+ return (~lhs) * (~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the outer product of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the outer product.
+// \param rhs The right-hand side vector for the outer product.
+// \return The outer product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ outer( const Vector<T1,true>& lhs, const Vector<T2,false>& rhs )
+{
+ return trans(~lhs) * trans(~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the outer product of two vectors
+// (\f$ s=(\vec{a},\vec{b}) \f$).
+// \ingroup vector
+//
+// \param lhs The left-hand side vector for the outer product.
+// \param rhs The right-hand side vector for the outer product.
+// \return The outer product.
+*/
+template< typename T1 // Type of the left-hand side vector
+ , typename T2 > // Type of the right-hand side vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ outer( const Vector<T1,true>& lhs, const Vector<T2,true>& rhs )
+{
+ return trans(~lhs) * (~rhs);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Global output operator for dense and sparse vectors.
+// \ingroup vector
+//
+// \param os Reference to the output stream.
+// \param v Reference to a constant vector object.
+// \return Reference to the output stream.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline std::ostream& operator<<( std::ostream& os, const Vector<VT,TF>& v )
+{
+ CompositeType_<VT> tmp( ~v );
+
+ if( tmp.size() == 0UL ) {
+ os << "( )\n";
+ }
+ else if( TF == rowVector ) {
+ os << "(";
+ for( size_t i=0UL; i<tmp.size(); ++i )
+ os << " " << tmp[i];
+ os << " )\n";
+ }
+ else {
+ for( size_t i=0UL; i<tmp.size(); ++i )
+ os << "( " << std::setw( 11UL ) << tmp[i] << " )\n";
+ }
+
+ return os;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/Views.h b/src/cpu/blaze/math/Views.h
new file mode 100644
index 00000000..ae093179
--- /dev/null
+++ b/src/cpu/blaze/math/Views.h
@@ -0,0 +1,48 @@
+//=================================================================================================
+/*!
+// \file blaze/math/Views.h
+// \brief Header file for the vector and matrix views
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_H_
+#define _BLAZE_MATH_VIEWS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Column.h>
+#include <blaze/math/Row.h>
+#include <blaze/math/Submatrix.h>
+#include <blaze/math/Subvector.h>
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/Adaptors.h b/src/cpu/blaze/math/adaptors/Adaptors.h
new file mode 100644
index 00000000..af81c239
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/Adaptors.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/Adaptors.h
+// \brief Adaptors module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_ADAPTORS_H_
+#define _BLAZE_MATH_ADAPTORS_ADAPTORS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup adaptors Adaptors
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/DiagonalMatrix.h b/src/cpu/blaze/math/adaptors/DiagonalMatrix.h
new file mode 100644
index 00000000..edfb1be5
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/DiagonalMatrix.h
@@ -0,0 +1,2208 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/DiagonalMatrix.h
+// \brief Header file for the implementation of a diagonal matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/diagonalmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/diagonalmatrix/Dense.h>
+#include <blaze/math/adaptors/diagonalmatrix/Sparse.h>
+#include <blaze/math/adaptors/lowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/uppermatrix/BaseTemplate.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/InversionFlag.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDivisor.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DIAGONALMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DiagonalMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF >
+inline void reset( DiagonalMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void reset( DiagonalMatrix<MT,SO,DF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF >
+inline void clear( DiagonalMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isDefault( const DiagonalMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isIntact( const DiagonalMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void swap( DiagonalMatrix<MT,SO,DF>& a, DiagonalMatrix<MT,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( DiagonalMatrix<MT,SO,DF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given diagonal matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( DiagonalMatrix<MT,SO,DF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void clear( DiagonalMatrix<MT,SO,DF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given diagonal matrix is in default state.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal matrix to be tested for its default state.
+// \return \a true in case the given matrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the matrix is in default state. For instance, in case the
+// matrix is instantiated for a built-in integral or floating point data type, the function
+// returns \a true in case all matrix elements are 0 and \a false in case any matrix element
+// is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DiagonalMatrix;
+
+ DiagonalMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault( const DiagonalMatrix<MT,SO,DF>& m )
+{
+ return isDefault( m.matrix_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given diagonal matrix are intact.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the diagonal matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DiagonalMatrix;
+
+ DiagonalMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isIntact( const DiagonalMatrix<MT,SO,DF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup diagonal_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void swap( DiagonalMatrix<MT,SO,DF>& a, DiagonalMatrix<MT,SO,DF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given diagonal dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given diagonal dense \f$ 2 \times 2 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert2x2( DiagonalMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ const ET det( A(0,0) * A(1,1) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+ const ET a11( A(0,0) * idet );
+
+ A(0,0) = A(1,1) * idet;
+ A(1,1) = a11;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given diagonal dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given diagonal dense \f$ 3 \times 3 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert3x3( DiagonalMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ const ET tmp1( A(0,0)*A(1,1) );
+ const ET tmp2( A(0,0)*A(2,2) );
+
+ const ET det( tmp1*A(2,2) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+
+ A(0,0) = A(1,1)*A(2,2)*idet;
+ A(1,1) = tmp2*idet;
+ A(2,2) = tmp1*idet;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given diagonal dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given diagonal dense \f$ 4 \times 4 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert4x4( DiagonalMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ const ET tmp1( A(2,2)*A(3,3) );
+ const ET tmp2( A(0,0)*A(1,1) );
+ const ET tmp3( A(0,0)*tmp1 );
+ const ET tmp4( A(2,2)*tmp2 );
+
+ const ET det( tmp1 * tmp2 );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+
+ A(0,0) = A(1,1)*tmp1*idet;
+ A(1,1) = tmp3*idet;
+ A(2,2) = A(3,3)*tmp2*idet;
+ A(3,3) = tmp4*idet;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given diagonal dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given diagonal dense \f$ 5 \times 5 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert5x5( DiagonalMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ const ET tmp1( A(0,0)*A(1,1) );
+ const ET tmp2( A(3,3)*A(4,4) );
+ const ET tmp3( A(0,0)*tmp2 );
+ const ET tmp4( tmp1*A(2,2) );
+ const ET tmp5( tmp4*A(3,3) );
+
+ const ET det( tmp2*tmp4 );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+
+ A(0,0) = A(1,1)*A(2,2)*tmp2*idet;
+ A(1,1) = A(2,2)*tmp3*idet;
+ A(2,2) = tmp1*tmp2*idet;
+ A(3,3) = tmp4*A(4,4)*idet;
+ A(4,4) = tmp5*idet;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given diagonal dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The diagonal dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given diagonal dense \f$ 6 \times 6 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert6x6( DiagonalMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ const ET tmp1( A(0,0)*A(1,1) );
+ const ET tmp2( A(3,3)*A(4,4) );
+ const ET tmp3( tmp1*A(2,2) );
+ const ET tmp4( tmp2*A(5,5) );
+ const ET tmp5( A(0,0)*tmp4 );
+ const ET tmp6( tmp3*A(3,3) );
+
+ const ET det( tmp3*tmp4 );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+
+ A(0,0) = A(1,1)*A(2,2)*tmp4*idet;
+ A(1,1) = tmp5*A(2,2)*idet;
+ A(2,2) = tmp1*tmp4*idet;
+ A(3,3) = tmp3*A(4,4)*A(5,5)*idet;
+ A(4,4) = tmp6*A(5,5)*idet;
+ A(5,5) = tmp2*tmp3*idet;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given dense diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param m The dense diagonal matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given dense diagonal matrix. The matrix inversion fails if the
+// given diagonal matrix is singular and not invertible. In this case a \a std::invalid_argument
+// exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< InversionFlag IF // Inversion algorithm
+ , typename MT // Type of the adapted matrix
+ , bool SO > // Storage order of the adapted matrix
+inline void invertNxN( DiagonalMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT& A( derestrict( m ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ if( !isDivisor( A(i,i) ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ invert( A(i,i) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief LU decomposition of the given diagonal dense matrix.
+// \ingroup diagonal_matrix
+//
+// \param A The diagonal matrix to be decomposed.
+// \param L The resulting lower triangular matrix.
+// \param U The resulting upper triangular matrix.
+// \param P The resulting permutation matrix.
+// \return void
+//
+// This function performs the dense matrix (P)LU decomposition of a diagonal n-by-n matrix. The
+// resulting decomposition is written to the three distinct matrices \c L, \c U, and \c P, which
+// are resized to the correct dimensions (if possible and necessary).
+//
+// \note The LU decomposition will never fail, even for singular matrices. However, in case of a
+// singular matrix the resulting decomposition cannot be used for a matrix inversion or solving
+// a linear system of equations.
+*/
+template< typename MT1, bool SO1, typename MT2, typename MT3, typename MT4, bool SO2 >
+inline void lu( const DiagonalMatrix<MT1,SO1,true>& A, DenseMatrix<MT2,SO1>& L,
+ DenseMatrix<MT3,SO1>& U, Matrix<MT4,SO2>& P )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE( MT3 );
+
+ typedef ElementType_<MT3> ET3;
+ typedef ElementType_<MT4> ET4;
+
+ const size_t n( (~A).rows() );
+
+ DerestrictTrait_<MT3> U2( derestrict( ~U ) );
+
+ (~L) = A;
+
+ resize( ~U, n, n );
+ reset( U2 );
+
+ resize( ~P, n, n );
+ reset( ~P );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ U2(i,i) = ET3(1);
+ (~P)(i,i) = ET4(1);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const DiagonalMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t index( ( column <= row )?( 0UL ):( column - row ) );
+
+ for( size_t i=0UL; i<index; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ for( size_t i=index+1UL; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const DiagonalMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t index( ( row <= column )?( 0UL ):( row - column ) );
+
+ for( size_t i=0UL; i<index; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ for( size_t i=index+1UL; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const DiagonalMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ const size_t index( column - row );
+
+ for( RhsIterator element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ if( element->index() != index && !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const DiagonalMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ const size_t index( row - column );
+
+ for( RhsIterator element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ if( element->index() != index && !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const DiagonalMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ if( ( row + i != column + j ) && !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const DiagonalMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ if( ( column + j != row + i ) && !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const DiagonalMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element ) {
+ if( ( row + i != column + element->index() ) && !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const DiagonalMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t N( (~rhs).columns() );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element ) {
+ if( ( column + j != row + element->index() ) && !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryAddAssign( const DiagonalMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a diagonal matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAddAssign( const DiagonalMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a diagonal
+// matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const DiagonalMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a diagonal
+// matrix.
+// \ingroup diagonal_matrix
+//
+// \param lhs The target left-hand side diagonal matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const DiagonalMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns a reference to the instance without the access restrictions to the lower and
+// upper part.
+// \ingroup math_shims
+//
+// \param m The diagonal matrix to be derestricted.
+// \return Reference to the matrix without access restrictions.
+//
+// This function returns a reference to the given diagonal matrix instance that has no access
+// restrictions to the lower and upper part of the matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline MT& derestrict( DiagonalMatrix<MT,SO,DF>& m )
+{
+ return m.matrix_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Rows< DiagonalMatrix<MT,SO,DF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Columns< DiagonalMatrix<MT,SO,DF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSquare< DiagonalMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSymmetric< DiagonalMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsHermitian< DiagonalMatrix<MT,SO,DF> >
+ : public BoolConstant< IsBuiltin< ElementType_<MT> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsLower< DiagonalMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsUpper< DiagonalMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAdaptor< DiagonalMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsRestricted< DiagonalMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasConstDataAccess< DiagonalMatrix<MT,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAligned< DiagonalMatrix<MT,SO,DF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsPadded< DiagonalMatrix<MT,SO,DF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsResizable< DiagonalMatrix<MT,SO,DF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RemoveAdaptor< DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct DerestrictTrait< DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = MT&;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< DiagonalMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< DiagonalMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< DiagonalMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< DynamicMatrix<T,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< DiagonalMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< DiagonalMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CompressedMatrix<T,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< DiagonalMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = DiagonalMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< DiagonalMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< DiagonalMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< DiagonalMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< DynamicMatrix<T,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< DiagonalMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< DiagonalMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CompressedMatrix<T,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct SubTrait< DiagonalMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< DiagonalMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< DiagonalMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< DiagonalMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< DiagonalMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< DiagonalMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< DiagonalMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< DiagonalMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = DiagonalMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< DiagonalMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = DiagonalMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< T, DiagonalMatrix<MT,SO,DF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = DiagonalMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< DiagonalMatrix<MT,SO,DF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< StaticVector<T,N,true>, DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< DiagonalMatrix<MT,SO,DF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< HybridVector<T,N,true>, DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< DiagonalMatrix<MT,SO,DF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< DynamicVector<T,true>, DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF >
+struct MultTrait< DiagonalMatrix<MT,SO,DF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF >
+struct MultTrait< CustomVector<T,AF,PF,true>, DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< DiagonalMatrix<MT,SO,DF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< CompressedVector<T,true>, DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< DiagonalMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< DiagonalMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< DiagonalMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< DynamicMatrix<T,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< DiagonalMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< DiagonalMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CompressedMatrix<T,SO1>, DiagonalMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< DiagonalMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using Type = DiagonalMatrix< MultTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct DivTrait< DiagonalMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = DiagonalMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Abs >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Abs> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Floor >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Floor> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Ceil >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Ceil> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Conj >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Conj> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Real >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Real> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Imag >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Imag> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Sin >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Sin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Asin >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Asin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Sinh >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Sinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Asinh >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Asinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Tan >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Tan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Atan >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Atan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Tanh >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Tanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Atanh >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Atanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< DiagonalMatrix<MT,SO,DF>, Erf >
+{
+ using Type = DiagonalMatrix< ForEachTrait_<MT,Erf> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MathTrait< DiagonalMatrix<MT1,SO1,DF1>, DiagonalMatrix<MT2,SO2,DF2> >
+{
+ using HighType = DiagonalMatrix< typename MathTrait<MT1,MT2>::HighType >;
+ using LowType = DiagonalMatrix< typename MathTrait<MT1,MT2>::LowType >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct SubmatrixTrait< DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RowTrait< DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ColumnTrait< DiagonalMatrix<MT,SO,DF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/Forward.h b/src/cpu/blaze/math/adaptors/Forward.h
new file mode 100644
index 00000000..c7f0cb7c
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/Forward.h
@@ -0,0 +1,59 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/Forward.h
+// \brief Header file for all adaptor forward declarations
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_FORWARD_H_
+#define _BLAZE_MATH_ADAPTORS_FORWARD_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+template< typename, bool, bool > class DiagonalMatrix;
+template< typename, bool, bool > class LowerMatrix;
+template< typename, bool, bool > class HermitianMatrix;
+template< typename, bool, bool > class StrictlyLowerMatrix;
+template< typename, bool, bool > class StrictlyUpperMatrix;
+template< typename, bool, bool, bool > class SymmetricMatrix;
+template< typename, bool, bool > class UniLowerMatrix;
+template< typename, bool, bool > class UniUpperMatrix;
+template< typename, bool, bool > class UpperMatrix;
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/HermitianMatrix.h b/src/cpu/blaze/math/adaptors/HermitianMatrix.h
new file mode 100644
index 00000000..0acbfef5
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/HermitianMatrix.h
@@ -0,0 +1,2130 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/HermitianMatrix.h
+// \brief Header file for the implementation of a Hermitian matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/hermitianmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/hermitianmatrix/Dense.h>
+#include <blaze/math/adaptors/hermitianmatrix/Sparse.h>
+#include <blaze/math/adaptors/symmetricmatrix/BaseTemplate.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/dense/StaticMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsDivisor.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// HERMITIANMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name HermitianMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF >
+inline void reset( HermitianMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void reset( HermitianMatrix<MT,SO,DF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF >
+inline void clear( HermitianMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isDefault( const HermitianMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isIntact( const HermitianMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void swap( HermitianMatrix<MT,SO,DF>& a, HermitianMatrix<MT,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( HermitianMatrix<MT,SO,DF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given Hermitian matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( HermitianMatrix<MT,SO,DF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void clear( HermitianMatrix<MT,SO,DF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given Hermitian matrix is in default state.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian matrix to be tested for its default state.
+// \return \a true in case the given matrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the matrix is in default state. For instance, in case the
+// matrix is instantiated for a built-in integral or floating point data type, the function
+// returns \a true in case all matrix elements are 0 and \a false in case any matrix element
+// is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::HermitianMatrix<int> A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault( const HermitianMatrix<MT,SO,DF>& m )
+{
+ return isDefault( m.matrix_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given Hermitian matrix are intact.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the Hermitian matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+
+ HermitianMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isIntact( const HermitianMatrix<MT,SO,DF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup hermitian_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void swap( HermitianMatrix<MT,SO,DF>& a, HermitianMatrix<MT,SO,DF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given Hermitian dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given Hermitian dense \f$ 2 \times 2 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert2x2( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const MT& A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ const ET det( real( A(0,0)*A(1,1) - A(0,1)*A(1,0) ) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+ const ET a11( A(0,0) * idet );
+
+ B(0,0) = ET( A(1,1) * idet );
+ B(1,0) = -A(1,0) * idet;
+ B(0,1) = conj( B(1,0) );
+ B(1,1) = ET( a11 );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given Hermitian dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given Hermitian dense \f$ 3 \times 3 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert3x3( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,3UL,3UL,SO> A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ B(0,0) = ET( real( A(1,1)*A(2,2) - A(1,2)*A(2,1) ) );
+ B(1,0) = A(1,2)*A(2,0) - A(1,0)*A(2,2);
+ B(2,0) = A(1,0)*A(2,1) - A(1,1)*A(2,0);
+
+ const ET det( real( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) ) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B(0,1) = conj( B(1,0) );
+ B(1,1) = ET( real( A(0,0)*A(2,2) - A(0,2)*A(2,0) ) );
+ B(2,1) = A(0,1)*A(2,0) - A(0,0)*A(2,1);
+ B(0,2) = conj( B(2,0) );
+ B(1,2) = conj( B(2,1) );
+ B(2,2) = ET( real( A(0,0)*A(1,1) - A(0,1)*A(1,0) ) );
+
+ m /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given Hermitian dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given Hermitian dense \f$ 4 \times 4 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert4x4( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,4UL,4UL,SO> A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ ET tmp1( A(2,2)*A(3,3) - A(2,3)*A(3,2) );
+ ET tmp2( A(2,1)*A(3,3) - A(2,3)*A(3,1) );
+ ET tmp3( A(2,1)*A(3,2) - A(2,2)*A(3,1) );
+
+ B(0,0) = ET( real( A(1,1)*tmp1 - A(1,2)*tmp2 + A(1,3)*tmp3 ) );
+ B(0,1) = A(0,2)*tmp2 - A(0,1)*tmp1 - A(0,3)*tmp3;
+
+ ET tmp4( A(2,0)*A(3,3) - A(2,3)*A(3,0) );
+ ET tmp5( A(2,0)*A(3,2) - A(2,2)*A(3,0) );
+
+ B(1,1) = ET( real( A(0,0)*tmp1 - A(0,2)*tmp4 + A(0,3)*tmp5 ) );
+
+ tmp1 = A(2,0)*A(3,1) - A(2,1)*A(3,0);
+
+ B(2,0) = A(1,0)*tmp2 - A(1,1)*tmp4 + A(1,3)*tmp1;
+ B(2,1) = A(0,1)*tmp4 - A(0,0)*tmp2 - A(0,3)*tmp1;
+ B(3,0) = A(1,1)*tmp5 - A(1,0)*tmp3 - A(1,2)*tmp1;
+ B(3,1) = A(0,0)*tmp3 - A(0,1)*tmp5 + A(0,2)*tmp1;
+
+ tmp1 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp2 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ tmp3 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp4 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+ tmp5 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+
+ B(2,2) = ET( real( A(3,0)*tmp1 - A(3,1)*tmp3 + A(3,3)*tmp5 ) );
+ B(2,3) = A(2,1)*tmp3 - A(2,0)*tmp1 - A(2,3)*tmp5;
+ B(3,3) = ET( real( A(2,0)*tmp2 - A(2,1)*tmp4 + A(2,2)*tmp5 ) );
+
+ B(0,2) = conj( B(2,0) );
+ B(0,3) = conj( B(3,0) );
+ B(1,0) = conj( B(0,1) );
+ B(1,2) = conj( B(2,1) );
+ B(1,3) = conj( B(3,1) );
+ B(3,2) = conj( B(2,3) );
+
+ const ET det( real( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) + A(0,3)*B(3,0) ) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given Hermitian dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given Hermitian dense \f$ 5 \times 5 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert5x5( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,5UL,5UL,SO> A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ ET tmp1 ( A(3,3)*A(4,4) - A(3,4)*A(4,3) );
+ ET tmp2 ( A(3,2)*A(4,4) - A(3,4)*A(4,2) );
+ ET tmp3 ( A(3,2)*A(4,3) - A(3,3)*A(4,2) );
+ ET tmp4 ( A(3,1)*A(4,4) - A(3,4)*A(4,1) );
+ ET tmp5 ( A(3,1)*A(4,3) - A(3,3)*A(4,1) );
+ ET tmp6 ( A(3,1)*A(4,2) - A(3,2)*A(4,1) );
+ ET tmp7 ( A(3,0)*A(4,4) - A(3,4)*A(4,0) );
+ ET tmp8 ( A(3,0)*A(4,3) - A(3,3)*A(4,0) );
+ ET tmp9 ( A(3,0)*A(4,2) - A(3,2)*A(4,0) );
+ ET tmp10( A(3,0)*A(4,1) - A(3,1)*A(4,0) );
+
+ ET tmp11( A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3 );
+ ET tmp12( A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5 );
+ ET tmp13( A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6 );
+ ET tmp14( A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6 );
+ ET tmp15( A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8 );
+ ET tmp16( A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9 );
+ ET tmp17( A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9 );
+
+ B(0,0) = ET( real( A(1,1)*tmp11 - A(1,2)*tmp12 + A(1,3)*tmp13 - A(1,4)*tmp14 ) );
+ B(0,1) = - A(0,1)*tmp11 + A(0,2)*tmp12 - A(0,3)*tmp13 + A(0,4)*tmp14;
+ B(1,1) = ET( real( A(0,0)*tmp11 - A(0,2)*tmp15 + A(0,3)*tmp16 - A(0,4)*tmp17 ) );
+
+ ET tmp18( A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10 );
+ ET tmp19( A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10 );
+ ET tmp20( A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10 );
+
+ B(2,0) = A(1,0)*tmp12 - A(1,1)*tmp15 + A(1,3)*tmp18 - A(1,4)*tmp19;
+ B(2,1) = - A(0,0)*tmp12 + A(0,1)*tmp15 - A(0,3)*tmp18 + A(0,4)*tmp19;
+ B(3,0) = - A(1,0)*tmp13 + A(1,1)*tmp16 - A(1,2)*tmp18 + A(1,4)*tmp20;
+ B(3,1) = A(0,0)*tmp13 - A(0,1)*tmp16 + A(0,2)*tmp18 - A(0,4)*tmp20;
+ B(4,0) = A(1,0)*tmp14 - A(1,1)*tmp17 + A(1,2)*tmp19 - A(1,3)*tmp20;
+ B(4,1) = - A(0,0)*tmp14 + A(0,1)*tmp17 - A(0,2)*tmp19 + A(0,3)*tmp20;
+
+ tmp11 = A(1,1)*tmp1 - A(1,3)*tmp4 + A(1,4)*tmp5;
+ tmp12 = A(1,0)*tmp1 - A(1,3)*tmp7 + A(1,4)*tmp8;
+ tmp13 = A(1,0)*tmp4 - A(1,1)*tmp7 + A(1,4)*tmp10;
+ tmp14 = A(1,0)*tmp5 - A(1,1)*tmp8 + A(1,3)*tmp10;
+
+ B(2,2) = ET( real( A(0,0)*tmp11 - A(0,1)*tmp12 + A(0,3)*tmp13 - A(0,4)*tmp14 ) );
+
+ tmp1 = A(0,2)*A(1,3) - A(0,3)*A(1,2);
+ tmp2 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp3 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ tmp4 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp5 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+ tmp6 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+ tmp7 = A(0,2)*A(1,4) - A(0,4)*A(1,2);
+ tmp8 = A(0,1)*A(1,4) - A(0,4)*A(1,1);
+ tmp9 = A(0,0)*A(1,4) - A(0,4)*A(1,0);
+ tmp10 = A(0,3)*A(1,4) - A(0,4)*A(1,3);
+
+ tmp11 = A(2,1)*tmp10 - A(2,3)*tmp8 + A(2,4)*tmp2;
+ tmp12 = A(2,1)*tmp7 - A(2,2)*tmp8 + A(2,4)*tmp3;
+ tmp13 = A(2,1)*tmp1 - A(2,2)*tmp2 + A(2,3)*tmp3;
+ tmp14 = A(2,0)*tmp10 - A(2,3)*tmp9 + A(2,4)*tmp4;
+ tmp15 = A(2,0)*tmp7 - A(2,2)*tmp9 + A(2,4)*tmp5;
+ tmp16 = A(2,0)*tmp1 - A(2,2)*tmp4 + A(2,3)*tmp5;
+ tmp17 = A(2,0)*tmp8 - A(2,1)*tmp9 + A(2,4)*tmp6;
+ tmp18 = A(2,0)*tmp2 - A(2,1)*tmp4 + A(2,3)*tmp6;
+ tmp19 = A(2,0)*tmp3 - A(2,1)*tmp5 + A(2,2)*tmp6;
+
+ B(2,3) = A(4,0)*tmp11 - A(4,1)*tmp14 + A(4,3)*tmp17 - A(4,4)*tmp18;
+ B(2,4) = - A(3,0)*tmp11 + A(3,1)*tmp14 - A(3,3)*tmp17 + A(3,4)*tmp18;
+ B(3,3) = - ET( real( A(4,0)*tmp12 - A(4,1)*tmp15 + A(4,2)*tmp17 - A(4,4)*tmp19 ) );
+ B(3,4) = A(3,0)*tmp12 - A(3,1)*tmp15 + A(3,2)*tmp17 - A(3,4)*tmp19;
+ B(4,4) = - ET( real( A(3,0)*tmp13 - A(3,1)*tmp16 + A(3,2)*tmp18 - A(3,3)*tmp19 ) );
+
+ B(0,2) = conj( B(2,0) );
+ B(0,3) = conj( B(3,0) );
+ B(0,4) = conj( B(4,0) );
+ B(1,0) = conj( B(0,1) );
+ B(1,2) = conj( B(2,1) );
+ B(1,3) = conj( B(3,1) );
+ B(1,4) = conj( B(4,1) );
+ B(3,2) = conj( B(2,3) );
+ B(4,2) = conj( B(2,4) );
+ B(4,3) = conj( B(3,4) );
+
+ const ET det( real( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) + A(0,3)*B(3,0) + A(0,4)*B(4,0) ) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given Hermitian dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given Hermitian dense \f$ 6 \times 6 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert6x6( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,6UL,6UL,SO> A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ ET tmp1 ( A(4,4)*A(5,5) - A(4,5)*A(5,4) );
+ ET tmp2 ( A(4,3)*A(5,5) - A(4,5)*A(5,3) );
+ ET tmp3 ( A(4,3)*A(5,4) - A(4,4)*A(5,3) );
+ ET tmp4 ( A(4,2)*A(5,5) - A(4,5)*A(5,2) );
+ ET tmp5 ( A(4,2)*A(5,4) - A(4,4)*A(5,2) );
+ ET tmp6 ( A(4,2)*A(5,3) - A(4,3)*A(5,2) );
+ ET tmp7 ( A(4,1)*A(5,5) - A(4,5)*A(5,1) );
+ ET tmp8 ( A(4,1)*A(5,4) - A(4,4)*A(5,1) );
+ ET tmp9 ( A(4,1)*A(5,3) - A(4,3)*A(5,1) );
+ ET tmp10( A(4,1)*A(5,2) - A(4,2)*A(5,1) );
+ ET tmp11( A(4,0)*A(5,5) - A(4,5)*A(5,0) );
+ ET tmp12( A(4,0)*A(5,4) - A(4,4)*A(5,0) );
+ ET tmp13( A(4,0)*A(5,3) - A(4,3)*A(5,0) );
+ ET tmp14( A(4,0)*A(5,2) - A(4,2)*A(5,0) );
+ ET tmp15( A(4,0)*A(5,1) - A(4,1)*A(5,0) );
+
+ ET tmp16( A(3,3)*tmp1 - A(3,4)*tmp2 + A(3,5)*tmp3 );
+ ET tmp17( A(3,2)*tmp1 - A(3,4)*tmp4 + A(3,5)*tmp5 );
+ ET tmp18( A(3,2)*tmp2 - A(3,3)*tmp4 + A(3,5)*tmp6 );
+ ET tmp19( A(3,2)*tmp3 - A(3,3)*tmp5 + A(3,4)*tmp6 );
+ ET tmp20( A(3,1)*tmp1 - A(3,4)*tmp7 + A(3,5)*tmp8 );
+ ET tmp21( A(3,1)*tmp2 - A(3,3)*tmp7 + A(3,5)*tmp9 );
+ ET tmp22( A(3,1)*tmp3 - A(3,3)*tmp8 + A(3,4)*tmp9 );
+ ET tmp23( A(3,1)*tmp4 - A(3,2)*tmp7 + A(3,5)*tmp10 );
+ ET tmp24( A(3,1)*tmp5 - A(3,2)*tmp8 + A(3,4)*tmp10 );
+ ET tmp25( A(3,1)*tmp6 - A(3,2)*tmp9 + A(3,3)*tmp10 );
+ ET tmp26( A(3,0)*tmp1 - A(3,4)*tmp11 + A(3,5)*tmp12 );
+ ET tmp27( A(3,0)*tmp2 - A(3,3)*tmp11 + A(3,5)*tmp13 );
+ ET tmp28( A(3,0)*tmp3 - A(3,3)*tmp12 + A(3,4)*tmp13 );
+ ET tmp29( A(3,0)*tmp4 - A(3,2)*tmp11 + A(3,5)*tmp14 );
+ ET tmp30( A(3,0)*tmp5 - A(3,2)*tmp12 + A(3,4)*tmp14 );
+ ET tmp31( A(3,0)*tmp6 - A(3,2)*tmp13 + A(3,3)*tmp14 );
+ ET tmp32( A(3,0)*tmp7 - A(3,1)*tmp11 + A(3,5)*tmp15 );
+ ET tmp33( A(3,0)*tmp8 - A(3,1)*tmp12 + A(3,4)*tmp15 );
+ ET tmp34( A(3,0)*tmp9 - A(3,1)*tmp13 + A(3,3)*tmp15 );
+ ET tmp35( A(3,0)*tmp10 - A(3,1)*tmp14 + A(3,2)*tmp15 );
+
+ ET tmp36( A(2,2)*tmp16 - A(2,3)*tmp17 + A(2,4)*tmp18 - A(2,5)*tmp19 );
+ ET tmp37( A(2,1)*tmp16 - A(2,3)*tmp20 + A(2,4)*tmp21 - A(2,5)*tmp22 );
+ ET tmp38( A(2,1)*tmp17 - A(2,2)*tmp20 + A(2,4)*tmp23 - A(2,5)*tmp24 );
+ ET tmp39( A(2,1)*tmp18 - A(2,2)*tmp21 + A(2,3)*tmp23 - A(2,5)*tmp25 );
+ ET tmp40( A(2,1)*tmp19 - A(2,2)*tmp22 + A(2,3)*tmp24 - A(2,4)*tmp25 );
+ ET tmp41( A(2,0)*tmp16 - A(2,3)*tmp26 + A(2,4)*tmp27 - A(2,5)*tmp28 );
+ ET tmp42( A(2,0)*tmp17 - A(2,2)*tmp26 + A(2,4)*tmp29 - A(2,5)*tmp30 );
+ ET tmp43( A(2,0)*tmp18 - A(2,2)*tmp27 + A(2,3)*tmp29 - A(2,5)*tmp31 );
+ ET tmp44( A(2,0)*tmp19 - A(2,2)*tmp28 + A(2,3)*tmp30 - A(2,4)*tmp31 );
+
+ B(0,0) = ET( real( A(1,1)*tmp36 - A(1,2)*tmp37 + A(1,3)*tmp38 - A(1,4)*tmp39 + A(1,5)*tmp40 ) );
+ B(0,1) = - A(0,1)*tmp36 + A(0,2)*tmp37 - A(0,3)*tmp38 + A(0,4)*tmp39 - A(0,5)*tmp40;
+ B(1,1) = ET( real( A(0,0)*tmp36 - A(0,2)*tmp41 + A(0,3)*tmp42 - A(0,4)*tmp43 + A(0,5)*tmp44 ) );
+
+ ET tmp45( A(2,0)*tmp20 - A(2,1)*tmp26 + A(2,4)*tmp32 - A(2,5)*tmp33 );
+ ET tmp46( A(2,0)*tmp21 - A(2,1)*tmp27 + A(2,3)*tmp32 - A(2,5)*tmp34 );
+ ET tmp47( A(2,0)*tmp22 - A(2,1)*tmp28 + A(2,3)*tmp33 - A(2,4)*tmp34 );
+ ET tmp48( A(2,0)*tmp23 - A(2,1)*tmp29 + A(2,2)*tmp32 - A(2,5)*tmp35 );
+ ET tmp49( A(2,0)*tmp24 - A(2,1)*tmp30 + A(2,2)*tmp33 - A(2,4)*tmp35 );
+
+ B(2,0) = A(1,0)*tmp37 - A(1,1)*tmp41 + A(1,3)*tmp45 - A(1,4)*tmp46 + A(1,5)*tmp47;
+ B(2,1) = - A(0,0)*tmp37 + A(0,1)*tmp41 - A(0,3)*tmp45 + A(0,4)*tmp46 - A(0,5)*tmp47;
+ B(3,0) = - A(1,0)*tmp38 + A(1,1)*tmp42 - A(1,2)*tmp45 + A(1,4)*tmp48 - A(1,5)*tmp49;
+ B(3,1) = A(0,0)*tmp38 - A(0,1)*tmp42 + A(0,2)*tmp45 - A(0,4)*tmp48 + A(0,5)*tmp49;
+
+ ET tmp50( A(2,0)*tmp25 - A(2,1)*tmp31 + A(2,2)*tmp34 - A(2,3)*tmp35 );
+
+ B(4,0) = A(1,0)*tmp39 - A(1,1)*tmp43 + A(1,2)*tmp46 - A(1,3)*tmp48 + A(1,5)*tmp50;
+ B(4,1) = - A(0,0)*tmp39 + A(0,1)*tmp43 - A(0,2)*tmp46 + A(0,3)*tmp48 - A(0,5)*tmp50;
+ B(5,0) = - A(1,0)*tmp40 + A(1,1)*tmp44 - A(1,2)*tmp47 + A(1,3)*tmp49 - A(1,4)*tmp50;
+ B(5,1) = A(0,0)*tmp40 - A(0,1)*tmp44 + A(0,2)*tmp47 - A(0,3)*tmp49 + A(0,4)*tmp50;
+
+ tmp36 = A(1,1)*tmp16 - A(1,3)*tmp20 + A(1,4)*tmp21 - A(1,5)*tmp22;
+ tmp37 = A(1,1)*tmp17 - A(1,2)*tmp20 + A(1,4)*tmp23 - A(1,5)*tmp24;
+ tmp38 = A(1,0)*tmp16 - A(1,3)*tmp26 + A(1,4)*tmp27 - A(1,5)*tmp28;
+ tmp39 = A(1,0)*tmp17 - A(1,2)*tmp26 + A(1,4)*tmp29 - A(1,5)*tmp30;
+ tmp40 = A(1,0)*tmp20 - A(1,1)*tmp26 + A(1,4)*tmp32 - A(1,5)*tmp33;
+ tmp41 = A(1,0)*tmp21 - A(1,1)*tmp27 + A(1,3)*tmp32 - A(1,5)*tmp34;
+ tmp42 = A(1,0)*tmp22 - A(1,1)*tmp28 + A(1,3)*tmp33 - A(1,4)*tmp34;
+ tmp43 = A(1,0)*tmp23 - A(1,1)*tmp29 + A(1,2)*tmp32 - A(1,5)*tmp35;
+ tmp44 = A(1,0)*tmp24 - A(1,1)*tmp30 + A(1,2)*tmp33 - A(1,4)*tmp35;
+
+ B(2,2) = ET( real( A(0,0)*tmp36 - A(0,1)*tmp38 + A(0,3)*tmp40 - A(0,4)*tmp41 + A(0,5)*tmp42 ) );
+ B(3,2) = - A(0,0)*tmp37 + A(0,1)*tmp39 - A(0,2)*tmp40 + A(0,4)*tmp43 - A(0,5)*tmp44;
+
+ tmp1 = A(0,3)*A(1,4) - A(0,4)*A(1,3);
+ tmp2 = A(0,2)*A(1,4) - A(0,4)*A(1,2);
+ tmp3 = A(0,2)*A(1,3) - A(0,3)*A(1,2);
+ tmp4 = A(0,1)*A(1,4) - A(0,4)*A(1,1);
+ tmp5 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp6 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ tmp7 = A(0,0)*A(1,4) - A(0,4)*A(1,0);
+ tmp8 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp9 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+ tmp10 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+ tmp11 = A(0,3)*A(1,5) - A(0,5)*A(1,3);
+ tmp12 = A(0,2)*A(1,5) - A(0,5)*A(1,2);
+ tmp13 = A(0,1)*A(1,5) - A(0,5)*A(1,1);
+ tmp14 = A(0,0)*A(1,5) - A(0,5)*A(1,0);
+ tmp15 = A(0,4)*A(1,5) - A(0,5)*A(1,4);
+
+ tmp16 = A(2,3)*tmp15 - A(2,4)*tmp11 + A(2,5)*tmp1;
+ tmp17 = A(2,2)*tmp15 - A(2,4)*tmp12 + A(2,5)*tmp2;
+ tmp18 = A(2,2)*tmp11 - A(2,3)*tmp12 + A(2,5)*tmp3;
+ tmp19 = A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3;
+ tmp20 = A(2,1)*tmp15 - A(2,4)*tmp13 + A(2,5)*tmp4;
+ tmp21 = A(2,1)*tmp11 - A(2,3)*tmp13 + A(2,5)*tmp5;
+ tmp22 = A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5;
+ tmp23 = A(2,1)*tmp12 - A(2,2)*tmp13 + A(2,5)*tmp6;
+ tmp24 = A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6;
+ tmp25 = A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6;
+ tmp26 = A(2,0)*tmp15 - A(2,4)*tmp14 + A(2,5)*tmp7;
+ tmp27 = A(2,0)*tmp11 - A(2,3)*tmp14 + A(2,5)*tmp8;
+ tmp28 = A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8;
+ tmp29 = A(2,0)*tmp12 - A(2,2)*tmp14 + A(2,5)*tmp9;
+ tmp30 = A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9;
+ tmp31 = A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9;
+ tmp32 = A(2,0)*tmp13 - A(2,1)*tmp14 + A(2,5)*tmp10;
+ tmp33 = A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10;
+ tmp34 = A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10;
+ tmp35 = A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10;
+
+ tmp36 = A(3,1)*tmp16 - A(3,3)*tmp20 + A(3,4)*tmp21 - A(3,5)*tmp22;
+ tmp37 = A(3,1)*tmp17 - A(3,2)*tmp20 + A(3,4)*tmp23 - A(3,5)*tmp24;
+ tmp38 = A(3,0)*tmp16 - A(3,3)*tmp26 + A(3,4)*tmp27 - A(3,5)*tmp28;
+ tmp39 = A(3,0)*tmp17 - A(3,2)*tmp26 + A(3,4)*tmp29 - A(3,5)*tmp30;
+ tmp40 = A(3,0)*tmp20 - A(3,1)*tmp26 + A(3,4)*tmp32 - A(3,5)*tmp33;
+ tmp41 = A(3,0)*tmp21 - A(3,1)*tmp27 + A(3,3)*tmp32 - A(3,5)*tmp34;
+ tmp42 = A(3,0)*tmp22 - A(3,1)*tmp28 + A(3,3)*tmp33 - A(3,4)*tmp34;
+ tmp43 = A(3,0)*tmp23 - A(3,1)*tmp29 + A(3,2)*tmp32 - A(3,5)*tmp35;
+ tmp44 = A(3,0)*tmp24 - A(3,1)*tmp30 + A(3,2)*tmp33 - A(3,4)*tmp35;
+
+ B(2,4) = - A(5,0)*tmp36 + A(5,1)*tmp38 - A(5,3)*tmp40 + A(5,4)*tmp41 - A(5,5)*tmp42;
+ B(2,5) = A(4,0)*tmp36 - A(4,1)*tmp38 + A(4,3)*tmp40 - A(4,4)*tmp41 + A(4,5)*tmp42;
+ B(3,4) = A(5,0)*tmp37 - A(5,1)*tmp39 + A(5,2)*tmp40 - A(5,4)*tmp43 + A(5,5)*tmp44;
+ B(3,5) = - A(4,0)*tmp37 + A(4,1)*tmp39 - A(4,2)*tmp40 + A(4,4)*tmp43 - A(4,5)*tmp44;
+
+ tmp36 = A(3,1)*tmp18 - A(3,2)*tmp21 + A(3,3)*tmp23 - A(3,5)*tmp25;
+ tmp37 = A(3,1)*tmp19 - A(3,2)*tmp22 + A(3,3)*tmp24 - A(3,4)*tmp25;
+ tmp38 = A(3,0)*tmp18 - A(3,2)*tmp27 + A(3,3)*tmp29 - A(3,5)*tmp31;
+ tmp39 = A(3,0)*tmp19 - A(3,2)*tmp28 + A(3,3)*tmp30 - A(3,4)*tmp31;
+ tmp40 = A(3,0)*tmp25 - A(3,1)*tmp31 + A(3,2)*tmp34 - A(3,3)*tmp35;
+
+ B(4,4) = - ET( real( A(5,0)*tmp36 - A(5,1)*tmp38 + A(5,2)*tmp41 - A(5,3)*tmp43 + A(5,5)*tmp40 ) );
+ B(4,5) = A(4,0)*tmp36 - A(4,1)*tmp38 + A(4,2)*tmp41 - A(4,3)*tmp43 + A(4,5)*tmp40;
+ B(5,5) = - ET( real( A(4,0)*tmp37 - A(4,1)*tmp39 + A(4,2)*tmp42 - A(4,3)*tmp44 + A(4,4)*tmp40 ) );
+
+ tmp36 = A(4,1)*tmp17 - A(4,2)*tmp20 + A(4,4)*tmp23 - A(4,5)*tmp24;
+ tmp37 = A(4,0)*tmp17 - A(4,2)*tmp26 + A(4,4)*tmp29 - A(4,5)*tmp30;
+ tmp38 = A(4,0)*tmp20 - A(4,1)*tmp26 + A(4,4)*tmp32 - A(4,5)*tmp33;
+ tmp39 = A(4,0)*tmp23 - A(4,1)*tmp29 + A(4,2)*tmp32 - A(4,5)*tmp35;
+ tmp40 = A(4,0)*tmp24 - A(4,1)*tmp30 + A(4,2)*tmp33 - A(4,4)*tmp35;
+
+ B(3,3) = - ET( real( A(5,0)*tmp36 - A(5,1)*tmp37 + A(5,2)*tmp38 - A(5,4)*tmp39 + A(5,5)*tmp40 ) );
+
+ B(0,2) = conj( B(2,0) );
+ B(0,3) = conj( B(3,0) );
+ B(0,4) = conj( B(4,0) );
+ B(0,5) = conj( B(5,0) );
+ B(1,0) = conj( B(0,1) );
+ B(1,2) = conj( B(2,1) );
+ B(1,3) = conj( B(3,1) );
+ B(1,4) = conj( B(4,1) );
+ B(1,5) = conj( B(5,1) );
+ B(2,3) = conj( B(3,2) );
+ B(4,2) = conj( B(2,4) );
+ B(4,3) = conj( B(3,4) );
+ B(5,2) = conj( B(2,5) );
+ B(5,3) = conj( B(3,5) );
+ B(5,4) = conj( B(4,5) );
+
+ const ET det( real( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) +
+ A(0,3)*B(3,0) + A(0,4)*B(4,0) + A(0,5)*B(5,0) ) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given Hermitian dense matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given Hermitian dense matrix by means of the most suited matrix
+// inversion algorithm. The matrix inversion fails if the given matrix is singular and not
+// invertible. In this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByDefault( HermitianMatrix<MT,SO,true>& m )
+{
+ invertByLDLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place LU-based inversion of the given Hermitian dense matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given Hermitian dense matrix by means of an LU decomposition.
+// The inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLU( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT tmp( m.matrix_ );
+ invertByLDLH( tmp );
+ m.matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given Hermitian dense matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given Hermitian dense matrix by means of a Bunch-Kaufman-based
+// decomposition. The inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLT( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT tmp( m.matrix_ );
+ invertByLDLT( tmp );
+ m.matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given Hermitian dense matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given Hermitian dense matrix by means of a Bunch-Kaufman-based
+// decomposition. The inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLH( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT tmp( m.matrix_ );
+ invertByLDLH( tmp );
+ m.matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Cholesky-based inversion of the given Hermitian dense matrix.
+// \ingroup hermitian_matrix
+//
+// \param m The Hermitian dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given Hermitian dense matrix by means of a Cholesky-based
+// decomposition. The inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLLH( HermitianMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT tmp( m.matrix_ );
+ invertByLLH( tmp );
+ m.matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a vector to a Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryAssign( const HermitianMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef ElementType_< HermitianMatrix<MT,SO,DF> > ET;
+
+ return ( IsBuiltin<ET>::value ||
+ column < row ||
+ (~rhs).size() <= column - row ||
+ isReal( (~rhs)[column-row] ) );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a vector to a Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryAssign( const HermitianMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef ElementType_< HermitianMatrix<MT,SO,DF> > ET;
+
+ return ( IsBuiltin<ET>::value ||
+ row < column ||
+ (~rhs).size() <= row - column ||
+ isReal( (~rhs)[row-column] ) );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a matrix to a Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAssign( const HermitianMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( ( row + M <= column ) || ( column + N <= row ) )
+ return true;
+
+ const bool lower( row > column );
+ const size_t size ( min( row + M, column + N ) - ( lower ? row : column ) );
+
+ if( size < 2UL )
+ return true;
+
+ const size_t subrow( lower ? 0UL : column - row );
+ const size_t subcol( lower ? row - column : 0UL );
+
+ return isHermitian( submatrix( ~rhs, subrow, subcol, size, size ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryAddAssign( const HermitianMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAddAssign( const HermitianMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a Hermitian
+// matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const HermitianMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a Hermitian
+// matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const HermitianMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to a Hermitian
+// matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side vector to be multiplied.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryMultAssign( const HermitianMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the division assignment of a vector to a Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// \param lhs The target left-hand side Hermitian matrix.
+// \param rhs The right-hand side vector divisor.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryDivAssign( const HermitianMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Rows< HermitianMatrix<MT,SO,DF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Columns< HermitianMatrix<MT,SO,DF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSquare< HermitianMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSymmetric< HermitianMatrix<MT,SO,DF> >
+ : public BoolConstant< IsBuiltin< ElementType_<MT> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsHermitian< HermitianMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAdaptor< HermitianMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsRestricted< HermitianMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasConstDataAccess< HermitianMatrix<MT,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAligned< HermitianMatrix<MT,SO,DF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsPadded< HermitianMatrix<MT,SO,DF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsResizable< HermitianMatrix<MT,SO,DF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RemoveAdaptor< HermitianMatrix<MT,SO,DF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< HermitianMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< HermitianMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< HermitianMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< DynamicMatrix<T,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< HermitianMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< HermitianMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CompressedMatrix<T,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = If_< IsSymmetric< HermitianMatrix<MT1,SO1,DF1> >
+ , SymmetricMatrix< AddTrait_<MT1,MT2> >
+ , AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = If_< IsSymmetric< HermitianMatrix<MT2,SO2,DF2> >
+ , SymmetricMatrix< AddTrait_<MT1,MT2> >
+ , AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = HermitianMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< HermitianMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< HermitianMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< HermitianMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< DynamicMatrix<T,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< HermitianMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< HermitianMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CompressedMatrix<T,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2> >
+{
+ using Type = If_< IsSymmetric< HermitianMatrix<MT1,SO1,DF1> >
+ , SymmetricMatrix< SubTrait_<MT1,MT2> >
+ , SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = If_< IsSymmetric< HermitianMatrix<MT2,SO2,DF2> >
+ , SymmetricMatrix< SubTrait_<MT1,MT2> >
+ , SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = HermitianMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< HermitianMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = HermitianMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< T, HermitianMatrix<MT,SO,DF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = HermitianMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< HermitianMatrix<MT,SO,DF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< StaticVector<T,N,true>, HermitianMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< HermitianMatrix<MT,SO,DF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< HybridVector<T,N,true>, HermitianMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< HermitianMatrix<MT,SO,DF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< DynamicVector<T,true>, HermitianMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF >
+struct MultTrait< HermitianMatrix<MT,SO,DF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF >
+struct MultTrait< CustomVector<T,AF,PF,true>, HermitianMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< HermitianMatrix<MT,SO,DF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< CompressedVector<T,true>, HermitianMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< HermitianMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< HermitianMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< HermitianMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< DynamicMatrix<T,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< HermitianMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< HermitianMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CompressedMatrix<T,SO1>, HermitianMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct DivTrait< HermitianMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = HermitianMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Abs >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Abs> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Floor >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Floor> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Ceil >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Ceil> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Conj >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Conj> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Real >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Real> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Imag >
+{
+ using Type = If_< IsBuiltin< ElementType_<MT> >
+ , HermitianMatrix< ForEachTrait_<MT,Imag> >
+ , ForEachTrait_<MT,Imag> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Sqrt >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Sqrt> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, InvSqrt >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,InvSqrt> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Cbrt >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Cbrt> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, InvCbrt >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,InvCbrt> >;
+};
+
+template< typename MT, bool SO, bool DF, typename ET >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Pow<ET> >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Pow<ET> > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Exp >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Exp > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Log >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Log > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Log10 >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Log10 > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Sin >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Sin > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Asin >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Asin > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Sinh >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Sinh > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Asinh >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Asinh > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Cos >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Cos > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Acos >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Acos > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Cosh >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Cosh > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Acosh >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Acosh > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Tan >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Tan > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Atan >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Atan > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Tanh >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Tanh > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Atanh >
+{
+ using Type = HermitianMatrix< ForEachTrait_< MT, Atanh > >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Erf >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Erf> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< HermitianMatrix<MT,SO,DF>, Erfc >
+{
+ using Type = HermitianMatrix< ForEachTrait_<MT,Erfc> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MathTrait< HermitianMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using HighType = HermitianMatrix< typename MathTrait<MT1,MT2>::HighType >;
+ using LowType = HermitianMatrix< typename MathTrait<MT1,MT2>::LowType >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct SubmatrixTrait< HermitianMatrix<MT,SO,DF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RowTrait< HermitianMatrix<MT,SO,DF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ColumnTrait< HermitianMatrix<MT,SO,DF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/LowerMatrix.h b/src/cpu/blaze/math/adaptors/LowerMatrix.h
new file mode 100644
index 00000000..153650fd
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/LowerMatrix.h
@@ -0,0 +1,2174 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/LowerMatrix.h
+// \brief Header file for the implementation of a lower matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_LOWERMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_LOWERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/lowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/lowermatrix/Dense.h>
+#include <blaze/math/adaptors/lowermatrix/Sparse.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/StaticMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/trtri.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsDivisor.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LOWERMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LowerMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF >
+inline void reset( LowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void reset( LowerMatrix<MT,SO,DF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF >
+inline void clear( LowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isDefault( const LowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isIntact( const LowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void swap( LowerMatrix<MT,SO,DF>& a, LowerMatrix<MT,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given lower matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( LowerMatrix<MT,SO,DF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given lower matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given lower matrix to their
+// default value. In case the given matrix is a \a rowMajor matrix the function resets the values
+// in row \a i, if it is a \a columnMajor matrix the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( LowerMatrix<MT,SO,DF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given lower matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void clear( LowerMatrix<MT,SO,DF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given lower matrix is in default state.
+// \ingroup lower_matrix
+//
+// \param m The lower matrix to be tested for its default state.
+// \return \a true in case the given matrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the matrix is in default state. For instance, in case the
+// matrix is instantiated for a built-in integral or floating point data type, the function
+// returns \a true in case all matrix elements are 0 and \a false in case any matrix element
+// is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+
+ LowerMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault( const LowerMatrix<MT,SO,DF>& m )
+{
+ return isDefault( m.matrix_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given lower matrix are intact.
+// \ingroup lower_matrix
+//
+// \param m The lower matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the lower matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+
+ LowerMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isIntact( const LowerMatrix<MT,SO,DF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup lower_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void swap( LowerMatrix<MT,SO,DF>& a, LowerMatrix<MT,SO,DF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given lower dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given lower dense \f$ 2 \times 2 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert2x2( LowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ const ET det( A(0,0) * A(1,1) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+ const ET a11( A(0,0) * idet );
+
+ A(0,0) = A(1,1) * idet;
+ A(1,0) = -A(1,0) * idet;
+ A(1,1) = a11;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given lower dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given lower dense \f$ 3 \times 3 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert3x3( LowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,3UL,3UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp( A(1,1)*A(2,2) );
+ const ET det( A(0,0)*tmp );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B(0,0) = tmp;
+ B(1,0) = - A(1,0)*A(2,2);
+ B(2,0) = A(1,0)*A(2,1) - A(1,1)*A(2,0);
+ B(1,1) = A(0,0)*A(2,2);
+ B(2,1) = - A(0,0)*A(2,1);
+ B(2,2) = A(0,0)*A(1,1);
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given lower dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given lower dense \f$ 4 \times 4 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert4x4( LowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,4UL,4UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp1( A(2,2)*A(3,3) );
+ const ET tmp2( A(2,1)*A(3,3) );
+ const ET tmp3( A(2,1)*A(3,2) - A(2,2)*A(3,1) );
+ const ET tmp4( A(0,0)*A(1,1) );
+
+ const ET det( tmp4 * A(2,2) * A(3,3) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B(0,0) = A(1,1)*tmp1;
+ B(1,0) = - A(1,0)*tmp1;
+ B(2,0) = A(1,0)*tmp2 - A(1,1)*A(2,0)*A(3,3);
+ B(3,0) = A(1,1)*( A(2,0)*A(3,2) - A(2,2)*A(3,0) ) - A(1,0)*tmp3;
+ B(1,1) = A(0,0)*tmp1;
+ B(2,1) = - A(0,0)*tmp2;
+ B(3,1) = A(0,0)*tmp3;
+ B(2,2) = A(3,3)*tmp4;
+ B(3,2) = - A(3,2)*tmp4;
+ B(3,3) = A(2,2)*tmp4;
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given lower dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given lower dense \f$ 5 \times 5 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert5x5( LowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,5UL,5UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp1( A(3,3)*A(4,4) );
+ const ET tmp2( A(3,2)*A(4,4) );
+ const ET tmp3( A(3,2)*A(4,3) - A(3,3)*A(4,2) );
+ const ET tmp4( A(0,0)*A(1,1) );
+
+ const ET tmp5 ( A(2,2)*tmp1 );
+ const ET tmp6 ( A(2,1)*tmp1 );
+ const ET tmp7 ( A(2,1)*tmp2 - A(2,2)*A(3,1)*A(4,4) );
+ const ET tmp8 ( A(2,1)*tmp3 - A(2,2)*( A(3,1)*A(4,3) - A(3,3)*A(4,1) ) );
+ const ET tmp9 ( A(3,2)*tmp4 );
+ const ET tmp10( A(2,2)*tmp4 );
+
+ B(0,0) = A(1,1)*tmp5;
+ B(1,0) = - A(1,0)*tmp5;
+ B(2,0) = A(1,0)*tmp6 - A(1,1)*A(2,0)*tmp1;
+ B(3,0) = A(1,1)*( A(2,0)*tmp2 - A(2,2)*A(3,0)*A(4,4) ) - A(1,0)*tmp7;
+ B(4,0) = A(1,0)*tmp8 - A(1,1)*( A(2,0)*tmp3 - A(2,2)*( A(3,0)*A(4,3) - A(3,3)*A(4,0) ) );
+ B(1,1) = A(0,0)*tmp5;
+ B(2,1) = - A(0,0)*tmp6;
+ B(3,1) = A(0,0)*tmp7;
+ B(4,1) = - A(0,0)*tmp8;
+ B(2,2) = A(0,0)*A(1,1)*tmp1;
+ B(3,2) = - A(4,4)*tmp9;
+ B(4,2) = A(4,3)*tmp9 - A(4,2)*A(3,3)*tmp4;
+ B(3,3) = A(4,4)*tmp10;
+ B(4,3) = - A(4,3)*tmp10;
+ B(4,4) = A(3,3)*tmp10;
+
+ const ET det( B(4,4) * A(4,4) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given lower dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given lower dense \f$ 6 \times 6 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert6x6( LowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,6UL,6UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp1( A(4,4)*A(5,5) );
+ const ET tmp2( A(4,3)*A(5,5) );
+ const ET tmp3( A(4,3)*A(5,4) - A(4,4)*A(5,3) );
+
+ const ET tmp4( A(3,3)*tmp1 );
+ const ET tmp5( A(3,2)*tmp1 );
+ const ET tmp6( A(3,2)*tmp2 - A(3,3)*A(4,2)*A(5,5) );
+ const ET tmp7( A(3,2)*tmp3 - A(3,3)*( A(4,2)*A(5,4) - A(4,4)*A(5,2) ) );
+ const ET tmp8( A(0,0)*A(1,1)*A(2,2) );
+
+ const ET tmp9 ( A(2,2)*tmp4 );
+ const ET tmp10( A(2,1)*tmp4 );
+ const ET tmp11( A(2,1)*tmp5 - A(2,2)*A(3,1)*tmp1 );
+ const ET tmp12( A(2,1)*tmp6 - A(2,2)*( A(3,1)*tmp2 - A(3,3)*A(4,1)*A(5,5) ) );
+ const ET tmp13( A(2,1)*tmp7 - A(2,2)*( A(3,1)*tmp3 - A(3,3)*( A(4,1)*A(5,4) - A(4,4)*A(5,1) ) ) );
+ const ET tmp14( A(4,4)*tmp8 );
+ const ET tmp15( A(4,3)*tmp8 );
+ const ET tmp16( A(3,3)*tmp8 );
+
+ B(0,0) = A(1,1)*tmp9;
+ B(1,0) = - A(1,0)*tmp9;
+ B(2,0) = A(1,0)*tmp10 - A(1,1)*A(2,0)*tmp4;
+ B(3,0) = - A(1,0)*tmp11 + A(1,1)*( A(2,0)*tmp5 - A(2,2)*A(3,0)*tmp1 );
+ B(4,0) = A(1,0)*tmp12 - A(1,1)*( A(2,0)*tmp6 - A(2,2)*( A(3,0)*tmp2 - A(3,3)*A(4,0)*A(5,5) ) );
+ B(5,0) = - A(1,0)*tmp13 + A(1,1)*( A(2,0)*tmp7 - A(2,2)*( A(3,0)*tmp3 - A(3,3)*( A(4,0)*A(5,4) - A(4,4)*A(5,0) ) ) );
+ B(1,1) = A(0,0)*tmp9;
+ B(2,1) = - A(0,0)*tmp10;
+ B(3,1) = A(0,0)*tmp11;
+ B(4,1) = - A(0,0)*tmp12;
+ B(5,1) = A(0,0)*tmp13;
+ B(2,2) = A(0,0)*A(1,1)*tmp4;
+ B(3,2) = - A(0,0)*A(1,1)*tmp5;
+ B(4,2) = A(0,0)*A(1,1)*tmp6;
+ B(5,2) = - A(0,0)*A(1,1)*tmp7;
+ B(3,3) = A(5,5)*tmp14;
+ B(4,3) = - A(5,5)*tmp15;
+ B(5,3) = A(5,4)*tmp15 - A(5,3)*tmp14;
+ B(4,4) = A(5,5)*tmp16 - A(5,3)*A(3,5)*tmp8;
+ B(5,4) = - A(5,4)*tmp16;
+ B(5,5) = A(4,4)*tmp16;
+
+ const ET det( B(5,5)*A(5,5) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given lower dense matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given lower dense matrix by means of the most suited matrix inversion
+// algorithm. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByDefault( LowerMatrix<MT,SO,true>& m )
+{
+ invertByLU( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place LU-based inversion of the given lower dense matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given lower dense matrix by means of an LU decomposition. The
+// matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLU( LowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ DerestrictTrait_<MT> A( derestrict( ~m ) );
+
+ trtri( A, 'L', 'N' );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given lower dense matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given lower dense matrix by means of a Bunch-Kaufman decomposition.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLT( LowerMatrix<MT,SO,true>& m )
+{
+ invertByLLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given lower dense matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given lower dense matrix by means of a Bunch-Kaufman decomposition.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLH( LowerMatrix<MT,SO,true>& m )
+{
+ invertByLLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Cholesky-based inversion of the given lower dense matrix.
+// \ingroup lower_matrix
+//
+// \param m The lower dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given lower dense matrix by means of a Cholesky decomposition. The
+// matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLLH( LowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( isDiagonal( ~m ), "Violation of preconditions detected" );
+
+ DerestrictTrait_<MT> A( derestrict( ~m ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ if( !isDivisor( A(i,i) ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ invert( A(i,i) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief LU decomposition of the given lower dense matrix.
+// \ingroup lower_matrix
+//
+// \param A The lower matrix to be decomposed.
+// \param L The resulting lower triangular matrix.
+// \param U The resulting upper triangular matrix.
+// \param P The resulting permutation matrix.
+// \return void
+//
+// This function performs the dense matrix (P)LU decomposition of a lower n-by-n matrix. The
+// resulting decomposition is written to the three distinct matrices \c L, \c U, and \c P, which
+// are resized to the correct dimensions (if possible and necessary).
+//
+// \note The LU decomposition will never fail, even for singular matrices. However, in case of a
+// singular matrix the resulting decomposition cannot be used for a matrix inversion or solving
+// a linear system of equations.
+*/
+template< typename MT1, bool SO1, typename MT2, typename MT3, typename MT4, bool SO2 >
+inline void lu( const LowerMatrix<MT1,SO1,true>& A, DenseMatrix<MT2,SO1>& L,
+ DenseMatrix<MT3,SO1>& U, Matrix<MT4,SO2>& P )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE( MT3 );
+
+ typedef ElementType_<MT3> ET3;
+ typedef ElementType_<MT4> ET4;
+
+ const size_t n( (~A).rows() );
+
+ DerestrictTrait_<MT3> U2( derestrict( ~U ) );
+
+ (~L) = A;
+
+ resize( ~U, n, n );
+ reset( U2 );
+
+ resize( ~P, n, n );
+ reset( ~P );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ U2(i,i) = ET3(1);
+ (~P)(i,i) = ET4(1);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const LowerMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( column <= row )
+ return true;
+
+ const size_t iend( min( column - row, (~rhs).size() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const LowerMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t ibegin( ( row < column )?( 0UL ):( row - column + 1UL ) );
+
+ for( size_t i=ibegin; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const LowerMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( column <= row )
+ return true;
+
+ const RhsIterator last( (~rhs).lowerBound( column - row ) );
+
+ for( RhsIterator element=(~rhs).begin(); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const LowerMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ const RhsIterator last( (~rhs).end() );
+ RhsIterator element( (~rhs).lowerBound( ( row < column )?( 0UL ):( row - column + 1UL ) ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const LowerMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t iend( min( column + N - row - 1UL, M ) );
+
+ for( size_t i=0UL; i<iend; ++i )
+ {
+ const bool containsDiagonal( row + i >= column );
+ const size_t jbegin( ( containsDiagonal )?( row + i - column + 1UL ):( 0UL ) );
+
+ for( size_t j=jbegin; j<N; ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const LowerMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t jbegin( ( row < column )?( 0UL ):( row - column + 1UL ) );
+
+ for( size_t j=jbegin; j<N; ++j )
+ {
+ const size_t iend( min( column + j - row, M ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const LowerMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t iend( min( column + N - row - 1UL, M ) );
+
+ for( size_t i=0UL; i<iend; ++i )
+ {
+ const bool containsDiagonal( row + i >= column );
+ const size_t index( ( containsDiagonal )?( row + i - column + 1UL ):( 0UL ) );
+
+ const RhsIterator last( (~rhs).end(i) );
+ RhsIterator element( (~rhs).lowerBound( i, index ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const LowerMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t jbegin( ( row < column )?( 0UL ):( row - column + 1UL ) );
+
+ for( size_t j=jbegin; j<N; ++j )
+ {
+ const size_t index( column + j - row );
+ const RhsIterator last( (~rhs).lowerBound( min( index, M ), j ) );
+
+ for( RhsIterator element=(~rhs).begin(j); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryAddAssign( const LowerMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAddAssign( const LowerMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const LowerMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a lower matrix.
+// \ingroup lower_matrix
+//
+// \param lhs The target left-hand side lower matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const LowerMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns a reference to the instance without the access restrictions to the upper part.
+// \ingroup lower_matrix
+//
+// \param m The lower matrix to be derestricted.
+// \return Reference to the matrix without access restrictions.
+//
+// This function returns a reference to the given lower matrix instance that has no access
+// restrictions to the upper part of the matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline MT& derestrict( LowerMatrix<MT,SO,DF>& m )
+{
+ return m.matrix_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Rows< LowerMatrix<MT,SO,DF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Columns< LowerMatrix<MT,SO,DF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSquare< LowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsLower< LowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAdaptor< LowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsRestricted< LowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasConstDataAccess< LowerMatrix<MT,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAligned< LowerMatrix<MT,SO,DF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsPadded< LowerMatrix<MT,SO,DF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsResizable< LowerMatrix<MT,SO,DF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RemoveAdaptor< LowerMatrix<MT,SO,DF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct DerestrictTrait< LowerMatrix<MT,SO,DF> >
+{
+ using Type = MT&;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< LowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< LowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< LowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< DynamicMatrix<T,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< LowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< LowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CompressedMatrix<T,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< LowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< LowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< LowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< DynamicMatrix<T,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< LowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< LowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CompressedMatrix<T,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< LowerMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = LowerMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< T, LowerMatrix<MT,SO,DF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = LowerMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< LowerMatrix<MT,SO,DF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< StaticVector<T,N,true>, LowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< LowerMatrix<MT,SO,DF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< HybridVector<T,N,true>, LowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< LowerMatrix<MT,SO,DF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< DynamicVector<T,true>, LowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF >
+struct MultTrait< LowerMatrix<MT,SO,DF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF >
+struct MultTrait< CustomVector<T,AF,PF,true>, LowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< LowerMatrix<MT,SO,DF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< CompressedVector<T,true>, LowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< LowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< LowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< LowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< DynamicMatrix<T,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< LowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< LowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CompressedMatrix<T,SO1>, LowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< MultTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct DivTrait< LowerMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = LowerMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Abs >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Abs> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Floor >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Floor> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Ceil >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Ceil> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Conj >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Conj> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Real >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Real> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Imag >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Imag> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Sin >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Sin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Asin >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Asin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Sinh >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Sinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Asinh >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Asinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Tan >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Tan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Atan >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Atan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Tanh >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Tanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Atanh >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Atanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< LowerMatrix<MT,SO,DF>, Erf >
+{
+ using Type = LowerMatrix< ForEachTrait_<MT,Erf> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MathTrait< LowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using HighType = LowerMatrix< typename MathTrait<MT1,MT2>::HighType >;
+ using LowType = LowerMatrix< typename MathTrait<MT1,MT2>::LowType >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct SubmatrixTrait< LowerMatrix<MT,SO,DF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RowTrait< LowerMatrix<MT,SO,DF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ColumnTrait< LowerMatrix<MT,SO,DF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/StrictlyLowerMatrix.h b/src/cpu/blaze/math/adaptors/StrictlyLowerMatrix.h
new file mode 100644
index 00000000..b6523cfd
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/StrictlyLowerMatrix.h
@@ -0,0 +1,1731 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/StrictlyLowerMatrix.h
+// \brief Header file for the implementation of a strictly lower triangular matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYLOWERMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYLOWERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/adaptors/lowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlylowermatrix/Dense.h>
+#include <blaze/math/adaptors/strictlylowermatrix/Sparse.h>
+#include <blaze/math/adaptors/unilowermatrix/BaseTemplate.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// STRICTLYLOWERMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name StrictlyLowerMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF >
+inline void reset( StrictlyLowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void reset( StrictlyLowerMatrix<MT,SO,DF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF >
+inline void clear( StrictlyLowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isDefault( const StrictlyLowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isIntact( const StrictlyLowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void swap( StrictlyLowerMatrix<MT,SO,DF>& a, StrictlyLowerMatrix<MT,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given strictly lower matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param m The strictly lower matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( StrictlyLowerMatrix<MT,SO,DF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given strictly lower matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param m The strictly lower matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given strictly lower matrix
+// to their default value. In case the given matrix is a \a rowMajor matrix the function resets
+// the values in row \a i, if it is a \a columnMajor matrix the function resets the values in
+// column \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( StrictlyLowerMatrix<MT,SO,DF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given strictly lower matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param m The strictly lower matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void clear( StrictlyLowerMatrix<MT,SO,DF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given resizable strictly lower matrix is in default state.
+// \ingroup strictly_lower_matrix
+//
+// \param m The strictly lower matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the resizable strictly lower triangular matrix is in default
+// state.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault_backend( const StrictlyLowerMatrix<MT,SO,DF>& m, TrueType )
+{
+ return ( m.rows() == 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given fixed-size strictly lower matrix is in default state.
+// \ingroup strictly_lower_matrix
+//
+// \param m The strictly lower matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the fixed-size strictly lower triangular matrix is in default
+// state.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault_backend( const StrictlyLowerMatrix<MT,SO,DF>& m, FalseType )
+{
+ return isIdentity( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given strictly lower matrix is in default state.
+// \ingroup strictly_lower_matrix
+//
+// \param m The strictly lower matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the strictly lower triangular matrix is in default state. The
+// following example demonstrates the use of the \a isDefault function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyLowerMatrix;
+
+ StrictlyLowerMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault( const StrictlyLowerMatrix<MT,SO,DF>& m )
+{
+ return isDefault_backend( m, typename IsResizable<MT>::Type() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given strictly lower matrix are intact.
+// \ingroup strictly_lower_matrix
+//
+// \param m The strictly lower matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the strictly lower matrix are intact, i.e.
+// if its state is valid. In case the invariants are intact, the function returns \a true, else
+// it will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyLowerMatrix;
+
+ StrictlyLowerMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isIntact( const StrictlyLowerMatrix<MT,SO,DF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup strictly_lower_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void swap( StrictlyLowerMatrix<MT,SO,DF>& a, StrictlyLowerMatrix<MT,SO,DF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const StrictlyLowerMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( column < row )
+ return true;
+
+ const size_t iend( min( column - row + 1UL, (~rhs).size() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const StrictlyLowerMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t ibegin( ( row <= column )?( 0UL ):( row - column ) );
+
+ for( size_t i=ibegin; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const StrictlyLowerMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( column < row )
+ return true;
+
+ const RhsIterator last( (~rhs).lowerBound( column - row + 1UL ) );
+
+ for( RhsIterator element=(~rhs).begin(); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const StrictlyLowerMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ const RhsIterator last( (~rhs).end() );
+ RhsIterator element( (~rhs).lowerBound( ( row <= column )?( 0UL ):( row - column ) ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const StrictlyLowerMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t iend( min( column + N - row, M ) );
+
+ for( size_t i=0UL; i<iend; ++i )
+ {
+ const bool containsDiagonal( row + i >= column );
+ const size_t jbegin( ( containsDiagonal )?( row + i - column ):( 0UL ) );
+
+ for( size_t j=jbegin; j<N; ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const StrictlyLowerMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t jbegin( ( row <= column )?( 0UL ):( row - column ) );
+
+ for( size_t j=jbegin; j<N; ++j )
+ {
+ const size_t iend( min( column + j - row + 1UL, M ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const StrictlyLowerMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t iend( min( column + N - row, M ) );
+
+ for( size_t i=0UL; i<iend; ++i )
+ {
+ const bool containsDiagonal( row + i >= column );
+ const size_t index( ( containsDiagonal )?( row + i - column ):( 0UL ) );
+
+ const RhsIterator last( (~rhs).end(i) );
+ RhsIterator element( (~rhs).lowerBound( i, index ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const StrictlyLowerMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t jbegin( ( row < column )?( 0UL ):( row - column ) );
+
+ for( size_t j=jbegin; j<N; ++j )
+ {
+ const size_t index( column + j - row + 1UL );
+ const RhsIterator last( (~rhs).lowerBound( min( index, M ), j ) );
+
+ for( RhsIterator element=(~rhs).begin(j); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryAddAssign( const StrictlyLowerMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a strictly lower
+// matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAddAssign( const StrictlyLowerMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a strictly
+// lower matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const StrictlyLowerMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a strictly
+// lower matrix.
+// \ingroup strictly_lower_matrix
+//
+// \param lhs The target left-hand side strictly lower matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const StrictlyLowerMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns a reference to the instance without the access restrictions to the upper part.
+// \ingroup math_shims
+//
+// \param m The strictly lower matrix to be derestricted.
+// \return Reference to the matrix without access restrictions.
+//
+// This function returns a reference to the given strictly lower matrix instance that has no
+// access restrictions to the upper part of the matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline MT& derestrict( StrictlyLowerMatrix<MT,SO,DF>& m )
+{
+ return m.matrix_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Rows< StrictlyLowerMatrix<MT,SO,DF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Columns< StrictlyLowerMatrix<MT,SO,DF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSquare< StrictlyLowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsStrictlyLower< StrictlyLowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAdaptor< StrictlyLowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsRestricted< StrictlyLowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasConstDataAccess< StrictlyLowerMatrix<MT,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAligned< StrictlyLowerMatrix<MT,SO,DF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsPadded< StrictlyLowerMatrix<MT,SO,DF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsResizable< StrictlyLowerMatrix<MT,SO,DF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RemoveAdaptor< StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct DerestrictTrait< StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = MT&;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< StrictlyLowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< StrictlyLowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< StrictlyLowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< DynamicMatrix<T,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< StrictlyLowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< StrictlyLowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CompressedMatrix<T,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = UniLowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = UniLowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< StrictlyLowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< StrictlyLowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< StrictlyLowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< DynamicMatrix<T,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< StrictlyLowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< StrictlyLowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CompressedMatrix<T,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct SubTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = UniLowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< StrictlyLowerMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< T, StrictlyLowerMatrix<MT,SO,DF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< StrictlyLowerMatrix<MT,SO,DF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< StaticVector<T,N,true>, StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< StrictlyLowerMatrix<MT,SO,DF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< HybridVector<T,N,true>, StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< StrictlyLowerMatrix<MT,SO,DF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< DynamicVector<T,true>, StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF >
+struct MultTrait< StrictlyLowerMatrix<MT,SO,DF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF >
+struct MultTrait< CustomVector<T,AF,PF,true>, StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< StrictlyLowerMatrix<MT,SO,DF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< CompressedVector<T,true>, StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< StrictlyLowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< StrictlyLowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< StrictlyLowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< DynamicMatrix<T,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< StrictlyLowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< StrictlyLowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CompressedMatrix<T,SO1>, StrictlyLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyLowerMatrix< MultTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct DivTrait< StrictlyLowerMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = StrictlyLowerMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Abs >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Abs> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Floor >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Floor> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Ceil >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Ceil> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Conj >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Conj> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Real >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Real> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Imag >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Imag> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Sin >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Sin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Asin >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Asin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Sinh >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Sinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Asinh >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Asinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Tan >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Tan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Atan >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Atan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Tanh >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Tanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Atanh >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Atanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyLowerMatrix<MT,SO,DF>, Erf >
+{
+ using Type = StrictlyLowerMatrix< ForEachTrait_<MT,Erf> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MathTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using HighType = StrictlyLowerMatrix< typename MathTrait<MT1,MT2>::HighType >;
+ using LowType = StrictlyLowerMatrix< typename MathTrait<MT1,MT2>::LowType >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct SubmatrixTrait< StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RowTrait< StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ColumnTrait< StrictlyLowerMatrix<MT,SO,DF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/StrictlyUpperMatrix.h b/src/cpu/blaze/math/adaptors/StrictlyUpperMatrix.h
new file mode 100644
index 00000000..4b0f4195
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/StrictlyUpperMatrix.h
@@ -0,0 +1,1840 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/StrictlyUpperMatrix.h
+// \brief Header file for the implementation of a strictly upper triangular matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlyuppermatrix/Dense.h>
+#include <blaze/math/adaptors/strictlyuppermatrix/Sparse.h>
+#include <blaze/math/adaptors/uniuppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/uppermatrix/BaseTemplate.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// STRICTLYUPPERMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name StrictlyUpperMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF >
+inline void reset( StrictlyUpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void reset( StrictlyUpperMatrix<MT,SO,DF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF >
+inline void clear( StrictlyUpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isDefault( const StrictlyUpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isIntact( const StrictlyUpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void swap( StrictlyUpperMatrix<MT,SO,DF>& a, StrictlyUpperMatrix<MT,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given strictly upper matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param m The strictly upper matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( StrictlyUpperMatrix<MT,SO,DF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given strictly upper matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param m The strictly upper matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given strictly upper matrix
+// to their default value. In case the given matrix is a \a rowMajor matrix the function resets
+// the values in row \a i, if it is a \a columnMajor matrix the function resets the values in
+// column \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( StrictlyUpperMatrix<MT,SO,DF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given strictly upper matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param m The strictly upper matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void clear( StrictlyUpperMatrix<MT,SO,DF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given resizable strictly upper matrix is in default state.
+// \ingroup strictly_upper_matrix
+//
+// \param m The strictly upper matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the resizable strictly upper triangular matrix is in default
+// state.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault_backend( const StrictlyUpperMatrix<MT,SO,DF>& m, TrueType )
+{
+ return ( m.rows() == 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given fixed-size strictly upper matrix is in default state.
+// \ingroup strictly_upper_matrix
+//
+// \param m The strictly upper matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the fixed-size strictly upper triangular matrix is in default
+// state.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault_backend( const StrictlyUpperMatrix<MT,SO,DF>& m, FalseType )
+{
+ return isIdentity( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given strictly upper matrix is in default state.
+// \ingroup strictly_upper_matrix
+//
+// \param m The strictly upper matrix to be tested for its default state.
+// \return \a true in case the given matrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the strictly upper triangular matrix is in default state. The
+// following example demonstrates the use of the \a isDefault function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::rowMajor;
+
+ StrictlyUpperMatrix< DynamicMatrix<int,rowMajor> > A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault( const StrictlyUpperMatrix<MT,SO,DF>& m )
+{
+ return isDefault_backend( m, typename IsResizable<MT>::Type() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given strictly upper matrix are intact.
+// \ingroup strictly_upper_matrix
+//
+// \param m The strictly upper matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the strictly upper matrix are intact, i.e.
+// if its state is valid. In case the invariants are intact, the function returns \a true, else
+// it will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyUpperMatrix;
+
+ StrictlyUpperMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isIntact( const StrictlyUpperMatrix<MT,SO,DF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup strictly_upper_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void swap( StrictlyUpperMatrix<MT,SO,DF>& a, StrictlyUpperMatrix<MT,SO,DF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const StrictlyUpperMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t ibegin( ( column <= row )?( 0UL ):( column - row ) );
+
+ for( size_t i=ibegin; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const StrictlyUpperMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( row < column )
+ return true;
+
+ const size_t iend( min( row - column + 1UL, (~rhs).size() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const StrictlyUpperMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ const RhsIterator last( (~rhs).end() );
+ RhsIterator element( (~rhs).lowerBound( ( column <= row )?( 0UL ):( column - row ) ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const StrictlyUpperMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( row < column )
+ return true;
+
+ const RhsIterator last( (~rhs).lowerBound( row - column + 1UL ) );
+
+ for( RhsIterator element=(~rhs).begin(); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const StrictlyUpperMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t ibegin( ( column <= row )?( 0UL ):( column - row ) );
+
+ for( size_t i=ibegin; i<M; ++i )
+ {
+ const size_t jend( min( row + i - column + 1UL, N ) );
+
+ for( size_t j=0UL; j<jend; ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const StrictlyUpperMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t jend( min( row + M - column, N ) );
+
+ for( size_t j=0UL; j<jend; ++j )
+ {
+ const bool containsDiagonal( column + j >= row );
+ const size_t ibegin( ( containsDiagonal )?( column + j - row ):( 0UL ) );
+
+ for( size_t i=ibegin; i<M; ++i ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const StrictlyUpperMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t ibegin( ( column < row )?( 0UL ):( column - row ) );
+
+ for( size_t i=ibegin; i<M; ++i )
+ {
+ const size_t index( row + i - column + 1UL );
+ const RhsIterator last( (~rhs).lowerBound( i, min( index, N ) ) );
+
+ for( RhsIterator element=(~rhs).begin(i); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const StrictlyUpperMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t jend( min( row + M - column, N ) );
+
+ for( size_t j=0UL; j<jend; ++j )
+ {
+ const bool containsDiagonal( column + j >= row );
+ const size_t index( ( containsDiagonal )?( column + j - row ):( 0UL ) );
+
+ const RhsIterator last( (~rhs).end(j) );
+ RhsIterator element( (~rhs).lowerBound( index, j ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryAddAssign( const StrictlyUpperMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a strictly upper
+// matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAddAssign( const StrictlyUpperMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a strictly
+// upper matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const StrictlyUpperMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a strictly
+// upper matrix.
+// \ingroup strictly_upper_matrix
+//
+// \param lhs The target left-hand side strictly upper matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const StrictlyUpperMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns a reference to the instance without the access restrictions to the lower part.
+// \ingroup math_shims
+//
+// \param m The strictly upper matrix to be derestricted.
+// \return Reference to the matrix without access restrictions.
+//
+// This function returns a reference to the given strictly upper matrix instance that has no
+// access restrictions to the lower part of the matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline MT& derestrict( StrictlyUpperMatrix<MT,SO,DF>& m )
+{
+ return m.matrix_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Rows< StrictlyUpperMatrix<MT,SO,DF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Columns< StrictlyUpperMatrix<MT,SO,DF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSquare< StrictlyUpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsStrictlyUpper< StrictlyUpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAdaptor< StrictlyUpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsRestricted< StrictlyUpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasConstDataAccess< StrictlyUpperMatrix<MT,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAligned< StrictlyUpperMatrix<MT,SO,DF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsPadded< StrictlyUpperMatrix<MT,SO,DF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsResizable< StrictlyUpperMatrix<MT,SO,DF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RemoveAdaptor< StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct DerestrictTrait< StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = MT&;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< StrictlyUpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< StrictlyUpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< StrictlyUpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< DynamicMatrix<T,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< StrictlyUpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< StrictlyUpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CompressedMatrix<T,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UniUpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UniUpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< StrictlyUpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< StrictlyUpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< StrictlyUpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< DynamicMatrix<T,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< StrictlyUpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< StrictlyUpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CompressedMatrix<T,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UniUpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< StrictlyUpperMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< T, StrictlyUpperMatrix<MT,SO,DF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< StrictlyUpperMatrix<MT,SO,DF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< StaticVector<T,N,true>, StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< StrictlyUpperMatrix<MT,SO,DF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< HybridVector<T,N,true>, StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< StrictlyUpperMatrix<MT,SO,DF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< DynamicVector<T,true>, StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF >
+struct MultTrait< StrictlyUpperMatrix<MT,SO,DF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF >
+struct MultTrait< CustomVector<T,AF,PF,true>, StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< StrictlyUpperMatrix<MT,SO,DF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< CompressedVector<T,true>, StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< StrictlyUpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< StrictlyUpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< StrictlyUpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< DynamicMatrix<T,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< StrictlyUpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< StrictlyUpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CompressedMatrix<T,SO1>, StrictlyUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = StrictlyUpperMatrix< MultTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct DivTrait< StrictlyUpperMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = StrictlyUpperMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Abs >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Abs> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Floor >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Floor> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Ceil >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Ceil> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Conj >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Conj> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Real >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Real> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Imag >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Imag> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Sin >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Sin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Asin >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Asin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Sinh >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Sinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Asinh >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Asinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Tan >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Tan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Atan >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Atan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Tanh >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Tanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Atanh >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Atanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< StrictlyUpperMatrix<MT,SO,DF>, Erf >
+{
+ using Type = StrictlyUpperMatrix< ForEachTrait_<MT,Erf> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MathTrait< StrictlyUpperMatrix<MT1,SO1,DF1>, StrictlyUpperMatrix<MT2,SO2,DF2> >
+{
+ using HighType = StrictlyUpperMatrix< typename MathTrait<MT1,MT2>::HighType >;
+ using LowType = StrictlyUpperMatrix< typename MathTrait<MT1,MT2>::LowType >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct SubmatrixTrait< StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RowTrait< StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ColumnTrait< StrictlyUpperMatrix<MT,SO,DF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/SymmetricMatrix.h b/src/cpu/blaze/math/adaptors/SymmetricMatrix.h
new file mode 100644
index 00000000..a104ca67
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/SymmetricMatrix.h
@@ -0,0 +1,1879 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/SymmetricMatrix.h
+// \brief Header file for the implementation of a symmetric matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/symmetricmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/symmetricmatrix/DenseNonNumeric.h>
+#include <blaze/math/adaptors/symmetricmatrix/DenseNumeric.h>
+#include <blaze/math/adaptors/symmetricmatrix/SparseNonNumeric.h>
+#include <blaze/math/adaptors/symmetricmatrix/SparseNumeric.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/dense/StaticMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsDivisor.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SYMMETRICMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SymmetricMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF, bool NF >
+inline void reset( SymmetricMatrix<MT,SO,DF,NF>& m );
+
+template< typename MT, bool SO, bool DF, bool NF >
+inline void reset( SymmetricMatrix<MT,SO,DF,NF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF, bool NF >
+inline void clear( SymmetricMatrix<MT,SO,DF,NF>& m );
+
+template< typename MT, bool SO, bool DF, bool NF >
+inline bool isDefault( const SymmetricMatrix<MT,SO,DF,NF>& m );
+
+template< typename MT, bool SO, bool DF, bool NF >
+inline bool isIntact( const SymmetricMatrix<MT,SO,DF,NF>& m );
+
+template< typename MT, bool SO, bool DF, bool NF >
+inline void swap( SymmetricMatrix<MT,SO,DF,NF>& a, SymmetricMatrix<MT,SO,DF,NF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given symmetric matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline void reset( SymmetricMatrix<MT,SO,DF,NF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given symmetric matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given symmetric matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline void reset( SymmetricMatrix<MT,SO,DF,NF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given symmetric matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline void clear( SymmetricMatrix<MT,SO,DF,NF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given symmetric matrix is in default state.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric matrix to be tested for its default state.
+// \return \a true in case the given matrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the matrix is in default state. For instance, in case the
+// matrix is instantiated for a built-in integral or floating point data type, the function
+// returns \a true in case all matrix elements are 0 and \a false in case any matrix element
+// is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::SymmetricMatrix<int> A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline bool isDefault( const SymmetricMatrix<MT,SO,DF,NF>& m )
+{
+ return isDefault( m.matrix_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given symmetric matrix are intact.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the symmetric matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ SymmetricMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline bool isIntact( const SymmetricMatrix<MT,SO,DF,NF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup symmetric_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF > // Numeric flag
+inline void swap( SymmetricMatrix<MT,SO,DF,NF>& a, SymmetricMatrix<MT,SO,DF,NF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given symmetric dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense \f$ 2 \times 2 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert2x2( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const MT& A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ const ET det( A(0,0)*A(1,1) - A(0,1)*A(1,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+ const ET a11( A(0,0) * idet );
+
+ B(0,0) = A(1,1) * idet;
+ B(1,0) = -A(1,0) * idet;
+ B(0,1) = B(1,0);
+ B(1,1) = a11;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given symmetric dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense \f$ 3 \times 3 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert3x3( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,3UL,3UL,SO> A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ B(0,0) = A(1,1)*A(2,2) - A(1,2)*A(2,1);
+ B(1,0) = A(1,2)*A(2,0) - A(1,0)*A(2,2);
+ B(2,0) = A(1,0)*A(2,1) - A(1,1)*A(2,0);
+
+ const ET det( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B(0,1) = B(1,0);
+ B(1,1) = A(0,0)*A(2,2) - A(0,2)*A(2,0);
+ B(2,1) = A(0,1)*A(2,0) - A(0,0)*A(2,1);
+ B(0,2) = B(2,0);
+ B(1,2) = B(2,1);
+ B(2,2) = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given symmetric dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense \f$ 4 \times 4 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert4x4( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,4UL,4UL,SO> A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ ET tmp1( A(2,2)*A(3,3) - A(2,3)*A(3,2) );
+ ET tmp2( A(2,1)*A(3,3) - A(2,3)*A(3,1) );
+ ET tmp3( A(2,1)*A(3,2) - A(2,2)*A(3,1) );
+
+ B(0,0) = A(1,1)*tmp1 - A(1,2)*tmp2 + A(1,3)*tmp3;
+ B(0,1) = A(0,2)*tmp2 - A(0,1)*tmp1 - A(0,3)*tmp3;
+
+ ET tmp4( A(2,0)*A(3,3) - A(2,3)*A(3,0) );
+ ET tmp5( A(2,0)*A(3,2) - A(2,2)*A(3,0) );
+
+ B(1,1) = A(0,0)*tmp1 - A(0,2)*tmp4 + A(0,3)*tmp5;
+
+ tmp1 = A(2,0)*A(3,1) - A(2,1)*A(3,0);
+
+ B(2,0) = A(1,0)*tmp2 - A(1,1)*tmp4 + A(1,3)*tmp1;
+ B(2,1) = A(0,1)*tmp4 - A(0,0)*tmp2 - A(0,3)*tmp1;
+ B(3,0) = A(1,1)*tmp5 - A(1,0)*tmp3 - A(1,2)*tmp1;
+ B(3,1) = A(0,0)*tmp3 - A(0,1)*tmp5 + A(0,2)*tmp1;
+
+ tmp1 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp2 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ tmp3 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp4 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+ tmp5 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+
+ B(2,2) = A(3,0)*tmp1 - A(3,1)*tmp3 + A(3,3)*tmp5;
+ B(2,3) = A(2,1)*tmp3 - A(2,0)*tmp1 - A(2,3)*tmp5;
+ B(3,3) = A(2,0)*tmp2 - A(2,1)*tmp4 + A(2,2)*tmp5;
+
+ B(0,2) = B(2,0);
+ B(0,3) = B(3,0);
+ B(1,0) = B(0,1);
+ B(1,2) = B(2,1);
+ B(1,3) = B(3,1);
+ B(3,2) = B(2,3);
+
+ const ET det( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) + A(0,3)*B(3,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given symmetric/Hermitian dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric/Hermitian dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense \f$ 5 \times 5 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert5x5( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,5UL,5UL,SO> A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ ET tmp1 ( A(3,3)*A(4,4) - A(3,4)*A(4,3) );
+ ET tmp2 ( A(3,2)*A(4,4) - A(3,4)*A(4,2) );
+ ET tmp3 ( A(3,2)*A(4,3) - A(3,3)*A(4,2) );
+ ET tmp4 ( A(3,1)*A(4,4) - A(3,4)*A(4,1) );
+ ET tmp5 ( A(3,1)*A(4,3) - A(3,3)*A(4,1) );
+ ET tmp6 ( A(3,1)*A(4,2) - A(3,2)*A(4,1) );
+ ET tmp7 ( A(3,0)*A(4,4) - A(3,4)*A(4,0) );
+ ET tmp8 ( A(3,0)*A(4,3) - A(3,3)*A(4,0) );
+ ET tmp9 ( A(3,0)*A(4,2) - A(3,2)*A(4,0) );
+ ET tmp10( A(3,0)*A(4,1) - A(3,1)*A(4,0) );
+
+ ET tmp11( A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3 );
+ ET tmp12( A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5 );
+ ET tmp13( A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6 );
+ ET tmp14( A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6 );
+ ET tmp15( A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8 );
+ ET tmp16( A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9 );
+ ET tmp17( A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9 );
+
+ B(0,0) = A(1,1)*tmp11 - A(1,2)*tmp12 + A(1,3)*tmp13 - A(1,4)*tmp14;
+ B(0,1) = - A(0,1)*tmp11 + A(0,2)*tmp12 - A(0,3)*tmp13 + A(0,4)*tmp14;
+ B(1,1) = A(0,0)*tmp11 - A(0,2)*tmp15 + A(0,3)*tmp16 - A(0,4)*tmp17;
+
+ ET tmp18( A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10 );
+ ET tmp19( A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10 );
+ ET tmp20( A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10 );
+
+ B(2,0) = A(1,0)*tmp12 - A(1,1)*tmp15 + A(1,3)*tmp18 - A(1,4)*tmp19;
+ B(2,1) = - A(0,0)*tmp12 + A(0,1)*tmp15 - A(0,3)*tmp18 + A(0,4)*tmp19;
+ B(3,0) = - A(1,0)*tmp13 + A(1,1)*tmp16 - A(1,2)*tmp18 + A(1,4)*tmp20;
+ B(3,1) = A(0,0)*tmp13 - A(0,1)*tmp16 + A(0,2)*tmp18 - A(0,4)*tmp20;
+ B(4,0) = A(1,0)*tmp14 - A(1,1)*tmp17 + A(1,2)*tmp19 - A(1,3)*tmp20;
+ B(4,1) = - A(0,0)*tmp14 + A(0,1)*tmp17 - A(0,2)*tmp19 + A(0,3)*tmp20;
+
+ tmp11 = A(1,1)*tmp1 - A(1,3)*tmp4 + A(1,4)*tmp5;
+ tmp12 = A(1,0)*tmp1 - A(1,3)*tmp7 + A(1,4)*tmp8;
+ tmp13 = A(1,0)*tmp4 - A(1,1)*tmp7 + A(1,4)*tmp10;
+ tmp14 = A(1,0)*tmp5 - A(1,1)*tmp8 + A(1,3)*tmp10;
+
+ B(2,2) = A(0,0)*tmp11 - A(0,1)*tmp12 + A(0,3)*tmp13 - A(0,4)*tmp14;
+
+ tmp1 = A(0,2)*A(1,3) - A(0,3)*A(1,2);
+ tmp2 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp3 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ tmp4 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp5 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+ tmp6 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+ tmp7 = A(0,2)*A(1,4) - A(0,4)*A(1,2);
+ tmp8 = A(0,1)*A(1,4) - A(0,4)*A(1,1);
+ tmp9 = A(0,0)*A(1,4) - A(0,4)*A(1,0);
+ tmp10 = A(0,3)*A(1,4) - A(0,4)*A(1,3);
+
+ tmp11 = A(2,1)*tmp10 - A(2,3)*tmp8 + A(2,4)*tmp2;
+ tmp12 = A(2,1)*tmp7 - A(2,2)*tmp8 + A(2,4)*tmp3;
+ tmp13 = A(2,1)*tmp1 - A(2,2)*tmp2 + A(2,3)*tmp3;
+ tmp14 = A(2,0)*tmp10 - A(2,3)*tmp9 + A(2,4)*tmp4;
+ tmp15 = A(2,0)*tmp7 - A(2,2)*tmp9 + A(2,4)*tmp5;
+ tmp16 = A(2,0)*tmp1 - A(2,2)*tmp4 + A(2,3)*tmp5;
+ tmp17 = A(2,0)*tmp8 - A(2,1)*tmp9 + A(2,4)*tmp6;
+ tmp18 = A(2,0)*tmp2 - A(2,1)*tmp4 + A(2,3)*tmp6;
+ tmp19 = A(2,0)*tmp3 - A(2,1)*tmp5 + A(2,2)*tmp6;
+
+ B(2,3) = A(4,0)*tmp11 - A(4,1)*tmp14 + A(4,3)*tmp17 - A(4,4)*tmp18;
+ B(2,4) = - A(3,0)*tmp11 + A(3,1)*tmp14 - A(3,3)*tmp17 + A(3,4)*tmp18;
+ B(3,3) = - A(4,0)*tmp12 + A(4,1)*tmp15 - A(4,2)*tmp17 + A(4,4)*tmp19;
+ B(3,4) = A(3,0)*tmp12 - A(3,1)*tmp15 + A(3,2)*tmp17 - A(3,4)*tmp19;
+ B(4,4) = - A(3,0)*tmp13 + A(3,1)*tmp16 - A(3,2)*tmp18 + A(3,3)*tmp19;
+
+ B(0,2) = B(2,0);
+ B(0,3) = B(3,0);
+ B(0,4) = B(4,0);
+ B(1,0) = B(0,1);
+ B(1,2) = B(2,1);
+ B(1,3) = B(3,1);
+ B(1,4) = B(4,1);
+ B(3,2) = B(2,3);
+ B(4,2) = B(2,4);
+ B(4,3) = B(3,4);
+
+ const ET det( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) + A(0,3)*B(3,0) + A(0,4)*B(4,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given symmetric dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense \f$ 6 \times 6 \f$ matrix via the rule of
+// Sarrus. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert6x6( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,6UL,6UL,SO> A( m.matrix_ );
+ MT& B( m.matrix_ );
+
+ ET tmp1 ( A(4,4)*A(5,5) - A(4,5)*A(5,4) );
+ ET tmp2 ( A(4,3)*A(5,5) - A(4,5)*A(5,3) );
+ ET tmp3 ( A(4,3)*A(5,4) - A(4,4)*A(5,3) );
+ ET tmp4 ( A(4,2)*A(5,5) - A(4,5)*A(5,2) );
+ ET tmp5 ( A(4,2)*A(5,4) - A(4,4)*A(5,2) );
+ ET tmp6 ( A(4,2)*A(5,3) - A(4,3)*A(5,2) );
+ ET tmp7 ( A(4,1)*A(5,5) - A(4,5)*A(5,1) );
+ ET tmp8 ( A(4,1)*A(5,4) - A(4,4)*A(5,1) );
+ ET tmp9 ( A(4,1)*A(5,3) - A(4,3)*A(5,1) );
+ ET tmp10( A(4,1)*A(5,2) - A(4,2)*A(5,1) );
+ ET tmp11( A(4,0)*A(5,5) - A(4,5)*A(5,0) );
+ ET tmp12( A(4,0)*A(5,4) - A(4,4)*A(5,0) );
+ ET tmp13( A(4,0)*A(5,3) - A(4,3)*A(5,0) );
+ ET tmp14( A(4,0)*A(5,2) - A(4,2)*A(5,0) );
+ ET tmp15( A(4,0)*A(5,1) - A(4,1)*A(5,0) );
+
+ ET tmp16( A(3,3)*tmp1 - A(3,4)*tmp2 + A(3,5)*tmp3 );
+ ET tmp17( A(3,2)*tmp1 - A(3,4)*tmp4 + A(3,5)*tmp5 );
+ ET tmp18( A(3,2)*tmp2 - A(3,3)*tmp4 + A(3,5)*tmp6 );
+ ET tmp19( A(3,2)*tmp3 - A(3,3)*tmp5 + A(3,4)*tmp6 );
+ ET tmp20( A(3,1)*tmp1 - A(3,4)*tmp7 + A(3,5)*tmp8 );
+ ET tmp21( A(3,1)*tmp2 - A(3,3)*tmp7 + A(3,5)*tmp9 );
+ ET tmp22( A(3,1)*tmp3 - A(3,3)*tmp8 + A(3,4)*tmp9 );
+ ET tmp23( A(3,1)*tmp4 - A(3,2)*tmp7 + A(3,5)*tmp10 );
+ ET tmp24( A(3,1)*tmp5 - A(3,2)*tmp8 + A(3,4)*tmp10 );
+ ET tmp25( A(3,1)*tmp6 - A(3,2)*tmp9 + A(3,3)*tmp10 );
+ ET tmp26( A(3,0)*tmp1 - A(3,4)*tmp11 + A(3,5)*tmp12 );
+ ET tmp27( A(3,0)*tmp2 - A(3,3)*tmp11 + A(3,5)*tmp13 );
+ ET tmp28( A(3,0)*tmp3 - A(3,3)*tmp12 + A(3,4)*tmp13 );
+ ET tmp29( A(3,0)*tmp4 - A(3,2)*tmp11 + A(3,5)*tmp14 );
+ ET tmp30( A(3,0)*tmp5 - A(3,2)*tmp12 + A(3,4)*tmp14 );
+ ET tmp31( A(3,0)*tmp6 - A(3,2)*tmp13 + A(3,3)*tmp14 );
+ ET tmp32( A(3,0)*tmp7 - A(3,1)*tmp11 + A(3,5)*tmp15 );
+ ET tmp33( A(3,0)*tmp8 - A(3,1)*tmp12 + A(3,4)*tmp15 );
+ ET tmp34( A(3,0)*tmp9 - A(3,1)*tmp13 + A(3,3)*tmp15 );
+ ET tmp35( A(3,0)*tmp10 - A(3,1)*tmp14 + A(3,2)*tmp15 );
+
+ ET tmp36( A(2,2)*tmp16 - A(2,3)*tmp17 + A(2,4)*tmp18 - A(2,5)*tmp19 );
+ ET tmp37( A(2,1)*tmp16 - A(2,3)*tmp20 + A(2,4)*tmp21 - A(2,5)*tmp22 );
+ ET tmp38( A(2,1)*tmp17 - A(2,2)*tmp20 + A(2,4)*tmp23 - A(2,5)*tmp24 );
+ ET tmp39( A(2,1)*tmp18 - A(2,2)*tmp21 + A(2,3)*tmp23 - A(2,5)*tmp25 );
+ ET tmp40( A(2,1)*tmp19 - A(2,2)*tmp22 + A(2,3)*tmp24 - A(2,4)*tmp25 );
+ ET tmp41( A(2,0)*tmp16 - A(2,3)*tmp26 + A(2,4)*tmp27 - A(2,5)*tmp28 );
+ ET tmp42( A(2,0)*tmp17 - A(2,2)*tmp26 + A(2,4)*tmp29 - A(2,5)*tmp30 );
+ ET tmp43( A(2,0)*tmp18 - A(2,2)*tmp27 + A(2,3)*tmp29 - A(2,5)*tmp31 );
+ ET tmp44( A(2,0)*tmp19 - A(2,2)*tmp28 + A(2,3)*tmp30 - A(2,4)*tmp31 );
+
+ B(0,0) = A(1,1)*tmp36 - A(1,2)*tmp37 + A(1,3)*tmp38 - A(1,4)*tmp39 + A(1,5)*tmp40;
+ B(0,1) = - A(0,1)*tmp36 + A(0,2)*tmp37 - A(0,3)*tmp38 + A(0,4)*tmp39 - A(0,5)*tmp40;
+ B(1,1) = A(0,0)*tmp36 - A(0,2)*tmp41 + A(0,3)*tmp42 - A(0,4)*tmp43 + A(0,5)*tmp44;
+
+ ET tmp45( A(2,0)*tmp20 - A(2,1)*tmp26 + A(2,4)*tmp32 - A(2,5)*tmp33 );
+ ET tmp46( A(2,0)*tmp21 - A(2,1)*tmp27 + A(2,3)*tmp32 - A(2,5)*tmp34 );
+ ET tmp47( A(2,0)*tmp22 - A(2,1)*tmp28 + A(2,3)*tmp33 - A(2,4)*tmp34 );
+ ET tmp48( A(2,0)*tmp23 - A(2,1)*tmp29 + A(2,2)*tmp32 - A(2,5)*tmp35 );
+ ET tmp49( A(2,0)*tmp24 - A(2,1)*tmp30 + A(2,2)*tmp33 - A(2,4)*tmp35 );
+
+ B(2,0) = A(1,0)*tmp37 - A(1,1)*tmp41 + A(1,3)*tmp45 - A(1,4)*tmp46 + A(1,5)*tmp47;
+ B(2,1) = - A(0,0)*tmp37 + A(0,1)*tmp41 - A(0,3)*tmp45 + A(0,4)*tmp46 - A(0,5)*tmp47;
+ B(3,0) = - A(1,0)*tmp38 + A(1,1)*tmp42 - A(1,2)*tmp45 + A(1,4)*tmp48 - A(1,5)*tmp49;
+ B(3,1) = A(0,0)*tmp38 - A(0,1)*tmp42 + A(0,2)*tmp45 - A(0,4)*tmp48 + A(0,5)*tmp49;
+
+ ET tmp50( A(2,0)*tmp25 - A(2,1)*tmp31 + A(2,2)*tmp34 - A(2,3)*tmp35 );
+
+ B(4,0) = A(1,0)*tmp39 - A(1,1)*tmp43 + A(1,2)*tmp46 - A(1,3)*tmp48 + A(1,5)*tmp50;
+ B(4,1) = - A(0,0)*tmp39 + A(0,1)*tmp43 - A(0,2)*tmp46 + A(0,3)*tmp48 - A(0,5)*tmp50;
+ B(5,0) = - A(1,0)*tmp40 + A(1,1)*tmp44 - A(1,2)*tmp47 + A(1,3)*tmp49 - A(1,4)*tmp50;
+ B(5,1) = A(0,0)*tmp40 - A(0,1)*tmp44 + A(0,2)*tmp47 - A(0,3)*tmp49 + A(0,4)*tmp50;
+
+ tmp36 = A(1,1)*tmp16 - A(1,3)*tmp20 + A(1,4)*tmp21 - A(1,5)*tmp22;
+ tmp37 = A(1,1)*tmp17 - A(1,2)*tmp20 + A(1,4)*tmp23 - A(1,5)*tmp24;
+ tmp38 = A(1,0)*tmp16 - A(1,3)*tmp26 + A(1,4)*tmp27 - A(1,5)*tmp28;
+ tmp39 = A(1,0)*tmp17 - A(1,2)*tmp26 + A(1,4)*tmp29 - A(1,5)*tmp30;
+ tmp40 = A(1,0)*tmp20 - A(1,1)*tmp26 + A(1,4)*tmp32 - A(1,5)*tmp33;
+ tmp41 = A(1,0)*tmp21 - A(1,1)*tmp27 + A(1,3)*tmp32 - A(1,5)*tmp34;
+ tmp42 = A(1,0)*tmp22 - A(1,1)*tmp28 + A(1,3)*tmp33 - A(1,4)*tmp34;
+ tmp43 = A(1,0)*tmp23 - A(1,1)*tmp29 + A(1,2)*tmp32 - A(1,5)*tmp35;
+ tmp44 = A(1,0)*tmp24 - A(1,1)*tmp30 + A(1,2)*tmp33 - A(1,4)*tmp35;
+
+ B(2,2) = A(0,0)*tmp36 - A(0,1)*tmp38 + A(0,3)*tmp40 - A(0,4)*tmp41 + A(0,5)*tmp42;
+ B(3,2) = - A(0,0)*tmp37 + A(0,1)*tmp39 - A(0,2)*tmp40 + A(0,4)*tmp43 - A(0,5)*tmp44;
+
+ tmp1 = A(0,3)*A(1,4) - A(0,4)*A(1,3);
+ tmp2 = A(0,2)*A(1,4) - A(0,4)*A(1,2);
+ tmp3 = A(0,2)*A(1,3) - A(0,3)*A(1,2);
+ tmp4 = A(0,1)*A(1,4) - A(0,4)*A(1,1);
+ tmp5 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp6 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ tmp7 = A(0,0)*A(1,4) - A(0,4)*A(1,0);
+ tmp8 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp9 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+ tmp10 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+ tmp11 = A(0,3)*A(1,5) - A(0,5)*A(1,3);
+ tmp12 = A(0,2)*A(1,5) - A(0,5)*A(1,2);
+ tmp13 = A(0,1)*A(1,5) - A(0,5)*A(1,1);
+ tmp14 = A(0,0)*A(1,5) - A(0,5)*A(1,0);
+ tmp15 = A(0,4)*A(1,5) - A(0,5)*A(1,4);
+
+ tmp16 = A(2,3)*tmp15 - A(2,4)*tmp11 + A(2,5)*tmp1;
+ tmp17 = A(2,2)*tmp15 - A(2,4)*tmp12 + A(2,5)*tmp2;
+ tmp18 = A(2,2)*tmp11 - A(2,3)*tmp12 + A(2,5)*tmp3;
+ tmp19 = A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3;
+ tmp20 = A(2,1)*tmp15 - A(2,4)*tmp13 + A(2,5)*tmp4;
+ tmp21 = A(2,1)*tmp11 - A(2,3)*tmp13 + A(2,5)*tmp5;
+ tmp22 = A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5;
+ tmp23 = A(2,1)*tmp12 - A(2,2)*tmp13 + A(2,5)*tmp6;
+ tmp24 = A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6;
+ tmp25 = A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6;
+ tmp26 = A(2,0)*tmp15 - A(2,4)*tmp14 + A(2,5)*tmp7;
+ tmp27 = A(2,0)*tmp11 - A(2,3)*tmp14 + A(2,5)*tmp8;
+ tmp28 = A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8;
+ tmp29 = A(2,0)*tmp12 - A(2,2)*tmp14 + A(2,5)*tmp9;
+ tmp30 = A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9;
+ tmp31 = A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9;
+ tmp32 = A(2,0)*tmp13 - A(2,1)*tmp14 + A(2,5)*tmp10;
+ tmp33 = A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10;
+ tmp34 = A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10;
+ tmp35 = A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10;
+
+ tmp36 = A(3,1)*tmp16 - A(3,3)*tmp20 + A(3,4)*tmp21 - A(3,5)*tmp22;
+ tmp37 = A(3,1)*tmp17 - A(3,2)*tmp20 + A(3,4)*tmp23 - A(3,5)*tmp24;
+ tmp38 = A(3,0)*tmp16 - A(3,3)*tmp26 + A(3,4)*tmp27 - A(3,5)*tmp28;
+ tmp39 = A(3,0)*tmp17 - A(3,2)*tmp26 + A(3,4)*tmp29 - A(3,5)*tmp30;
+ tmp40 = A(3,0)*tmp20 - A(3,1)*tmp26 + A(3,4)*tmp32 - A(3,5)*tmp33;
+ tmp41 = A(3,0)*tmp21 - A(3,1)*tmp27 + A(3,3)*tmp32 - A(3,5)*tmp34;
+ tmp42 = A(3,0)*tmp22 - A(3,1)*tmp28 + A(3,3)*tmp33 - A(3,4)*tmp34;
+ tmp43 = A(3,0)*tmp23 - A(3,1)*tmp29 + A(3,2)*tmp32 - A(3,5)*tmp35;
+ tmp44 = A(3,0)*tmp24 - A(3,1)*tmp30 + A(3,2)*tmp33 - A(3,4)*tmp35;
+
+ B(2,4) = - A(5,0)*tmp36 + A(5,1)*tmp38 - A(5,3)*tmp40 + A(5,4)*tmp41 - A(5,5)*tmp42;
+ B(2,5) = A(4,0)*tmp36 - A(4,1)*tmp38 + A(4,3)*tmp40 - A(4,4)*tmp41 + A(4,5)*tmp42;
+ B(3,4) = A(5,0)*tmp37 - A(5,1)*tmp39 + A(5,2)*tmp40 - A(5,4)*tmp43 + A(5,5)*tmp44;
+ B(3,5) = - A(4,0)*tmp37 + A(4,1)*tmp39 - A(4,2)*tmp40 + A(4,4)*tmp43 - A(4,5)*tmp44;
+
+ tmp36 = A(3,1)*tmp18 - A(3,2)*tmp21 + A(3,3)*tmp23 - A(3,5)*tmp25;
+ tmp37 = A(3,1)*tmp19 - A(3,2)*tmp22 + A(3,3)*tmp24 - A(3,4)*tmp25;
+ tmp38 = A(3,0)*tmp18 - A(3,2)*tmp27 + A(3,3)*tmp29 - A(3,5)*tmp31;
+ tmp39 = A(3,0)*tmp19 - A(3,2)*tmp28 + A(3,3)*tmp30 - A(3,4)*tmp31;
+ tmp40 = A(3,0)*tmp25 - A(3,1)*tmp31 + A(3,2)*tmp34 - A(3,3)*tmp35;
+
+ B(4,4) = - A(5,0)*tmp36 + A(5,1)*tmp38 - A(5,2)*tmp41 + A(5,3)*tmp43 - A(5,5)*tmp40;
+ B(4,5) = A(4,0)*tmp36 - A(4,1)*tmp38 + A(4,2)*tmp41 - A(4,3)*tmp43 + A(4,5)*tmp40;
+ B(5,5) = - A(4,0)*tmp37 + A(4,1)*tmp39 - A(4,2)*tmp42 + A(4,3)*tmp44 - A(4,4)*tmp40;
+
+ tmp36 = A(4,1)*tmp17 - A(4,2)*tmp20 + A(4,4)*tmp23 - A(4,5)*tmp24;
+ tmp37 = A(4,0)*tmp17 - A(4,2)*tmp26 + A(4,4)*tmp29 - A(4,5)*tmp30;
+ tmp38 = A(4,0)*tmp20 - A(4,1)*tmp26 + A(4,4)*tmp32 - A(4,5)*tmp33;
+ tmp39 = A(4,0)*tmp23 - A(4,1)*tmp29 + A(4,2)*tmp32 - A(4,5)*tmp35;
+ tmp40 = A(4,0)*tmp24 - A(4,1)*tmp30 + A(4,2)*tmp33 - A(4,4)*tmp35;
+
+ B(3,3) = - A(5,0)*tmp36 + A(5,1)*tmp37 - A(5,2)*tmp38 + A(5,4)*tmp39 - A(5,5)*tmp40;
+
+ B(0,2) = B(2,0);
+ B(0,3) = B(3,0);
+ B(0,4) = B(4,0);
+ B(0,5) = B(5,0);
+ B(1,0) = B(0,1);
+ B(1,2) = B(2,1);
+ B(1,3) = B(3,1);
+ B(1,4) = B(4,1);
+ B(1,5) = B(5,1);
+ B(2,3) = B(3,2);
+ B(4,2) = B(2,4);
+ B(4,3) = B(3,4);
+ B(5,2) = B(2,5);
+ B(5,3) = B(3,5);
+ B(5,4) = B(4,5);
+
+ const ET det( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) +
+ A(0,3)*B(3,0) + A(0,4)*B(4,0) + A(0,5)*B(5,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given symmetric dense matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense matrix by means of the most suited matrix
+// inversion algorithm. The matrix inversion fails if the given matrix is singular and not
+// invertible. In this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByDefault( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ invertByLDLT( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place LU-based inversion of the given symmetric dense matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense matrix by means of an LU decomposition.
+// The inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLU( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT tmp( m.matrix_ );
+ invertByLU( tmp );
+ m.matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given symmetric dense matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense matrix by means of a Bunch-Kaufman-based
+// decomposition. The inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLT( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT tmp( m.matrix_ );
+ invertByLDLT( tmp );
+ m.matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given symmetric dense matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense matrix by means of a Bunch-Kaufman-based
+// decomposition. The inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLH( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT tmp( m.matrix_ );
+ invertByLDLH( tmp );
+ m.matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Cholesky-based inversion of the given symmetric dense matrix.
+// \ingroup symmetric_matrix
+//
+// \param m The symmetric dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense matrix by means of a Cholesky-based
+// decomposition. The inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLLH( SymmetricMatrix<MT,SO,true,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ MT tmp( m.matrix_ );
+ invertByLLH( tmp );
+ m.matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a matrix to a symmetric matrix.
+// \ingroup symmetric_matrix
+//
+// \param lhs The target left-hand side symmetric matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF // Numeric flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAssign( const SymmetricMatrix<MT1,SO1,DF,NF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( ( row + M <= column ) || ( column + N <= row ) )
+ return true;
+
+ const bool lower( row > column );
+ const size_t size ( min( row + M, column + N ) - ( lower ? row : column ) );
+
+ if( size < 2UL )
+ return true;
+
+ const size_t subrow( lower ? 0UL : column - row );
+ const size_t subcol( lower ? row - column : 0UL );
+
+ return isSymmetric( submatrix( ~rhs, subrow, subcol, size, size ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a symmetric matrix.
+// \ingroup symmetric_matrix
+//
+// \param lhs The target left-hand side symmetric matrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF // Numeric flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAddAssign( const SymmetricMatrix<MT1,SO1,DF,NF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a symmetric
+// matrix.
+// \ingroup symmetric_matrix
+//
+// \param lhs The target left-hand side symmetric matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , bool NF // Numeric flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const SymmetricMatrix<MT1,SO1,DF,NF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct Rows< SymmetricMatrix<MT,SO,DF,NF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct Columns< SymmetricMatrix<MT,SO,DF,NF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct IsSquare< SymmetricMatrix<MT,SO,DF,NF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct IsSymmetric< SymmetricMatrix<MT,SO,DF,NF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct IsHermitian< SymmetricMatrix<MT,SO,DF,NF> >
+ : public BoolConstant< IsBuiltin< ElementType_<MT> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct IsAdaptor< SymmetricMatrix<MT,SO,DF,NF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct IsRestricted< SymmetricMatrix<MT,SO,DF,NF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool NF >
+struct HasConstDataAccess< SymmetricMatrix<MT,SO,true,NF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct IsAligned< SymmetricMatrix<MT,SO,DF,NF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct IsPadded< SymmetricMatrix<MT,SO,DF,NF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct IsResizable< SymmetricMatrix<MT,SO,DF,NF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct RemoveAdaptor< SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< SymmetricMatrix<MT,SO1,DF,NF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< SymmetricMatrix<MT,SO1,DF,NF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 >
+struct AddTrait< SymmetricMatrix<MT,SO1,DF,NF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct AddTrait< DynamicMatrix<T,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< SymmetricMatrix<MT,SO1,DF,NF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 >
+struct AddTrait< SymmetricMatrix<MT,SO1,DF,NF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct AddTrait< CompressedMatrix<T,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF1, typename MT2, bool SO2, bool DF2, bool NF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1,NF1>, SymmetricMatrix<MT2,SO2,DF2,NF2> >
+{
+ using Type = SymmetricMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< SymmetricMatrix<MT,SO1,DF,NF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< SymmetricMatrix<MT,SO1,DF,NF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 >
+struct SubTrait< SymmetricMatrix<MT,SO1,DF,NF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct SubTrait< DynamicMatrix<T,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< SymmetricMatrix<MT,SO1,DF,NF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 >
+struct SubTrait< SymmetricMatrix<MT,SO1,DF,NF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct SubTrait< CompressedMatrix<T,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF1, typename MT2, bool SO2, bool DF2, bool NF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1,NF1>, SymmetricMatrix<MT2,SO2,DF2,NF2> >
+{
+ using Type = SymmetricMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF, typename T >
+struct MultTrait< SymmetricMatrix<MT,SO,DF,NF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = SymmetricMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool NF >
+struct MultTrait< T, SymmetricMatrix<MT,SO,DF,NF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = SymmetricMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF, typename T, size_t N >
+struct MultTrait< SymmetricMatrix<MT,SO,DF,NF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF, bool NF >
+struct MultTrait< StaticVector<T,N,true>, SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF, typename T, size_t N >
+struct MultTrait< SymmetricMatrix<MT,SO,DF,NF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF, bool NF >
+struct MultTrait< HybridVector<T,N,true>, SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF, typename T >
+struct MultTrait< SymmetricMatrix<MT,SO,DF,NF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool NF >
+struct MultTrait< DynamicVector<T,true>, SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF, typename T, bool AF, bool PF >
+struct MultTrait< SymmetricMatrix<MT,SO,DF,NF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF, bool NF >
+struct MultTrait< CustomVector<T,AF,PF,true>, SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF, typename T >
+struct MultTrait< SymmetricMatrix<MT,SO,DF,NF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool NF >
+struct MultTrait< CompressedVector<T,true>, SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< SymmetricMatrix<MT,SO1,DF,NF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< SymmetricMatrix<MT,SO1,DF,NF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 >
+struct MultTrait< SymmetricMatrix<MT,SO1,DF,NF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct MultTrait< DynamicMatrix<T,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< SymmetricMatrix<MT,SO1,DF,NF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 >
+struct MultTrait< SymmetricMatrix<MT,SO1,DF,NF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF >
+struct MultTrait< CompressedMatrix<T,SO1>, SymmetricMatrix<MT,SO2,DF,NF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF1, typename MT2, bool SO2, bool DF2, bool NF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1,NF1>, SymmetricMatrix<MT2,SO2,DF2,NF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF, typename T >
+struct DivTrait< SymmetricMatrix<MT,SO,DF,NF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = SymmetricMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Abs >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Abs> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Floor >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Floor> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Ceil >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Ceil> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Conj >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Conj> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Real >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Real> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Imag >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Imag> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Sqrt >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,InvSqrt> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Cbrt >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Cbrt> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, InvCbrt >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,InvCbrt> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF, typename ET >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Pow<ET> >
+{
+ using Type = SymmetricMatrix< ForEachTrait_< MT, Pow<ET> > >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Exp >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Exp> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Log >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Log> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Log10 >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Log10> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Sin >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Sin> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Asin >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Asin> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Sinh >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Sinh> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Asinh >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Asinh> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Cos >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Cos> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Acos >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Acos> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Cosh >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Cosh> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Acosh >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Acosh> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Tan >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Tan> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Atan >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Atan> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Tanh >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Tanh> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Atanh >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Atanh> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Erf >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Erf> >;
+};
+
+template< typename MT, bool SO, bool DF, bool NF >
+struct ForEachTrait< SymmetricMatrix<MT,SO,DF,NF>, Erfc >
+{
+ using Type = SymmetricMatrix< ForEachTrait_<MT,Erfc> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, bool NF1, typename MT2, bool SO2, bool DF2, bool NF2 >
+struct MathTrait< SymmetricMatrix<MT1,SO1,DF1,NF1>, SymmetricMatrix<MT2,SO2,DF2,NF2> >
+{
+ typedef SymmetricMatrix< typename MathTrait<MT1,MT2>::HighType > HighType;
+ typedef SymmetricMatrix< typename MathTrait<MT1,MT2>::LowType > LowType;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct SubmatrixTrait< SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct RowTrait< SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool NF >
+struct ColumnTrait< SymmetricMatrix<MT,SO,DF,NF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/UniLowerMatrix.h b/src/cpu/blaze/math/adaptors/UniLowerMatrix.h
new file mode 100644
index 00000000..210ac654
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/UniLowerMatrix.h
@@ -0,0 +1,2562 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/UniLowerMatrix.h
+// \brief Header file for the implementation of a lower unitriangular matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/lowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/unilowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/unilowermatrix/Dense.h>
+#include <blaze/math/adaptors/unilowermatrix/Sparse.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/StaticMatrix.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/trtri.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// UNILOWERMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UniLowerMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF >
+inline void reset( UniLowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void reset( UniLowerMatrix<MT,SO,DF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF >
+inline void clear( UniLowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isDefault( const UniLowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isIntact( const UniLowerMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void swap( UniLowerMatrix<MT,SO,DF>& a, UniLowerMatrix<MT,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( UniLowerMatrix<MT,SO,DF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given unilower matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( UniLowerMatrix<MT,SO,DF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void clear( UniLowerMatrix<MT,SO,DF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given resizable unilower matrix is in default state.
+// \ingroup unilower_matrix
+//
+// \param m The unilower matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the resizable lower unitriangular matrix is in default state.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault_backend( const UniLowerMatrix<MT,SO,DF>& m, TrueType )
+{
+ return ( m.rows() == 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given fixed-size unilower matrix is in default state.
+// \ingroup unilower_matrix
+//
+// \param m The unilower matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the fixed-size lower unitriangular matrix is in default state.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault_backend( const UniLowerMatrix<MT,SO,DF>& m, FalseType )
+{
+ return isIdentity( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given unilower matrix is in default state.
+// \ingroup unilower_matrix
+//
+// \param m The unilower matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the lower unitriangular matrix is in default state. The following
+// example demonstrates the use of the \a isDefault function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+
+ UniLowerMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault( const UniLowerMatrix<MT,SO,DF>& m )
+{
+ return isDefault_backend( m, typename IsResizable<MT>::Type() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given unilower matrix are intact.
+// \ingroup unilower_matrix
+//
+// \param m The unilower matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the unilower matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+
+ UniLowerMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isIntact( const UniLowerMatrix<MT,SO,DF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup unilower_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void swap( UniLowerMatrix<MT,SO,DF>& a, UniLowerMatrix<MT,SO,DF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given unilower dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense \f$ 2 \times 2 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert2x2( UniLowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" );
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ A(1,0) = -A(1,0);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given unilower dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense \f$ 3 \times 3 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert3x3( UniLowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,3UL,3UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ B(1,0) = - A(1,0);
+ B(2,0) = A(1,0)*A(2,1) - A(2,0);
+ B(2,1) = - A(2,1);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given unilower dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense \f$ 4 \times 4 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert4x4( UniLowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,4UL,4UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp( A(2,1)*A(3,2) - A(3,1) );
+
+ B(1,0) = - A(1,0);
+ B(2,0) = A(1,0)*A(2,1) - A(2,0);
+ B(3,0) = A(2,0)*A(3,2) - A(3,0) - A(1,0)*tmp;
+ B(2,1) = - A(2,1);
+ B(3,1) = tmp;
+ B(3,2) = - A(3,2);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given unilower dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense \f$ 5 \times 5 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert5x5( UniLowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,5UL,5UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp1( A(3,2)*A(4,3) - A(4,2) );
+ const ET tmp2( A(2,1)*A(3,2) - A(3,1) );
+ const ET tmp3( A(2,1)*tmp1 - A(3,1)*A(4,3) + A(4,1) );
+
+ B(1,0) = - A(1,0);
+ B(2,0) = A(1,0)*A(2,1) - A(2,0);
+ B(3,0) = - A(1,0)*tmp2 + A(2,0)*A(3,2) - A(3,0);
+ B(4,0) = A(1,0)*tmp3 - A(2,0)*tmp1 + A(3,0)*A(4,3) - A(4,0);
+ B(2,1) = - A(2,1);
+ B(3,1) = tmp2;
+ B(4,1) = - tmp3;
+ B(3,2) = - A(3,2);
+ B(4,2) = A(4,3)*A(3,2) - A(4,2);
+ B(4,3) = - A(4,3);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given unilower dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense \f$ 6 \times 6 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert6x6( UniLowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,6UL,6UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp1( A(4,3)*A(5,4) - A(5,3) );
+ const ET tmp2( A(3,2)*A(4,3) - A(4,2) );
+ const ET tmp3( A(3,2)*tmp1 - A(4,2)*A(5,4) + A(5,2) );
+ const ET tmp4( A(2,1)*A(3,2) - A(3,1) );
+ const ET tmp5( A(2,1)*tmp2 - A(3,1)*A(4,3) + A(4,1) );
+ const ET tmp6( A(2,1)*tmp3 - A(3,1)*tmp1 + A(4,1)*A(5,4) - A(5,1) );
+
+ B(1,0) = - A(1,0);
+ B(2,0) = A(1,0)*A(2,1) - A(2,0);
+ B(3,0) = - A(1,0)*tmp4 + A(2,0)*A(3,2) - A(3,0);
+ B(4,0) = A(1,0)*tmp5 - A(2,0)*tmp2 + A(3,0)*A(4,3) - A(4,0);
+ B(5,0) = - A(1,0)*tmp6 + A(2,0)*tmp3 - A(3,0)*tmp1 + A(4,0)*A(5,4) - A(5,0);
+ B(2,1) = - A(2,1);
+ B(3,1) = tmp4;
+ B(4,1) = - tmp5;
+ B(5,1) = tmp6;
+ B(3,2) = - A(3,2);
+ B(4,2) = tmp2;
+ B(5,2) = - tmp3;
+ B(4,3) = A(5,3)*A(4,5) - A(4,3);
+ B(5,3) = A(5,4)*A(4,3) - A(5,3);
+ B(5,4) = A(5,3)*A(3,4) - A(5,4);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given unilower dense matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense matrix by means of the most suited matrix
+// inversion algorithm.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByDefault( UniLowerMatrix<MT,SO,true>& m )
+{
+ invertByLU( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place LU-based inversion of the given unilower dense matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense matrix by means of an LU decomposition.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLU( UniLowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ DerestrictTrait_<MT> A( derestrict( ~m ) );
+
+ trtri( A, 'L', 'U' );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given unilower dense matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense matrix by means of a Bunch-Kaufman decomposition.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLT( UniLowerMatrix<MT,SO,true>& m )
+{
+ invertByLLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given unilower dense matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense matrix by means of a Bunch-Kaufman decomposition.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLH( UniLowerMatrix<MT,SO,true>& m )
+{
+ invertByLLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Cholesky-based inversion of the given unilower dense matrix.
+// \ingroup unilower_matrix
+//
+// \param m The unilower dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given unilower dense matrix by means of a Cholesky decomposition.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLLH( UniLowerMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( isIdentity( ~m ), "Violation of preconditions detected" );
+
+ UNUSED_PARAMETER( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief LU decomposition of the given unilower dense matrix.
+// \ingroup unilower_matrix
+//
+// \param A The unilower matrix to be decomposed.
+// \param L The resulting lower triangular matrix.
+// \param U The resulting upper triangular matrix.
+// \param P The resulting permutation matrix.
+// \return void
+//
+// This function performs the dense matrix (P)LU decomposition of a unilower n-by-n matrix. The
+// resulting decomposition is written to the three distinct matrices \c L, \c U, and \c P, which
+// are resized to the correct dimensions (if possible and necessary).
+//
+// \note The LU decomposition will never fail, even for singular matrices. However, in case of a
+// singular matrix the resulting decomposition cannot be used for a matrix inversion or solving
+// a linear system of equations.
+*/
+template< typename MT1, bool SO1, typename MT2, typename MT3, typename MT4, bool SO2 >
+inline void lu( const UniLowerMatrix<MT1,SO1,true>& A, DenseMatrix<MT2,SO1>& L,
+ DenseMatrix<MT3,SO1>& U, Matrix<MT4,SO2>& P )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE( MT3 );
+
+ typedef ElementType_<MT3> ET3;
+ typedef ElementType_<MT4> ET4;
+
+ const size_t n( (~A).rows() );
+
+ DerestrictTrait_<MT3> U2( derestrict( ~U ) );
+
+ (~L) = A;
+
+ resize( ~U, n, n );
+ reset( U2 );
+
+ resize( ~P, n, n );
+ reset( ~P );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ U2(i,i) = ET3(1);
+ (~P)(i,i) = ET4(1);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( column < row )
+ return true;
+
+ const bool containsDiagonal( column < row + (~rhs).size() );
+ const size_t iend( min( column - row, (~rhs).size() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ if( containsDiagonal && !isOne( (~rhs)[iend] ) )
+ return false;
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( row >= column + (~rhs).size() )
+ return true;
+
+ const bool containsDiagonal( row >= column );
+ const size_t ibegin( ( !containsDiagonal )?( 0UL ):( row - column + 1UL ) );
+
+ if( containsDiagonal && !isOne( (~rhs)[row-column] ) )
+ return false;
+
+ for( size_t i=ibegin; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( column < row )
+ return true;
+
+ const bool containsDiagonal( column < row + (~rhs).size() );
+ const size_t index( column - row );
+ const RhsIterator last( (~rhs).lowerBound( index ) );
+
+ if( containsDiagonal ) {
+ if( last == (~rhs).end() || last->index() != index || !isOne( last->value() ) )
+ return false;
+ }
+
+ for( RhsIterator element=(~rhs).begin(); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( row >= column + (~rhs).size() )
+ return true;
+
+ const bool containsDiagonal( row >= column );
+ const size_t index( ( containsDiagonal )?( row - column ):( 0UL ) );
+ const RhsIterator last( (~rhs).end() );
+ RhsIterator element( (~rhs).lowerBound( index ) );
+
+ if( containsDiagonal ) {
+ if( element == last || element->index() != index || !isOne( element->value() ) )
+ return false;
+ ++element;
+ }
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const UniLowerMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t iend( min( column + N - row, M ) );
+
+ for( size_t i=0UL; i<iend; ++i )
+ {
+ const bool containsDiagonal( row + i >= column );
+
+ if( containsDiagonal && !isOne( (~rhs)(i,row+i-column) ) )
+ return false;
+
+ const size_t jbegin( ( containsDiagonal )?( row + i - column + 1UL ):( 0UL ) );
+
+ for( size_t j=jbegin; j<N; ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const UniLowerMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t jbegin( ( row < column )?( 0UL ):( row - column ) );
+
+ for( size_t j=jbegin; j<N; ++j )
+ {
+ const size_t iend( min( column + j - row, M ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+
+ const bool containsDiagonal( column + j < row + M );
+
+ if( containsDiagonal && !isOne( (~rhs)(iend,j) ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const UniLowerMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t iend( min( column + N - row, M ) );
+
+ for( size_t i=0UL; i<iend; ++i )
+ {
+ const bool containsDiagonal( row + i >= column );
+ const size_t index( ( containsDiagonal )?( row + i - column ):( 0UL ) );
+
+ const RhsIterator last( (~rhs).end(i) );
+ RhsIterator element( (~rhs).lowerBound( i, index ) );
+
+ if( containsDiagonal ) {
+ if( element == last || ( element->index() != index ) || !isOne( element->value() ) )
+ return false;
+ ++element;
+ }
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const UniLowerMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t jbegin( ( row < column )?( 0UL ):( row - column ) );
+
+ for( size_t j=jbegin; j<N; ++j )
+ {
+ const bool containsDiagonal( column + j < row + M );
+
+ const size_t index( column + j - row );
+ const RhsIterator last( (~rhs).lowerBound( min( index, M ), j ) );
+
+ if( containsDiagonal ) {
+ if( last == (~rhs).end(j) || ( last->index() != index ) || !isOne( last->value() ) )
+ return false;
+ }
+
+ for( RhsIterator element=(~rhs).begin(j); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a dense vector to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side dense vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAddAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( column < row )
+ return true;
+
+ const size_t iend( min( column - row + 1UL, (~rhs).size() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a dense vector to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side dense vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAddAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t ibegin( ( row <= column )?( 0UL ):( row - column ) );
+
+ for( size_t i=ibegin; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a sparse vector to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side sparse vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAddAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( column < row )
+ return true;
+
+ const RhsIterator last( (~rhs).lowerBound( column - row + 1UL ) );
+
+ for( RhsIterator element=(~rhs).begin(); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a sparse vector to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side sparse vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAddAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ const RhsIterator last( (~rhs).end() );
+ RhsIterator element( (~rhs).lowerBound( ( row <= column )?( 0UL ):( row - column ) ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a dense matrix to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side dense matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAddAssign( const UniLowerMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t iend( min( column + N - row, M ) );
+
+ for( size_t i=0UL; i<iend; ++i )
+ {
+ const bool containsDiagonal( row + i >= column );
+ const size_t jbegin( ( containsDiagonal )?( row + i - column ):( 0UL ) );
+
+ for( size_t j=jbegin; j<N; ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a dense matrix to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side dense matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAddAssign( const UniLowerMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t jbegin( ( row <= column )?( 0UL ):( row - column ) );
+
+ for( size_t j=jbegin; j<N; ++j )
+ {
+ const size_t iend( min( column + j - row + 1UL, M ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a sparse matrix to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side sparse matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAddAssign( const UniLowerMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t iend( min( column + N - row, M ) );
+
+ for( size_t i=0UL; i<iend; ++i )
+ {
+ const bool containsDiagonal( row + i >= column );
+ const size_t index( ( containsDiagonal )?( row + i - column ):( 0UL ) );
+
+ const RhsIterator last( (~rhs).end(i) );
+ RhsIterator element( (~rhs).lowerBound( i, index ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a sparse matrix to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side sparse matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAddAssign( const UniLowerMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( row + 1UL >= column + N )
+ return true;
+
+ const size_t jbegin( ( row < column )?( 0UL ):( row - column ) );
+
+ for( size_t j=jbegin; j<N; ++j )
+ {
+ const size_t index( column + j - row + 1UL );
+ const RhsIterator last( (~rhs).lowerBound( min( index, M ), j ) );
+
+ for( RhsIterator element=(~rhs).begin(j); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to an unilower
+// matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAddAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to an unilower
+// matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const UniLowerMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAddAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side vector to be multiplied.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryMultAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ return ( column < row || (~rhs).size() <= column - row || isOne( (~rhs)[column-row] ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to an
+// unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side vector to be multiplied.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryMultAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ return ( row < column || (~rhs).size() <= row - column || isOne( (~rhs)[row-column] ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the division assignment of a vector to an unilower matrix.
+// \ingroup unilower_matrix
+//
+// \param lhs The target left-hand side unilower matrix.
+// \param rhs The right-hand side vector divisor.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryDivAssign( const UniLowerMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryMultAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns a reference to the instance without the access restrictions to the upper part.
+// \ingroup math_shims
+//
+// \param m The unilower matrix to be derestricted.
+// \return Reference to the matrix without access restrictions.
+//
+// This function returns a reference to the given unilower matrix instance that has no access
+// restrictions to the upper part of the matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline MT& derestrict( UniLowerMatrix<MT,SO,DF>& m )
+{
+ return m.matrix_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Rows< UniLowerMatrix<MT,SO,DF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Columns< UniLowerMatrix<MT,SO,DF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSquare< UniLowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsUniLower< UniLowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAdaptor< UniLowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsRestricted< UniLowerMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasConstDataAccess< UniLowerMatrix<MT,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAligned< UniLowerMatrix<MT,SO,DF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsPadded< UniLowerMatrix<MT,SO,DF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsResizable< UniLowerMatrix<MT,SO,DF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RemoveAdaptor< UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct DerestrictTrait< UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = MT&;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< UniLowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< UniLowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< UniLowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< DynamicMatrix<T,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< UniLowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< UniLowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CompressedMatrix<T,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< UniLowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< UniLowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< UniLowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< DynamicMatrix<T,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< UniLowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< UniLowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CompressedMatrix<T,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UniLowerMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = LowerMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< T, UniLowerMatrix<MT,SO,DF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = LowerMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< UniLowerMatrix<MT,SO,DF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< StaticVector<T,N,true>, UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< UniLowerMatrix<MT,SO,DF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< HybridVector<T,N,true>, UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UniLowerMatrix<MT,SO,DF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< DynamicVector<T,true>, UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF >
+struct MultTrait< UniLowerMatrix<MT,SO,DF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF >
+struct MultTrait< CustomVector<T,AF,PF,true>, UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UniLowerMatrix<MT,SO,DF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< CompressedVector<T,true>, UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< UniLowerMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< UniLowerMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< UniLowerMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< DynamicMatrix<T,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< UniLowerMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< UniLowerMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CompressedMatrix<T,SO1>, UniLowerMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = LowerMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = UniLowerMatrix< MultTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct DivTrait< UniLowerMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = LowerMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename ET >
+struct ForEachTrait< UniLowerMatrix<MT,SO,DF>, Pow<ET> >
+{
+ using Type = UniLowerMatrix< ForEachTrait_< MT, Pow<ET> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MathTrait< UniLowerMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using HighType = UniLowerMatrix< typename MathTrait<MT1,MT2>::HighType >;
+ using LowType = UniLowerMatrix< typename MathTrait<MT1,MT2>::LowType >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct SubmatrixTrait< UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RowTrait< UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ColumnTrait< UniLowerMatrix<MT,SO,DF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/UniUpperMatrix.h b/src/cpu/blaze/math/adaptors/UniUpperMatrix.h
new file mode 100644
index 00000000..c7a45178
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/UniUpperMatrix.h
@@ -0,0 +1,2671 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/UniUpperMatrix.h
+// \brief Header file for the implementation of a upper unitriangular matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/uniuppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/uniuppermatrix/Dense.h>
+#include <blaze/math/adaptors/uniuppermatrix/Sparse.h>
+#include <blaze/math/adaptors/uppermatrix/BaseTemplate.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/StaticMatrix.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/trtri.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// UNIUPPERMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UniUpperMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF >
+inline void reset( UniUpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void reset( UniUpperMatrix<MT,SO,DF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF >
+inline void clear( UniUpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isDefault( const UniUpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isIntact( const UniUpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void swap( UniUpperMatrix<MT,SO,DF>& a, UniUpperMatrix<MT,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( UniUpperMatrix<MT,SO,DF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given uniupper matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( UniUpperMatrix<MT,SO,DF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void clear( UniUpperMatrix<MT,SO,DF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given resizable uniupper matrix is in default state.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the resizable upper unitriangular matrix is in default state.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault_backend( const UniUpperMatrix<MT,SO,DF>& m, TrueType )
+{
+ return ( m.rows() == 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given fixed-size uniupper matrix is in default state.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper matrix to be tested for its default state.
+// \return \a true in case the given matrix is in default state, \a false otherwise.
+//
+// This function checks whether the fixed-size upper unitriangular matrix is in default state.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault_backend( const UniUpperMatrix<MT,SO,DF>& m, FalseType )
+{
+ return isIdentity( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given uniupper matrix are intact.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the uniupper matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+
+ UniUpperMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isIntact( const UniUpperMatrix<MT,SO,DF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given uniupper matrix is in default state.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper matrix to be tested for its default state.
+// \return \a true in case the given matrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the upper unitriangular matrix is in default state. The following
+// example demonstrates the use of the \a isDefault function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+ using blaze::rowMajor;
+
+ UniUpperMatrix< DynamicMatrix<int,rowMajor> > A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault( const UniUpperMatrix<MT,SO,DF>& m )
+{
+ return isDefault_backend( m, typename IsResizable<MT>::Type() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup uniupper_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void swap( UniUpperMatrix<MT,SO,DF>& a, UniUpperMatrix<MT,SO,DF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given uniupper dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense \f$ 2 \times 2 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert2x2( UniUpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" );
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ A(0,1) = -A(0,1);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given uniupper dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense \f$ 3 \times 3 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert3x3( UniUpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,3UL,3UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ B(0,1) = - A(0,1);
+ B(0,2) = A(0,1)*A(1,2) - A(0,2);
+ B(1,2) = - A(1,2);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given uniupper dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense \f$ 4 \times 4 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert4x4( UniUpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,4UL,4UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ ET tmp( A(0,1)*A(1,2) - A(0,2) );
+
+ B(0,1) = - A(0,1);
+ B(0,2) = tmp;
+ B(1,2) = - A(1,2);
+ B(0,3) = A(0,1)*A(1,3) - A(0,3) - A(2,3)*tmp;
+ B(1,3) = A(2,3)*A(1,2) - A(1,3);
+ B(2,3) = - A(2,3);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given uniupper dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense \f$ 5 \times 5 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert5x5( UniUpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,5UL,5UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp2( A(0,1)*A(1,2) - A(0,2) );
+
+ const ET tmp8 ( A(2,3)*tmp2 - A(0,1)*A(1,3) + A(0,3) );
+ const ET tmp9 ( A(2,3)*A(1,2) - A(1,3) );
+ const ET tmp10( A(2,3) );
+
+ B(0,1) = - A(0,1);
+ B(0,2) = A(0,1)*A(1,2) - A(0,2);
+ B(1,2) = - A(1,2);
+ B(0,3) = - tmp8;
+ B(1,3) = tmp9;
+ B(2,3) = - A(2,3);
+ B(0,4) = A(3,4)*tmp8 - A(2,4)*tmp2 + A(0,1)*A(1,4) - A(0,4);
+ B(1,4) = A(2,4)*A(1,2) - A(1,4) - A(3,4)*tmp9;
+ B(2,4) = A(3,4)*A(2,3) - A(2,4);
+ B(3,4) = - A(3,4);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given uniupper dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense \f$ 6 \times 6 \f$ matrix via the rule of Sarrus.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert6x6( UniUpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,6UL,6UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp1( A(0,1)*A(1,2) - A(0,2) );
+ const ET tmp2( A(2,3)*tmp1 - A(0,1)*A(1,3) + A(0,3) );
+ const ET tmp3( A(2,3)*A(1,2) - A(1,3) );
+ const ET tmp4( A(2,4)*tmp1 - A(0,1)*A(1,4) + A(0,4) - A(3,4)*tmp2 );
+ const ET tmp5( A(2,4)*A(1,2) - A(1,4) - A(3,4)*tmp3 );
+ const ET tmp6( A(2,4) - A(3,4)*A(2,3) );
+
+ B(0,1) = - A(0,1);
+ B(0,2) = A(0,1)*A(1,2) - A(0,2);
+ B(1,2) = - A(1,2);
+ B(0,3) = - tmp2;
+ B(1,3) = tmp3;
+ B(2,3) = - A(2,3);
+ B(0,4) = - tmp4;
+ B(1,4) = tmp5;
+ B(2,4) = - tmp6;
+ B(3,4) = - A(3,4);
+ B(0,5) = - A(2,5)*tmp1 + A(0,1)*A(1,5) - A(0,5) + A(3,5)*tmp2 + A(4,5)*tmp4;
+ B(1,5) = A(2,5)*A(1,2) - A(1,5) - A(3,5)*tmp3 - A(4,5)*tmp5;
+ B(2,5) = - A(2,5) + A(3,5)*A(2,3) + A(4,5)*tmp6;
+ B(3,5) = - A(3,5) + A(4,5)*A(3,4);
+ B(4,5) = - A(4,5);
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given uniupper dense matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense matrix by means of the most suited matrix
+// inversion algorithm.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByDefault( UniUpperMatrix<MT,SO,true>& m )
+{
+ invertByLU( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place LU-based inversion of the given uniupper dense matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense matrix by means of an LU decomposition.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLU( UniUpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ DerestrictTrait_<MT> A( derestrict( ~m ) );
+
+ trtri( A, 'U', 'U' );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given uniupper dense matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense matrix by means of a Bunch-Kaufman decomposition.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLT( UniUpperMatrix<MT,SO,true>& m )
+{
+ invertByLLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given uniupper dense matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense matrix by means of a Bunch-Kaufman decomposition.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLH( UniUpperMatrix<MT,SO,true>& m )
+{
+ invertByLLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Cholesky-based inversion of the given uniupper dense matrix.
+// \ingroup uniupper_matrix
+//
+// \param m The uniupper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given uniupper dense matrix by means of a Cholesky decomposition.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLLH( UniUpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( isIdentity( ~m ), "Violation of preconditions detected" );
+
+ UNUSED_PARAMETER( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief LU decomposition of the given uniupper dense matrix.
+// \ingroup upper_matrix
+//
+// \param A The uniupper matrix to be decomposed.
+// \param L The resulting lower triangular matrix.
+// \param U The resulting upper triangular matrix.
+// \param P The resulting permutation matrix.
+// \return void
+//
+// This function performs the dense matrix (P)LU decomposition of a uniupper n-by-n matrix. The
+// resulting decomposition is written to the three distinct matrices \c L, \c U, and \c P, which
+// are resized to the correct dimensions (if possible and necessary).
+//
+// \note The LU decomposition will never fail, even for singular matrices. However, in case of a
+// singular matrix the resulting decomposition cannot be used for a matrix inversion or solving
+// a linear system of equations.
+*/
+template< typename MT1, bool SO1, typename MT2, typename MT3, typename MT4, bool SO2 >
+inline void lu( const UniUpperMatrix<MT1,SO1,true>& A, DenseMatrix<MT2,SO1>& L,
+ DenseMatrix<MT3,SO1>& U, Matrix<MT4,SO2>& P )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE( MT3 );
+
+ typedef ElementType_<MT2> ET2;
+ typedef ElementType_<MT4> ET4;
+
+ const size_t n( (~A).rows() );
+
+ DerestrictTrait_<MT2> L2( derestrict( ~L ) );
+
+ (~U) = A;
+
+ resize( ~L, n, n );
+ reset( L2 );
+
+ resize( ~P, n, n );
+ reset( ~P );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ L2(i,i) = ET2(1);
+ (~P)(i,i) = ET4(1);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( column >= row + (~rhs).size() )
+ return true;
+
+ const bool containsDiagonal( column >= row );
+ const size_t ibegin( ( !containsDiagonal )?( 0UL ):( column - row + 1UL ) );
+
+ if( containsDiagonal && !isOne( (~rhs)[column-row] ) )
+ return false;
+
+ for( size_t i=ibegin; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( row < column )
+ return true;
+
+ const bool containsDiagonal( row < column + (~rhs).size() );
+ const size_t iend( min( row - column, (~rhs).size() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ if( containsDiagonal && !isOne( (~rhs)[iend] ) )
+ return false;
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( column >= row + (~rhs).size() )
+ return true;
+
+ const bool containsDiagonal( column >= row );
+ const size_t index( ( containsDiagonal )?( column - row ):( 0UL ) );
+ const RhsIterator last( (~rhs).end() );
+ RhsIterator element( (~rhs).lowerBound( index ) );
+
+ if( containsDiagonal ) {
+ if( element == last || element->index() != index || !isOne( element->value() ) )
+ return false;
+ ++element;
+ }
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( row < column )
+ return true;
+
+ const bool containsDiagonal( row < column + (~rhs).size() );
+ const size_t index( row - column );
+ const RhsIterator last( (~rhs).lowerBound( index ) );
+
+ if( containsDiagonal ) {
+ if( last == (~rhs).end() || last->index() != index || !isOne( last->value() ) )
+ return false;
+ }
+
+ for( RhsIterator element=(~rhs).begin(); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const UniUpperMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t ibegin( ( column < row )?( 0UL ):( column - row ) );
+
+ for( size_t i=ibegin; i<M; ++i )
+ {
+ const size_t jend( min( row + i - column, N ) );
+
+ for( size_t j=0UL; j<jend; ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+
+ const bool containsDiagonal( row + i < column + N );
+
+ if( containsDiagonal && !isOne( (~rhs)(i,jend) ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const UniUpperMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t jend( min( row + M - column, N ) );
+
+ for( size_t j=0UL; j<jend; ++j )
+ {
+ const bool containsDiagonal( column + j >= row );
+
+ if( containsDiagonal && !isOne( (~rhs)(column+j-row,j) ) )
+ return false;
+
+ const size_t ibegin( ( containsDiagonal )?( column + j - row + 1UL ):( 0UL ) );
+
+ for( size_t i=ibegin; i<M; ++i ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const UniUpperMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t ibegin( ( column < row )?( 0UL ):( column - row ) );
+
+ for( size_t i=ibegin; i<M; ++i )
+ {
+ const bool containsDiagonal( row + i < column + N );
+
+ const size_t index( row + i - column );
+ const RhsIterator last( (~rhs).lowerBound( i, min( index, N ) ) );
+
+ if( containsDiagonal ) {
+ if( last == (~rhs).end(i) || ( last->index() != index ) || !isOne( last->value() ) )
+ return false;
+ }
+
+ for( RhsIterator element=(~rhs).begin(i); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const UniUpperMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t jend( min( row + M - column, N ) );
+
+ for( size_t j=0UL; j<jend; ++j )
+ {
+ const bool containsDiagonal( column + j >= row );
+ const size_t index( ( containsDiagonal )?( column + j - row ):( 0UL ) );
+
+ const RhsIterator last( (~rhs).end(j) );
+ RhsIterator element( (~rhs).lowerBound( index, j ) );
+
+ if( containsDiagonal ) {
+ if( element == last || ( element->index() != index ) || !isOne( element->value() ) )
+ return false;
+ ++element;
+ }
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a dense vector to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side dense vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAddAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t ibegin( ( column <= row )?( 0UL ):( column - row ) );
+
+ for( size_t i=ibegin; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a dense vector to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side dense vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAddAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( row < column )
+ return true;
+
+ const size_t iend( min( row - column + 1UL, (~rhs).size() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a sparse vector to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side sparse vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAddAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ const RhsIterator last( (~rhs).end() );
+ RhsIterator element( (~rhs).lowerBound( ( column <= row )?( 0UL ):( column - row ) ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a sparse vector to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side sparse vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAddAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( row < column )
+ return true;
+
+ const RhsIterator last( (~rhs).lowerBound( row - column + 1UL ) );
+
+ for( RhsIterator element=(~rhs).begin(); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a dense matrix to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side dense matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAddAssign( const UniUpperMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t ibegin( ( column <= row )?( 0UL ):( column - row ) );
+
+ for( size_t i=ibegin; i<M; ++i )
+ {
+ const size_t jend( min( row + i - column + 1UL, N ) );
+
+ for( size_t j=0UL; j<jend; ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a dense matrix to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side dense matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAddAssign( const UniUpperMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t jend( min( row + M - column, N ) );
+
+ for( size_t j=0UL; j<jend; ++j )
+ {
+ const bool containsDiagonal( column + j >= row );
+ const size_t ibegin( ( containsDiagonal )?( column + j - row ):( 0UL ) );
+
+ for( size_t i=ibegin; i<M; ++i ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a sparse matrix to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side sparse matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAddAssign( const UniUpperMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t ibegin( ( column < row )?( 0UL ):( column - row ) );
+
+ for( size_t i=ibegin; i<M; ++i )
+ {
+ const size_t index( row + i - column + 1UL );
+ const RhsIterator last( (~rhs).lowerBound( i, min( index, N ) ) );
+
+ for( RhsIterator element=(~rhs).begin(i); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a sparse matrix to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side sparse matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAddAssign( const UniUpperMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t jend( min( row + M - column, N ) );
+
+ for( size_t j=0UL; j<jend; ++j )
+ {
+ const bool containsDiagonal( column + j >= row );
+ const size_t index( ( containsDiagonal )?( column + j - row ):( 0UL ) );
+
+ const RhsIterator last( (~rhs).end(j) );
+ RhsIterator element( (~rhs).lowerBound( index, j ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to an uniupper
+// matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAddAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to an uniupper
+// matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const UniUpperMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAddAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side vector to be multiplied.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryMultAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ return ( column < row || (~rhs).size() <= column - row || isOne( (~rhs)[column-row] ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to an
+// uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side vector to be multiplied.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryMultAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ return ( row < column || (~rhs).size() <= row - column || isOne( (~rhs)[row-column] ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the division assignment of a vector to an uniupper matrix.
+// \ingroup uniupper_matrix
+//
+// \param lhs The target left-hand side uniupper matrix.
+// \param rhs The right-hand side vector divisor.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryDivAssign( const UniUpperMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryMultAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns a reference to the instance without the access restrictions to the lower part.
+// \ingroup math_shims
+//
+// \param m The uniupper matrix to be derestricted.
+// \return Reference to the matrix without access restrictions.
+//
+// This function returns a reference to the given uniupper matrix instance that has no access
+// restrictions to the lower part of the matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline MT& derestrict( UniUpperMatrix<MT,SO,DF>& m )
+{
+ return m.matrix_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Rows< UniUpperMatrix<MT,SO,DF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Columns< UniUpperMatrix<MT,SO,DF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSquare< UniUpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsUniUpper< UniUpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAdaptor< UniUpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsRestricted< UniUpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasConstDataAccess< UniUpperMatrix<MT,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAligned< UniUpperMatrix<MT,SO,DF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsPadded< UniUpperMatrix<MT,SO,DF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsResizable< UniUpperMatrix<MT,SO,DF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RemoveAdaptor< UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct DerestrictTrait< UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = MT&;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< UniUpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< UniUpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< UniUpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< DynamicMatrix<T,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< UniUpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< UniUpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CompressedMatrix<T,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniUpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< UniUpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< UniUpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< UniUpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< DynamicMatrix<T,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< UniUpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< UniUpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CompressedMatrix<T,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniUpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UniUpperMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = UpperMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< T, UniUpperMatrix<MT,SO,DF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = UpperMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< UniUpperMatrix<MT,SO,DF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< StaticVector<T,N,true>, UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< UniUpperMatrix<MT,SO,DF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< HybridVector<T,N,true>, UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UniUpperMatrix<MT,SO,DF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< DynamicVector<T,true>, UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF >
+struct MultTrait< UniUpperMatrix<MT,SO,DF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF >
+struct MultTrait< CustomVector<T,AF,PF,true>, UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UniUpperMatrix<MT,SO,DF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< CompressedVector<T,true>, UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< UniUpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< UniUpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< UniUpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< DynamicMatrix<T,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< UniUpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< UniUpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CompressedMatrix<T,SO1>, UniUpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< MultTrait_<MT1,MT2> >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniUpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UniUpperMatrix< MultTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct DivTrait< UniUpperMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = UpperMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename ET >
+struct ForEachTrait< UniUpperMatrix<MT,SO,DF>, Pow<ET> >
+{
+ using Type = UniUpperMatrix< ForEachTrait_< MT, Pow<ET> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MathTrait< UniUpperMatrix<MT1,SO1,DF1>, UniUpperMatrix<MT2,SO2,DF2> >
+{
+ using HighType = UniUpperMatrix< typename MathTrait<MT1,MT2>::HighType >;
+ using LowType = UniUpperMatrix< typename MathTrait<MT1,MT2>::LowType >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct SubmatrixTrait< UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RowTrait< UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ColumnTrait< UniUpperMatrix<MT,SO,DF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/UpperMatrix.h b/src/cpu/blaze/math/adaptors/UpperMatrix.h
new file mode 100644
index 00000000..ee55b8e8
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/UpperMatrix.h
@@ -0,0 +1,2279 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/UpperMatrix.h
+// \brief Header file for the implementation of a upper matrix adaptor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UPPERMATRIX_H_
+#define _BLAZE_MATH_ADAPTORS_UPPERMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/uppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/uppermatrix/Dense.h>
+#include <blaze/math/adaptors/uppermatrix/Sparse.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/StaticMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/trtri.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsDivisor.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/IsAdaptor.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// UPPERMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UpperMatrix operators */
+//@{
+template< typename MT, bool SO, bool DF >
+inline void reset( UpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void reset( UpperMatrix<MT,SO,DF>& m, size_t i );
+
+template< typename MT, bool SO, bool DF >
+inline void clear( UpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isDefault( const UpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline bool isIntact( const UpperMatrix<MT,SO,DF>& m );
+
+template< typename MT, bool SO, bool DF >
+inline void swap( UpperMatrix<MT,SO,DF>& a, UpperMatrix<MT,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given upper matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( UpperMatrix<MT,SO,DF>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the specified row/column of the given upper matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given upper matrix to their
+// default value. In case the given matrix is a \a rowMajor matrix the function resets the values
+// in row \a i, if it is a \a columnMajor matrix the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void reset( UpperMatrix<MT,SO,DF>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given upper matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper matrix to be cleared.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void clear( UpperMatrix<MT,SO,DF>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given upper matrix is in default state.
+// \ingroup upper_matrix
+//
+// \param m The upper matrix to be tested for its default state.
+// \return \a true in case the given matrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the matrix is in default state. For instance, in case the
+// matrix is instantiated for a built-in integral or floating point data type, the function
+// returns \a true in case all matrix elements are 0 and \a false in case any matrix element
+// is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UpperMatrix;
+
+ UpperMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isDefault( const UpperMatrix<MT,SO,DF>& m )
+{
+ return isDefault( m.matrix_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given lower matrix are intact.
+// \ingroup lower_matrix
+//
+// \param m The lower matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the lower matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UpperMatrix;
+
+ UpperMatrix< DynamicMatrix<int> > A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline bool isIntact( const UpperMatrix<MT,SO,DF>& m )
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+// \ingroup upper_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline void swap( UpperMatrix<MT,SO,DF>& a, UpperMatrix<MT,SO,DF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given upper dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given upper dense \f$ 2 \times 2 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert2x2( UpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ DerestrictTrait_<MT> A( derestrict( m ) );
+
+ const ET det( A(0,0) * A(1,1) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+ const ET a11( A(0,0) * idet );
+
+ A(0,0) = A(1,1) * idet;
+ A(0,1) = -A(0,1) * idet;
+ A(1,1) = a11;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given upper dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given upper dense \f$ 3 \times 3 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert3x3( UpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,3UL,3UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp( A(1,1)*A(2,2) );
+ const ET det( A(0,0)*tmp );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B(0,0) = tmp;
+ B(0,1) = - A(0,1)*A(2,2);
+ B(1,1) = A(0,0)*A(2,2);
+ B(0,2) = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ B(1,2) = - A(0,0)*A(1,2);
+ B(2,2) = A(0,0)*A(1,1);
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given upper dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given upper dense \f$ 4 \times 4 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert4x4( UpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,4UL,4UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ ET tmp1( A(2,2)*A(3,3) );
+ ET tmp2( A(0,1)*A(1,2) - A(0,2)*A(1,1) );
+ ET tmp3( A(0,0)*A(1,2) );
+ ET tmp4( A(0,0)*A(1,1) );
+
+ const ET det( A(0,0)*A(1,1)*tmp1 );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B(0,0) = A(1,1)*tmp1;
+ B(0,1) = - A(0,1)*tmp1;
+ B(1,1) = A(0,0)*tmp1;
+ B(0,2) = A(3,3)*tmp2;
+ B(1,2) = - A(3,3)*tmp3;
+ B(2,2) = A(3,3)*tmp4;
+ B(0,3) = A(2,2)*( A(0,1)*A(1,3) - A(0,3)*A(1,1) ) - A(2,3)*tmp2;
+ B(1,3) = A(2,3)*tmp3 - A(2,2)*A(0,0)*A(1,3);
+ B(2,3) = - A(2,3)*tmp4;
+ B(3,3) = A(2,2)*tmp4;
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given upper dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given upper dense \f$ 5 \times 5 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert5x5( UpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,5UL,5UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp1( A(3,3)*A(4,4) );
+ const ET tmp2( A(0,1)*A(1,2) - A(0,2)*A(1,1) );
+ const ET tmp3( A(0,0)*A(1,2) );
+ const ET tmp4( A(0,0)*A(1,1) );
+
+ const ET tmp5 ( A(2,2)*tmp1 );
+ const ET tmp6 ( A(1,2)*tmp1 );
+ const ET tmp7 ( A(1,1)*tmp1 );
+ const ET tmp8 ( A(2,3)*tmp2 - A(2,2)*( A(0,1)*A(1,3) - A(0,3)*A(1,1) ) );
+ const ET tmp9 ( A(2,3)*tmp3 - A(2,2)*A(0,0)*A(1,3) );
+ const ET tmp10( A(2,3)*tmp4 );
+ const ET tmp11( A(2,2)*tmp4 );
+
+ B(0,0) = A(1,1)*tmp5;
+ B(0,1) = - A(0,1)*tmp5;
+ B(1,1) = A(0,0)*tmp5;
+ B(0,2) = A(0,1)*tmp6 - A(0,2)*tmp7;
+ B(1,2) = - A(0,0)*tmp6;
+ B(2,2) = A(0,0)*tmp7;
+ B(0,3) = - A(4,4)*tmp8;
+ B(1,3) = A(4,4)*tmp9;
+ B(2,3) = - A(4,4)*tmp10;
+ B(3,3) = A(4,4)*tmp11;
+ B(0,4) = A(3,4)*tmp8 - A(3,3)*( A(2,4)*tmp2 - A(2,2)*( A(0,1)*A(1,4) - A(0,4)*A(1,1) ) );
+ B(1,4) = A(3,3)*( A(2,4)*tmp3 - A(2,2)*A(0,0)*A(1,4) ) - A(3,4)*tmp9;
+ B(2,4) = A(3,4)*tmp10 - A(3,3)*A(2,4)*tmp4;
+ B(3,4) = - A(3,4)*tmp11;
+ B(4,4) = A(3,3)*tmp11;
+
+ const ET det( A(0,0) * B(0,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given upper dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+//
+// This function inverts the given upper dense \f$ 6 \times 6 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert6x6( UpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,6UL,6UL,SO> A( m );
+ DerestrictTrait_<MT> B( derestrict( m ) );
+
+ const ET tmp1( A(0,1)*A(1,2) - A(0,2)*A(1,1) );
+ const ET tmp2( A(0,0)*A(1,2) );
+ const ET tmp3( A(0,0)*A(1,1) );
+
+ const ET tmp4( A(3,3)*A(4,4)*A(5,5) );
+ const ET tmp5( A(2,3)*tmp1 - A(2,2)*( A(0,1)*A(1,3) - A(0,3)*A(1,1) ) );
+ const ET tmp6( A(2,3)*tmp2 - A(0,0)*A(1,3)*A(2,2) );
+ const ET tmp7( A(2,3)*tmp3 );
+ const ET tmp8( A(2,2)*tmp3 );
+
+ const ET tmp9 ( A(2,2)*tmp4 );
+ const ET tmp10( A(1,2)*tmp4 );
+ const ET tmp11( A(1,1)*tmp4 );
+ const ET tmp12( A(3,3)*( A(2,4)*tmp1 - A(2,2)*( A(0,1)*A(1,4) - A(0,4)*A(1,1) ) ) - A(3,4)*tmp5 );
+ const ET tmp13( A(3,3)*( A(2,4)*tmp2 - A(0,0)*A(1,4)*A(2,2) ) - A(3,4)*tmp6 );
+ const ET tmp14( A(3,3)*A(2,4)*tmp3 - A(3,4)*tmp7 );
+ const ET tmp15( - A(3,4)*tmp8 );
+ const ET tmp16( - A(3,3)*tmp8 );
+
+ B(0,0) = A(1,1)*tmp9;
+ B(0,1) = - A(0,1)*tmp9;
+ B(1,1) = A(0,0)*tmp9;
+ B(0,2) = A(0,1)*tmp10 - A(0,2)*tmp11;
+ B(1,2) = - A(0,0)*tmp10;
+ B(2,2) = A(0,0)*tmp11;
+ B(0,3) = - A(5,5)*A(4,4)*tmp5;
+ B(1,3) = A(5,5)*A(4,4)*tmp6;
+ B(2,3) = - A(5,5)*A(4,4)*tmp7;
+ B(3,3) = A(5,5)*A(4,4)*tmp8;
+ B(0,4) = - A(5,5)*tmp12;
+ B(1,4) = A(5,5)*tmp13;
+ B(2,4) = - A(5,5)*tmp14;
+ B(3,4) = A(5,5)*tmp15;
+ B(4,4) = - A(5,5)*tmp16;
+ B(0,5) = - A(4,4)*( A(3,3)*( A(2,5)*tmp1 - A(2,2)*( A(0,1)*A(1,5) - A(0,5)*A(1,1) ) ) - A(3,5)*tmp5 ) + A(4,5)*tmp12;
+ B(1,5) = A(4,4)*( A(3,3)*( A(2,5)*tmp2 - A(0,0)*A(1,5)*A(2,2) ) - A(3,5)*tmp6 ) - A(4,5)*tmp13;
+ B(2,5) = - A(4,4)*( A(3,3)*A(2,5)*tmp3 - A(3,5)*tmp7 ) + A(4,5)*tmp14;
+ B(3,5) = - A(4,4)*A(3,5)*tmp8 - A(4,5)*tmp15;
+ B(4,5) = A(4,5)*tmp16;
+ B(5,5) = - A(4,4)*tmp16;
+
+ const ET det( A(0,0)*B(0,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( m ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given upper dense matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given upper dense matrix by means of the most suited matrix inversion
+// algorithm. The matrix inversion fails if the given matrix is singular and not invertible. In
+// this case a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByDefault( UpperMatrix<MT,SO,true>& m )
+{
+ invertByLU( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place LU-based inversion of the given upper dense matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given upper dense matrix by means of an LU decomposition. The
+// matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLU( UpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ DerestrictTrait_<MT> A( derestrict( ~m ) );
+
+ trtri( A, 'U', 'N' );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given upper dense matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given upper dense matrix by means of a Bunch-Kaufman decomposition.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLT( UpperMatrix<MT,SO,true>& m )
+{
+ invertByLLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given upper dense matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given upper dense matrix by means of a Bunch-Kaufman decomposition.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLH( UpperMatrix<MT,SO,true>& m )
+{
+ invertByLLH( m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Cholesky-based inversion of the given upper dense matrix.
+// \ingroup upper_matrix
+//
+// \param m The upper dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given upper dense matrix by means of a Cholesky decomposition. The
+// matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::invalid_argument exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a m may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLLH( UpperMatrix<MT,SO,true>& m )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( isDiagonal( ~m ), "Violation of preconditions detected" );
+
+ DerestrictTrait_<MT> A( derestrict( ~m ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ if( !isDivisor( A(i,i) ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ invert( A(i,i) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief LU decomposition of the given upper dense matrix.
+// \ingroup upper_matrix
+//
+// \param A The upper matrix to be decomposed.
+// \param L The resulting lower triangular matrix.
+// \param U The resulting upper triangular matrix.
+// \param P The resulting permutation matrix.
+// \return void
+//
+// This function performs the dense matrix (P)LU decomposition of a upper n-by-n matrix. The
+// resulting decomposition is written to the three distinct matrices \c L, \c U, and \c P, which
+// are resized to the correct dimensions (if possible and necessary).
+//
+// \note The LU decomposition will never fail, even for singular matrices. However, in case of a
+// singular matrix the resulting decomposition cannot be used for a matrix inversion or solving
+// a linear system of equations.
+*/
+template< typename MT1, bool SO1, typename MT2, typename MT3, typename MT4, bool SO2 >
+inline void lu( const UpperMatrix<MT1,SO1,true>& A, DenseMatrix<MT2,SO1>& L,
+ DenseMatrix<MT3,SO1>& U, Matrix<MT4,SO2>& P )
+{
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE( MT3 );
+
+ typedef ElementType_<MT2> ET2;
+ typedef ElementType_<MT4> ET4;
+
+ const size_t n( (~A).rows() );
+
+ DerestrictTrait_<MT2> L2( derestrict( ~L ) );
+
+ (~U) = A;
+
+ resize( ~L, n, n );
+ reset( L2 );
+
+ resize( ~P, n, n );
+ reset( ~P );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ L2(i,i) = ET2(1);
+ (~P)(i,i) = ET4(1);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const UpperMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t ibegin( ( column < row )?( 0UL ):( column - row + 1UL ) );
+
+ for( size_t i=ibegin; i<(~rhs).size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense vector to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side dense vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side dense vector
+inline bool tryAssign( const UpperMatrix<MT,SO,DF>& lhs,
+ const DenseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ if( row <= column )
+ return true;
+
+ const size_t iend( min( row - column, (~rhs).size() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ if( !isDefault( (~rhs)[i] ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const UpperMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.rows() - row, "Invalid number of rows" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ const RhsIterator last( (~rhs).end() );
+ RhsIterator element( (~rhs).lowerBound( ( column < row )?( 0UL ):( column - row + 1UL ) ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse vector to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT > // Type of the right-hand side sparse vector
+inline bool tryAssign( const UpperMatrix<MT,SO,DF>& lhs,
+ const SparseVector<VT,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename VT::ConstIterator RhsIterator;
+
+ if( row <= column )
+ return true;
+
+ const RhsIterator last( (~rhs).lowerBound( row - column ) );
+
+ for( RhsIterator element=(~rhs).begin(); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const UpperMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t ibegin( ( column < row )?( 0UL ):( column - row + 1UL ) );
+
+ for( size_t i=ibegin; i<M; ++i )
+ {
+ const size_t jend( min( row + i - column, N ) );
+
+ for( size_t j=0UL; j<jend; ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a dense matrix to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side dense matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side dense matrix
+inline bool tryAssign( const UpperMatrix<MT1,SO,DF>& lhs,
+ const DenseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t jend( min( row + M - column - 1UL, N ) );
+
+ for( size_t j=0UL; j<jend; ++j )
+ {
+ const bool containsDiagonal( column + j >= row );
+ const size_t ibegin( ( containsDiagonal )?( column + j - row + 1UL ):( 0UL ) );
+
+ for( size_t i=ibegin; i<M; ++i ) {
+ if( !isDefault( (~rhs)(i,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const UpperMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,false>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t ibegin( ( column < row )?( 0UL ):( column - row + 1UL ) );
+
+ for( size_t i=ibegin; i<M; ++i )
+ {
+ const size_t index( row + i - column );
+ const RhsIterator last( (~rhs).lowerBound( i, min( index, N ) ) );
+
+ for( RhsIterator element=(~rhs).begin(i); element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a sparse matrix to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 > // Type of the right-hand side sparse matrix
+inline bool tryAssign( const UpperMatrix<MT1,SO,DF>& lhs,
+ const SparseMatrix<MT2,true>& rhs, size_t row, size_t column )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs );
+
+ typedef typename MT2::ConstIterator RhsIterator;
+
+ const size_t M( (~rhs).rows() );
+ const size_t N( (~rhs).columns() );
+
+ if( column + 1UL >= row + M )
+ return true;
+
+ const size_t jend( min( row + M - column - 1UL, N ) );
+
+ for( size_t j=0UL; j<jend; ++j )
+ {
+ const bool containsDiagonal( column + j >= row );
+ const size_t index( ( containsDiagonal )?( column + j - row + 1UL ):( 0UL ) );
+
+ const RhsIterator last( (~rhs).end(j) );
+ RhsIterator element( (~rhs).lowerBound( index, j ) );
+
+ for( ; element!=last; ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryAddAssign( const UpperMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAddAssign( const UpperMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const UpperMatrix<MT,SO,DF>& lhs,
+ const Vector<VT,TF>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a upper matrix.
+// \ingroup upper_matrix
+//
+// \param lhs The target left-hand side upper matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the adapted matrix
+ , bool SO1 // Storage order of the adapted matrix
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const UpperMatrix<MT1,SO1,DF>& lhs,
+ const Matrix<MT2,SO2>& rhs, size_t row, size_t column )
+{
+ return tryAssign( lhs, ~rhs, row, column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns a reference to the instance without the access restrictions to the lower part.
+// \ingroup math_shims
+//
+// \param m The upper matrix to be derestricted.
+// \return Reference to the matrix without access restrictions.
+//
+// This function returns a reference to the given upper matrix instance that has no access
+// restrictions to the lower part of the matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO // Storage order of the adapted matrix
+ , bool DF > // Density flag
+inline MT& derestrict( UpperMatrix<MT,SO,DF>& m )
+{
+ return m.matrix_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Rows< UpperMatrix<MT,SO,DF> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct Columns< UpperMatrix<MT,SO,DF> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsSquare< UpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsUpper< UpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAdaptor< UpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsRestricted< UpperMatrix<MT,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasConstDataAccess< UpperMatrix<MT,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsAligned< UpperMatrix<MT,SO,DF> > : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsPadded< UpperMatrix<MT,SO,DF> > : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct IsResizable< UpperMatrix<MT,SO,DF> > : public BoolConstant< IsResizable<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVEADAPTOR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RemoveAdaptor< UpperMatrix<MT,SO,DF> >
+{
+ using Type = MT;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct DerestrictTrait< UpperMatrix<MT,SO,DF> >
+{
+ using Type = MT&;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< UpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< StaticMatrix<T,M,N,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct AddTrait< UpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = AddTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< HybridMatrix<T,M,N,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< UpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< DynamicMatrix<T,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct AddTrait< UpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = AddTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CustomMatrix<T,AF,PF,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct AddTrait< UpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = AddTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct AddTrait< CompressedMatrix<T,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = AddTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< HermitianMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< LowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UniLowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = AddTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct AddTrait< UpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< AddTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< UpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< StaticMatrix<T,M,N,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct SubTrait< UpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = SubTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< HybridMatrix<T,M,N,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< UpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< DynamicMatrix<T,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct SubTrait< UpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = SubTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CustomMatrix<T,AF,PF,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct SubTrait< UpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = SubTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct SubTrait< CompressedMatrix<T,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = SubTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< HermitianMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< LowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UniLowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = SubTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct SubTrait< UpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< SubTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UpperMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = UpperMatrix< MultTrait_<MT,T> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< T, UpperMatrix<MT,SO,DF>, EnableIf_< IsNumeric<T> > >
+{
+ using Type = UpperMatrix< MultTrait_<T,MT> >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< UpperMatrix<MT,SO,DF>, StaticVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, StaticVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< StaticVector<T,N,true>, UpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< StaticVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, size_t N >
+struct MultTrait< UpperMatrix<MT,SO,DF>, HybridVector<T,N,false> >
+{
+ using Type = MultTrait_< MT, HybridVector<T,N,false> >;
+};
+
+template< typename T, size_t N, typename MT, bool SO, bool DF >
+struct MultTrait< HybridVector<T,N,true>, UpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< HybridVector<T,N,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UpperMatrix<MT,SO,DF>, DynamicVector<T,false> >
+{
+ using Type = MultTrait_< MT, DynamicVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< DynamicVector<T,true>, UpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< DynamicVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF >
+struct MultTrait< UpperMatrix<MT,SO,DF>, CustomVector<T,AF,PF,false> >
+{
+ using Type = MultTrait_< MT, CustomVector<T,AF,PF,false> >;
+};
+
+template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF >
+struct MultTrait< CustomVector<T,AF,PF,true>, UpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CustomVector<T,AF,PF,true>, MT >;
+};
+
+template< typename MT, bool SO, bool DF, typename T >
+struct MultTrait< UpperMatrix<MT,SO,DF>, CompressedVector<T,false> >
+{
+ using Type = MultTrait_< MT, CompressedVector<T,false> >;
+};
+
+template< typename T, typename MT, bool SO, bool DF >
+struct MultTrait< CompressedVector<T,true>, UpperMatrix<MT,SO,DF> >
+{
+ using Type = MultTrait_< CompressedVector<T,true>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< UpperMatrix<MT,SO1,DF>, StaticMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, StaticMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< StaticMatrix<T,M,N,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< StaticMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 >
+struct MultTrait< UpperMatrix<MT,SO1,DF>, HybridMatrix<T,M,N,SO2> >
+{
+ using Type = MultTrait_< MT, HybridMatrix<T,M,N,SO2> >;
+};
+
+template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< HybridMatrix<T,M,N,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< HybridMatrix<T,M,N,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< UpperMatrix<MT,SO1,DF>, DynamicMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, DynamicMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< DynamicMatrix<T,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< DynamicMatrix<T,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 >
+struct MultTrait< UpperMatrix<MT,SO1,DF>, CustomMatrix<T,AF,PF,SO2> >
+{
+ using Type = MultTrait_< MT, CustomMatrix<T,AF,PF,SO2> >;
+};
+
+template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CustomMatrix<T,AF,PF,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CustomMatrix<T,AF,PF,SO1>, MT >;
+};
+
+template< typename MT, bool SO1, bool DF, typename T, bool SO2 >
+struct MultTrait< UpperMatrix<MT,SO1,DF>, CompressedMatrix<T,SO2> >
+{
+ using Type = MultTrait_< MT, CompressedMatrix<T,SO2> >;
+};
+
+template< typename T, bool SO1, typename MT, bool SO2, bool DF >
+struct MultTrait< CompressedMatrix<T,SO1>, UpperMatrix<MT,SO2,DF> >
+{
+ using Type = MultTrait_< CompressedMatrix<T,SO1>, MT >;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, SymmetricMatrix<MT2,SO2,DF2,NF> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< SymmetricMatrix<MT1,SO1,DF1,NF>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, HermitianMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< HermitianMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, LowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< LowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, UniLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UniLowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, StrictlyLowerMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< StrictlyLowerMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = MultTrait_<MT1,MT2>;
+};
+
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MultTrait< UpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using Type = UpperMatrix< MultTrait_<MT1,MT2> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, typename T >
+struct DivTrait< UpperMatrix<MT,SO,DF>, T, EnableIf_< IsNumeric<T> > >
+{
+ using Type = UpperMatrix< DivTrait_<MT,T> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FOREACHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Abs >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Abs> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Floor >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Floor> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Ceil >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Ceil> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Conj >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Conj> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Real >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Real> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Imag >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Imag> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Sin >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Sin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Asin >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Asin> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Sinh >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Sinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Asinh >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Asinh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Tan >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Tan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Atan >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Atan> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Tanh >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Tanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Atanh >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Atanh> >;
+};
+
+template< typename MT, bool SO, bool DF >
+struct ForEachTrait< UpperMatrix<MT,SO,DF>, Erf >
+{
+ using Type = UpperMatrix< ForEachTrait_<MT,Erf> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 >
+struct MathTrait< UpperMatrix<MT1,SO1,DF1>, UpperMatrix<MT2,SO2,DF2> >
+{
+ using HighType = UpperMatrix< typename MathTrait<MT1,MT2>::HighType >;
+ using LowType = UpperMatrix< typename MathTrait<MT1,MT2>::LowType >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct SubmatrixTrait< UpperMatrix<MT,SO,DF> >
+{
+ using Type = SubmatrixTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct RowTrait< UpperMatrix<MT,SO,DF> >
+{
+ using Type = RowTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF >
+struct ColumnTrait< UpperMatrix<MT,SO,DF> >
+{
+ using Type = ColumnTrait_<MT>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/diagonalmatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/diagonalmatrix/BaseTemplate.h
new file mode 100644
index 00000000..3524c4b4
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/diagonalmatrix/BaseTemplate.h
@@ -0,0 +1,562 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/diagonalmatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the DiagonalMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup diagonal_matrix DiagonalMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for diagonal \f$ N \times N \f$ matrices.
+// \ingroup diagonal_matrix
+//
+// \section diagonalmatrix_general General
+//
+// The DiagonalMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \a MT and extends it by
+// enforcing the additional invariant that all matrix elements above and below the diagonal are
+// 0 (diagonal matrix). The type of the adapted matrix can be specified via the first template
+// parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF >
+ class DiagonalMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. DiagonalMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Note that the given matrix type must be either resizable (as for instance
+// HybridMatrix or DynamicMatrix) or must be square at compile time (as for instance
+// StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+// The following examples give an impression of several possible diagonal matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense diagonal matrix with static memory
+ blaze::DiagonalMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense diagonal matrix based on HybridMatrix
+ blaze::DiagonalMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense diagonal matrix based on DynamicMatrix
+ blaze::DiagonalMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense diagonal matrix based on CustomMatrix
+ blaze::DiagonalMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision diagonal matrix
+ blaze::DiagonalMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of a diagonal matrix is depending on the storage order of the adapted matrix
+// type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified
+// as blaze::rowMajor), the diagonal matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the diagonal matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section diagonalmatrix_special_properties Special Properties of Diagonal Matrices
+//
+// A diagonal matrix is used exactly like a matrix of the underlying, adapted matrix type \a MT.
+// It also provides (nearly) the same interface as the underlying matrix type. However, there
+// are some important exceptions resulting from the diagonal matrix constraint:
+//
+// -# <b>\ref diagonalmatrix_square</b>
+// -# <b>\ref diagonalmatrix_diagonal</b>
+// -# <b>\ref diagonalmatrix_initialization</b>
+// -# <b>\ref diagonalmatrix_storage</b>
+//
+// \n \subsection diagonalmatrix_square Diagonal Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DiagonalMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 diagonal dynamic matrix
+ DiagonalMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::DiagonalMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 diagonal static matrix
+ DiagonalMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ DiagonalMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection diagonalmatrix_diagonal The Diagonal Matrix Property is Always Enforced!
+//
+// This means that it is only allowed to modify elements on the the diagonal of the matrix, but
+// not the elements in the lower or upper part of the matrix. Also, it is only possible to assign
+// matrices that are diagonal matrices themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::DiagonalMatrix;
+ using blaze::rowMajor;
+
+ typedef DiagonalMatrix< CompressedMatrix<double,rowMajor> > CompressedDiagonal;
+
+ // Default constructed, row-major 3x3 diagonal compressed matrix
+ CompressedDiagonal A( 3 );
+
+ // Initializing elements via the function call operator
+ A(0,0) = 1.0; // Initialization of the diagonal element (0,0)
+ A(1,0) = 9.0; // Throws an exception; invalid modification of lower element
+
+ // Inserting more elements via the insert() function
+ A.insert( 1, 1, 3.0 ); // Inserting the diagonal element (1,1)
+ A.insert( 0, 2, 9.0 ); // Throws an exception; invalid insertion of upper element
+
+ // Appending an element via the append() function
+ A.reserve( 2, 1 ); // Reserving enough capacity in row 2
+ A.append( 2, 2, 5.0 ); // Appending the diagonal element (2,2)
+ A.append( 1, 2, 9.0 ); // Throws an exception; appending an element in the upper part
+
+ // Access via a non-const iterator
+ CompressedDiagonal::Iterator it = A.begin(1);
+ *it = 6.0; // Modifies the element (1,1)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 2, 2 ); // Erasing the diagonal element (2,2)
+
+ // Construction from a diagonal dense matrix
+ StaticMatrix<double,3UL,3UL> B( 3.0, 0.0, 0.0,
+ 0.0, -2.0, 0.0,
+ 0.0, 0.0, 4.0 );
+
+ DiagonalMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-diagonal dense matrix
+ StaticMatrix<double,3UL,3UL> D( 3.0, 0.0, 9.0,
+ 0.0, -2.0, 0.0,
+ 0.0, 0.0, 4.0 );
+
+ C = D; // Throws an exception; diagonal matrix invariant would be violated!
+ \endcode
+
+// The diagonal matrix property is also enforced for diagonal custom matrices: In case the given
+// array of elements does not represent a diagonal matrix, a \a std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::DiagonalMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef DiagonalMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomDiagonal;
+
+ // Creating a 3x3 diagonal custom matrix from a properly initialized array
+ double array[9] = { 1.0, 0.0, 0.0,
+ 0.0, 2.0, 0.0,
+ 0.0, 0.0, 3.0 };
+ CustomDiagonal A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 diagonal custom matrix from an uninitialized array
+ CustomDiagonal B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the diagonal matrix property is enforced for views (rows, columns, submatrices, ...)
+// on the diagonal matrix. The following example demonstrates that modifying the elements of an
+// entire row and submatrix of a diagonal matrix only affects the diagonal matrix elements:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DiagonalMatrix;
+
+ // Setup of the diagonal matrix
+ //
+ // ( 0 0 0 0 )
+ // A = ( 0 1 0 0 )
+ // ( 0 0 2 0 )
+ // ( 0 0 0 3 )
+ //
+ DiagonalMatrix< DynamicMatrix<int> > A( 4 );
+ A(1,1) = 1;
+ A(2,2) = 2;
+ A(3,3) = 3;
+
+ // Setting the diagonal element in the 2nd row to 9 results in the matrix
+ //
+ // ( 0 0 0 0 )
+ // A = ( 0 1 0 0 )
+ // ( 0 0 9 0 )
+ // ( 0 0 0 3 )
+ //
+ row( A, 2 ) = 9;
+
+ // Setting the diagonal element in the 1st and 2nd column to 7 results in
+ //
+ // ( 0 0 0 0 )
+ // A = ( 0 7 0 0 )
+ // ( 0 0 7 0 )
+ // ( 0 0 0 3 )
+ //
+ submatrix( A, 0, 1, 4, 2 ) = 7;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to rows/columns and submatrices of
+// diagonal matrices. Since only diagonal elements may be modified the matrix to be assigned
+// must be structured such that the diagonal matrix invariant of the diagonal matrix is
+// preserved. Otherwise a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::DiagonalMatrix;
+ using blaze::rowVector;
+
+ // Setup of two default 4x4 diagonal matrices
+ DiagonalMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of a 4-dimensional vector
+ //
+ // v = ( 0 0 3 0 )
+ //
+ DynamicVector<int,rowVector> v( 4, 0 );
+ v[2] = 3;
+
+ // OK: Assigning v to the 2nd row of A1 preserves the diagonal matrix invariant
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 0 0 0 )
+ // ( 0 0 3 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 2 ) = v; // OK
+
+ // Error: Assigning v to the 1st row of A1 violates the diagonal matrix invariant! The element
+ // marked with X cannot be assigned and triggers an exception.
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 0 X 0 )
+ // ( 0 0 3 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 1 ) = v; // Assignment throws an exception!
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 0 0 )
+ // B = ( 2 0 )
+ // ( 0 3 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL, 0 );
+ B(1,0) = 2;
+ B(2,1) = 3;
+
+ // OK: Assigning B to a submatrix of A2 such that the diagonal matrix invariant can be preserved
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 2 0 0 )
+ // ( 0 0 3 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the diagonal matrix invariant cannot be
+ // preserved! The elements marked with X cannot be assigned without violating the invariant!
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 2 X 0 )
+ // ( 0 0 3 X )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 2UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection diagonalmatrix_initialization The Lower and Upper Elements of a Dense Diagonal Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency during the creation of a dense diagonal
+// matrix this initialization is important since otherwise the diagonal matrix property of dense
+// diagonal matrices would not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DiagonalMatrix;
+
+ // Uninitialized, 5x5 row-major diagonal matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // 5x5 row-major diagonal dynamic matrix with default initialized lower and upper matrix
+ DiagonalMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \subsection diagonalmatrix_storage Dense Diagonal Matrices Also Store the Non-diagonal Elements!
+//
+// It is very important to note that dense diagonal matrices store all elements, including the
+// non-diagonal elements, and therefore don't provide any kind of memory reduction! There are
+// two main reasons for this: First, storing also the non-diagonal elements guarantees maximum
+// performance for many algorithms that perform vectorized operations on the diagonal matrix,
+// which is especially true for small dense matrices. Second, conceptually the DiagonalMatrix
+// adaptor merely restricts the interface to the matrix type \a MT and does not change the data
+// layout or the underlying matrix type. Thus, in order to achieve the perfect combination of
+// performance and memory consumption it is recommended to use dense matrices for small diagonal
+// matrices and sparse matrices for large diagonal matrices:
+
+ \code
+ // Recommendation 1: use dense matrices for small diagonal matrices
+ typedef blaze::DiagonalMatrix< blaze::StaticMatrix<float,3UL,3UL> > SmallDiagonalMatrix;
+
+ // Recommendation 2: use sparse matrices for large diagonal matrices
+ typedef blaze::DiagonalMatrix< blaze::CompressedMatrix<float> > LargeDiagonalMatrix;
+ \endcode
+
+// \n \section diagonalmatrix_arithmetic_operations Arithmetic Operations
+//
+// A DiagonalMatrix matrix can participate in numerical operations in any way any other dense or
+// sparse matrix can participate. It can also be combined with any other dense or sparse vector
+// or matrix. The following code example gives an impression of the use of DiagonalMatrix within
+// arithmetic operations:
+
+ \code
+ using blaze::DiagonalMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ DiagonalMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ DiagonalMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ DiagonalMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > E;
+ DiagonalMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major diagonal matrix
+ F = C - D; // Matrix subtraction and assignment to a column-major diagonal matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section diagonalmatrix_block_structured Block-Structured Diagonal Matrices
+//
+// It is also possible to use block-structured diagonal matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticMatrix;
+ using blaze::DiagonalMatrix;
+
+ // Definition of a 5x5 block-structured diagonal matrix based on CompressedMatrix
+ DiagonalMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > A( 5 );
+ \endcode
+
+// Also in this case the diagonal matrix invariant is enforced, i.e. it is not possible to
+// manipulate elements in the lower and upper part of the matrix:
+
+ \code
+ const StaticMatrix<int,3UL,3UL> B( { { 1, -4, 5 },
+ { 6, 8, -3 },
+ { 2, -1, 2 } } )
+
+ A.insert( 2, 2, B ); // Inserting the diagonal elements (2,2)
+ A(2,4)(1,1) = -5; // Invalid manipulation of upper matrix element; Results in an exception
+ \endcode
+
+// \n \section diagonalmatrix_performance Performance Considerations
+//
+// The \b Blaze library tries to exploit the properties of diagonal matrices whenever and wherever
+// possible. In fact, diagonal matrices come with several special kernels and additionally profit
+// from all optimizations for symmetric and triangular matrices. Thus using a diagonal matrix
+// instead of a general matrix can result in a considerable performance improvement. However,
+// there are also situations when using a diagonal triangular matrix introduces some overhead. The
+// following examples demonstrate several common situations where diagonal matrices can positively
+// or negatively impact performance.
+//
+// \n \subsection diagonalmatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is diagonal, \b Blaze can exploit the fact
+// that the lower and upper part of the matrix contains only default elements and restrict the
+// algorithm to the diagonal elements. The following example demonstrates this by means of a dense
+// matrix/dense matrix multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DiagonalMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DiagonalMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicMatrix<double,columnMajor> B, C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// In comparison to a general matrix multiplication, the performance advantage is significant,
+// especially for large matrices. In this particular case, the multiplication performs similarly
+// to a matrix addition since the complexity is reduced from \f$ O(N^3) \f$ to \f$ O(N^2) \f$.
+// Therefore is it highly recommended to use the DiagonalMatrix adaptor when a matrix is known
+// to be diagonal. Note however that the performance advantage is most pronounced for dense
+// matrices and much less so for sparse matrices.
+//
+// \n \subsection diagonalmatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar performance improvement can be gained when using a diagonal matrix in a matrix/vector
+// multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::DiagonalMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DiagonalMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicVector<double,columnVector> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example, \b Blaze also exploits the structure of the matrix and performs similarly to
+// a vector addition. Also in case of matrix/vector multiplications the performance improvement
+// is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection diagonalmatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a diagonal matrix on the right-hand side of an assignment (i.e. for read
+// access), which introduces absolutely no performance penalty, using a diagonal matrix on the
+// left-hand side of an assignment (i.e. for write access) may introduce additional overhead when
+// it is assigned a general matrix, which is not diagonal at compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DiagonalMatrix;
+
+ DiagonalMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the diagonal matrix; no performance penalty
+ C = A; // Assignment of a diagonal matrix to another diagonal matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a diagonal matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not diagonal matrix to a diagonal matrix it is necessary
+// to check whether the matrix is diagonal at runtime in order to guarantee the diagonal property
+// of the diagonal matrix. In case it turns out to be diagonal, it is assigned as efficiently as
+// possible, if it is not, an exception is thrown. In order to prevent this runtime overhead it
+// is therefore generally advisable to assign diagonal matrices to other diagonal matrices.\n
+// In this context it is especially noteworthy that the addition, subtraction, and multiplication
+// of two diagonal matrices always results in another diagonal matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DiagonalMatrix;
+
+ DiagonalMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a diagonal matrix; no runtime overhead
+ C = A - B; // Results in a diagonal matrix; no runtime overhead
+ C = A * B; // Results in a diagonal matrix; no runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class DiagonalMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/diagonalmatrix/Dense.h b/src/cpu/blaze/math/adaptors/diagonalmatrix/Dense.h
new file mode 100644
index 00000000..1ac6cacf
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/diagonalmatrix/Dense.h
@@ -0,0 +1,2650 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/diagonalmatrix/Dense.h
+// \brief DiagonalMatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_DENSE_H_
+#define _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/diagonalmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/diagonalmatrix/DiagonalProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/Square.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of DiagonalMatrix for dense matrices.
+// \ingroup diagonal_matrix
+//
+// This specialization of DiagonalMatrix adapts the class template to the requirements of dense
+// matrices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class DiagonalMatrix<MT,SO,true>
+ : public DenseMatrix< DiagonalMatrix<MT,SO,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DiagonalMatrix<MT,SO,true> This; //!< Type of this DiagonalMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this DiagonalMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef DiagonalMatrix<OT,!SO,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef DiagonalMatrix<TT,!SO,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef DiagonalProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a DiagonalMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other DiagonalMatrix.
+ typedef DiagonalMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense diagonal matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef DiagonalProxy<MT> PointerType; //!< Pointer return type.
+ typedef DiagonalProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row-index of the iterator
+ , column_( column ) // The current column-index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) noexcept {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row-index of the iterator.
+ size_t column_; //!< The current column-index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline DiagonalMatrix();
+ template< typename A1 > explicit inline DiagonalMatrix( const A1& a1 );
+ explicit inline DiagonalMatrix( size_t n, const ElementType& init );
+
+ explicit inline DiagonalMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline DiagonalMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline DiagonalMatrix( const Other (&array)[N][N] );
+
+ explicit inline DiagonalMatrix( ElementType* ptr, size_t n );
+ explicit inline DiagonalMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline DiagonalMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline DiagonalMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline DiagonalMatrix( const DiagonalMatrix& m );
+ inline DiagonalMatrix( DiagonalMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline DiagonalMatrix& operator=( const ElementType& rhs );
+ inline DiagonalMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline DiagonalMatrix& operator=( const Other (&array)[N][N] );
+
+ inline DiagonalMatrix& operator=( const DiagonalMatrix& rhs );
+ inline DiagonalMatrix& operator=( DiagonalMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, DiagonalMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, DiagonalMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, DiagonalMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, DiagonalMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, DiagonalMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, DiagonalMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DiagonalMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, DiagonalMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, DiagonalMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ template< typename Other > inline DiagonalMatrix& scale( const Other& scalar );
+ inline void swap( DiagonalMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ inline const MT construct( size_t n , TrueType );
+ inline const MT construct( const ElementType& value, FalseType );
+
+ template< typename MT2, bool SO2, typename T >
+ inline const MT construct( const Matrix<MT2,SO2>& m, T );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend bool isDefault( const DiagonalMatrix<MT2,SO2,DF2>& m );
+
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( DiagonalMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for DiagonalMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Single argument constructor for a diagonal matrix.
+//
+// \param a1 The single constructor argument.
+// \exception std::invalid_argument Invalid setup of diagonal matrix.
+//
+// This constructor constructs the diagonal matrix based on the given argument and the type
+// of the underlying matrix \a MT:
+// - in case the given argument is a matrix, the diagonal matrix is initialized as a copy of
+// the given matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// resizable, the given argument \a a1 specifies the number of rows and columns of the
+// diagonal matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// a matrix with fixed size, the given argument \a a1 specifies the initial value of the
+// diagonal elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename A1 > // Type of the constructor argument
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( const A1& a1 )
+ : matrix_( construct( a1, typename IsResizable<MT>::Type() ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a \f$ n \times n \f$ matrix with initialized diagonal elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param init The initial value of the diagonal matrix elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( size_t n, const ElementType& init )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ for( size_t i=0UL; i<n; ++i )
+ matrix_(i,i) = init;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of diagonal matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the diagonal
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DiagonalMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A{ { 1, 0, 0 },
+ { 0, 2 },
+ { 0, 0, 3 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isDiagonal( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all diagonal matrix elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of diagonal matrix.
+//
+// This constructor offers the option to directly initialize the elements of the diagonal matrix
+// with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[16];
+ // ... Initialization of the dynamic array
+ blaze::DiagonalMatrix< blaze::DynamicMatrix<int,rowMajor> > v( 4UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized according to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a m by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also,
+// in case the given array does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isDiagonal( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all diagonal matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of diagonal matrix.
+//
+// This constructor offers the option to directly initialize the elements of the diagonal matrix
+// with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 0, 0 },
+ { 0, 2 },
+ { 0, 0, 3 } };
+ blaze::DiagonalMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a diagonal matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isDiagonal( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a diagonal custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of diagonal custom matrix.
+//
+// This constructor creates an unpadded diagonal custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a diagonal matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded diagonal custom matrices!
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isDiagonal( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a diagonal custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of diagonal custom matrix.
+//
+// This constructor creates a diagonal custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a diagonal matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isDiagonal( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a diagonal custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of diagonal custom matrix.
+//
+// This constructor creates an unpadded diagonal custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a diagonal matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded diagonal custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isDiagonal( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a diagonal custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of diagonal custom matrix.
+//
+// This constructor creates a diagonal custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a diagonal matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isDiagonal( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for DiagonalMatrix.
+//
+// \param m The diagonal matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( const DiagonalMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for DiagonalMatrix.
+//
+// \param m The diagonal matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( DiagonalMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::Reference
+ DiagonalMatrix<MT,SO,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::ConstReference
+ DiagonalMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::Reference
+ DiagonalMatrix<MT,SO,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::ConstReference
+ DiagonalMatrix<MT,SO,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the diagonal matrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The diagonal matrix
+// may use techniques such as padding to improve the alignment of the data. Whereas the number
+// of elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::ConstPointer
+ DiagonalMatrix<MT,SO,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::ConstPointer
+ DiagonalMatrix<MT,SO,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the diagonal matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::Iterator
+ DiagonalMatrix<MT,SO,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the diagonal matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::ConstIterator
+ DiagonalMatrix<MT,SO,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the diagonal matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::ConstIterator
+ DiagonalMatrix<MT,SO,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the diagonal matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::Iterator
+ DiagonalMatrix<MT,SO,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the diagonal matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::ConstIterator
+ DiagonalMatrix<MT,SO,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the diagonal matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename DiagonalMatrix<MT,SO,true>::ConstIterator
+ DiagonalMatrix<MT,SO,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all diagonal matrix elements.
+//
+// \param rhs Scalar value to be assigned to the diagonal matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>&
+ DiagonalMatrix<MT,SO,true>::operator=( const ElementType& rhs )
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ matrix_(j,j) = rhs;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ matrix_(i,i) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the diagonal
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DiagonalMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = { { 1, 0, 0 },
+ { 0, 2 },
+ { 0, 0, 3 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>&
+ DiagonalMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all diagonal matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// This assignment operator offers the option to directly set all elements of the diagonal matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 0, 0 },
+ { 0, 2 },
+ { 0, 0, 3 } };
+ blaze::DiagonalMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a diagonal matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline DiagonalMatrix<MT,SO,true>&
+ DiagonalMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for DiagonalMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>&
+ DiagonalMatrix<MT,SO,true>::operator=( const DiagonalMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for DiagonalMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline DiagonalMatrix<MT,SO,true>&
+ DiagonalMatrix<MT,SO,true>::operator=( DiagonalMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// diagonal matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,true>& >
+ DiagonalMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsDiagonal<MT2>::value && !isDiagonal( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// diagonal matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,true>& >
+ DiagonalMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ if( IsDiagonal<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a
+// diagonal matrix, i.e. the given matrix must be a diagonal matrix. In case the result
+// is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,true>& >
+ DiagonalMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsDiagonal<MT2>::value && !isDiagonal( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a
+// diagonal matrix, i.e. the given matrix must be a diagonal matrix. In case the result
+// is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,true>& >
+ DiagonalMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ if( IsDiagonal<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a
+// diagonal matrix, i.e. the given matrix must be a diagonal matrix. In case the result
+// is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,true>& >
+ DiagonalMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsDiagonal<MT2>::value && !isDiagonal( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a
+// diagonal matrix, i.e. the given matrix must be a diagonal matrix. In case the result
+// is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,true>& >
+ DiagonalMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ if( IsDiagonal<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a diagonal matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DiagonalMatrix<MT,SO,true>&
+ DiagonalMatrix<MT,SO,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, DiagonalMatrix<MT,SO,true> >&
+ DiagonalMatrix<MT,SO,true>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, DiagonalMatrix<MT,SO,true> >&
+ DiagonalMatrix<MT,SO,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t DiagonalMatrix<MT,SO,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t DiagonalMatrix<MT,SO,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the total
+// number of elements of a row/column. In case the diagonal matrix adapts a \a rowMajor dense
+// matrix the function returns the spacing between two rows, in case it adapts a \a columnMajor
+// dense matrix the function returns the spacing between two columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t DiagonalMatrix<MT,SO,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t DiagonalMatrix<MT,SO,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the diagonal
+// matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor dense matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t DiagonalMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the diagonal matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t DiagonalMatrix<MT,SO,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the diagonal matrix adapts a \a rowMajor dense matrix the function returns the number
+// of non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix the
+// function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t DiagonalMatrix<MT,SO,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void DiagonalMatrix<MT,SO,true>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void DiagonalMatrix<MT,SO,true>::reset( size_t i )
+{
+ matrix_.reset( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the diagonal matrix.
+//
+// \return void
+//
+// This function clears the diagonal matrix and returns it to its default state. The function has
+// the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
+// matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
+// to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
+// be reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void DiagonalMatrix<MT,SO,true>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the diagonal matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the diagonal matrix adapts a resizable matrix, this function resizes the matrix using
+// the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
+// in case the capacity of the matrix is too small. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, the resize operation potentially changes all matrix elements. In order
+// to preserve the old matrix values, the \a preserve flag can be set to \a true. Also note that
+// in case the size of the matrix is increased, only the new elements in the upper part of the
+// matrix are default initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 0 & 0 \\
+ 2 & 3 & 0 \\
+ 4 & 5 & 6 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 0 & 0 & 0 \\
+ 2 & 3 & 0 & 0 \\
+ 4 & 5 & 6 & 0 \\
+ x & x & x & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void DiagonalMatrix<MT,SO,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize ) {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, 0UL, oldsize, n, increment ).reset();
+ submatrix( matrix_, oldsize, 0UL, increment, increment ).reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void DiagonalMatrix<MT,SO,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the diagonal matrix.
+// \return void
+//
+// This function increases the capacity of the diagonal matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void DiagonalMatrix<MT,SO,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the scalar value
+inline DiagonalMatrix<MT,SO,true>& DiagonalMatrix<MT,SO,true>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void DiagonalMatrix<MT,SO,true>::swap( DiagonalMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the diagonal matrix are intact.
+//
+// \return \a true in case the diagonal matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the diagonal matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool DiagonalMatrix<MT,SO,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isDiagonal( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool DiagonalMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool DiagonalMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool DiagonalMatrix<MT,SO,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool DiagonalMatrix<MT,SO,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the diagonal matrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename DiagonalMatrix<MT,SO,true>::SIMDType
+ DiagonalMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the diagonal matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename DiagonalMatrix<MT,SO,true>::SIMDType
+ DiagonalMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the diagonal matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename DiagonalMatrix<MT,SO,true>::SIMDType
+ DiagonalMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a resizable matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT DiagonalMatrix<MT,SO,true>::construct( size_t n, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ return MT( n, n, ElementType() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a fixed-size matrix with homogeneously initialized diagonal elements.
+//
+// \param init The initial value of the diagonal matrix elements.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT DiagonalMatrix<MT,SO,true>::construct( const ElementType& init, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SQUARE( MT );
+
+ MT tmp;
+
+ for( size_t i=0UL; i<tmp.rows(); ++i )
+ tmp(i,i) = init;
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a matrix as a copy from another matrix.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of diagonal matrix.
+// \return The newly constructed matrix.
+//
+// In case the given matrix is not a diagonal matrix, a \a std::invalid_argument exception is
+// thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT DiagonalMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ const MT tmp( ~m );
+
+ if( !IsDiagonal<MT2>::value && !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/diagonalmatrix/DiagonalProxy.h b/src/cpu/blaze/math/adaptors/diagonalmatrix/DiagonalProxy.h
new file mode 100644
index 00000000..c281d914
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/diagonalmatrix/DiagonalProxy.h
@@ -0,0 +1,665 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/diagonalmatrix/DiagonalProxy.h
+// \brief Header file for the DiagonalProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_DIAGONALPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_DIAGONALPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/typetraits/AddConst.h>
+#include <blaze/util/typetraits/AddReference.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for diagonal matrices.
+// \ingroup diagonal_matrix
+//
+// The DiagonalProxy provides controlled access to the elements of a non-const diagonal matrix.
+// It guarantees that the diagonal matrix invariant is not violated, i.e. that elements in the
+// lower and upper part of the matrix remain default values. The following example illustrates
+// this by means of a \f$ 3 \times 3 \f$ dense diagonal matrix:
+
+ \code
+ // Creating a 3x3 dense diagonal matrix
+ blaze::DiagonalMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(0,0) = -2; // ( -2 0 0 )
+ A(1,1) = 3; // => A = ( 0 3 0 )
+ A(2,2) = 5; // ( 0 0 5 )
+
+ A(0,2) = 7; // Invalid assignment to upper matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class DiagonalProxy : public Proxy< DiagonalProxy<MT>, ElementType_<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Reference type of the underlying matrix type.
+ typedef AddConst_< typename MT::Reference > ReferenceType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+ typedef AddReference_<ReferenceType> RawReference; //!< Reference-to-non-const to the represented element.
+ typedef const RepresentedType& ConstReference; //!< Reference-to-const to the represented element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline DiagonalProxy( MT& matrix, size_t row, size_t column );
+ inline DiagonalProxy( const DiagonalProxy& dp );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline DiagonalProxy& operator=( const DiagonalProxy& dp );
+
+ template< typename T >
+ inline DiagonalProxy& operator=( initializer_list<T> list );
+
+ template< typename T >
+ inline DiagonalProxy& operator=( initializer_list< initializer_list<T> > list );
+
+ template< typename T > inline DiagonalProxy& operator= ( const T& value );
+ template< typename T > inline DiagonalProxy& operator+=( const T& value );
+ template< typename T > inline DiagonalProxy& operator-=( const T& value );
+ template< typename T > inline DiagonalProxy& operator*=( const T& value );
+ template< typename T > inline DiagonalProxy& operator/=( const T& value );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline RawReference get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator ConstReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ ReferenceType value_; //!< Reference to the accessed matrix element.
+ const bool restricted_; //!< Access flag for the accessed matrix element.
+ /*!< The flag indicates if access to the matrix element is
+ restricted. It is \a true in case the proxy represents
+ an element in the lower or upper part of the matrix. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a DiagonalProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline DiagonalProxy<MT>::DiagonalProxy( MT& matrix, size_t row, size_t column )
+ : value_ ( matrix( row, column ) ) // Reference to the accessed matrix element
+ , restricted_( row != column ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for DiagonalProxy.
+//
+// \param dp Diagonal proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline DiagonalProxy<MT>::DiagonalProxy( const DiagonalProxy& dp )
+ : value_ ( dp.value_ ) // Reference to the accessed matrix element
+ , restricted_( dp.restricted_ ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for DiagonalProxy.
+//
+// \param dp Diagonal proxy to be copied.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// In case the proxy represents a non-diagonal matrix element, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline DiagonalProxy<MT>& DiagonalProxy<MT>::operator=( const DiagonalProxy& dp )
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to non-diagonal matrix element" );
+ }
+
+ value_ = dp.value_;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// In case the proxy represents a non-diagonal matrix element, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline DiagonalProxy<MT>& DiagonalProxy<MT>::operator=( initializer_list<T> list )
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to non-diagonal matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// In case the proxy represents a non-diagonal matrix element, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline DiagonalProxy<MT>& DiagonalProxy<MT>::operator=( initializer_list< initializer_list<T> > list )
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to non-diagonal matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// In case the proxy represents a non-diagonal matrix element, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline DiagonalProxy<MT>& DiagonalProxy<MT>::operator=( const T& value )
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to non-diagonal matrix element" );
+ }
+
+ value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// In case the proxy represents a non-diagonal matrix element, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline DiagonalProxy<MT>& DiagonalProxy<MT>::operator+=( const T& value )
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to non-diagonal matrix element" );
+ }
+
+ value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// In case the proxy represents a non-diagonal matrix element, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline DiagonalProxy<MT>& DiagonalProxy<MT>::operator-=( const T& value )
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to non-diagonal matrix element" );
+ }
+
+ value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// In case the proxy represents a non-diagonal matrix element, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline DiagonalProxy<MT>& DiagonalProxy<MT>::operator*=( const T& value )
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to non-diagonal matrix element" );
+ }
+
+ value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// In case the proxy represents a non-diagonal matrix element, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline DiagonalProxy<MT>& DiagonalProxy<MT>::operator/=( const T& value )
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to non-diagonal matrix element" );
+ }
+
+ value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename DiagonalProxy<MT>::RawReference DiagonalProxy<MT>::get() const noexcept
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted matrix element..
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool DiagonalProxy<MT>::isRestricted() const noexcept
+{
+ return restricted_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Reference-to-const to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline DiagonalProxy<MT>::operator ConstReference() const noexcept
+{
+ return static_cast<ConstReference>( value_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DiagonalProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const DiagonalProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const DiagonalProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const DiagonalProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const DiagonalProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const DiagonalProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const DiagonalProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const DiagonalProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup diagonal_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the numeric proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const DiagonalProxy<MT>& proxy )
+{
+ using blaze::reset;
+
+ reset( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup diagonal_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the numeric proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const DiagonalProxy<MT>& proxy )
+{
+ using blaze::clear;
+
+ clear( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup diagonal_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const DiagonalProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup diagonal_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const DiagonalProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup diagonal_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const DiagonalProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup diagonal_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const DiagonalProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup diagonal_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const DiagonalProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/diagonalmatrix/Sparse.h b/src/cpu/blaze/math/adaptors/diagonalmatrix/Sparse.h
new file mode 100644
index 00000000..a6c977bb
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/diagonalmatrix/Sparse.h
@@ -0,0 +1,2022 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/diagonalmatrix/Sparse.h
+// \brief DiagonalMatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_SPARSE_H_
+#define _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <vector>
+#include <utility>
+#include <blaze/math/adaptors/diagonalmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/diagonalmatrix/DiagonalProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of DiagonalMatrix for sparse matrices.
+// \ingroup diagonal_matrix
+//
+// This specialization of DiagonalMatrix adapts the class template to the requirements of sparse
+// matrices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class DiagonalMatrix<MT,SO,false>
+ : public SparseMatrix< DiagonalMatrix<MT,SO,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DiagonalMatrix<MT,SO,false> This; //!< Type of this DiagonalMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this DiagonalMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef DiagonalMatrix<OT,!SO,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef DiagonalMatrix<TT,!SO,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef DiagonalProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a DiagonalMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other DiagonalMatrix.
+ typedef DiagonalMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline DiagonalMatrix();
+ explicit inline DiagonalMatrix( size_t n );
+ explicit inline DiagonalMatrix( size_t n, size_t nonzeros );
+ explicit inline DiagonalMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline DiagonalMatrix( const DiagonalMatrix& m );
+ inline DiagonalMatrix( DiagonalMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DiagonalMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline DiagonalMatrix& operator=( const DiagonalMatrix& rhs );
+ inline DiagonalMatrix& operator=( DiagonalMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, DiagonalMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, DiagonalMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, DiagonalMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, DiagonalMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, DiagonalMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, DiagonalMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DiagonalMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, DiagonalMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, DiagonalMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ template< typename Other > inline DiagonalMatrix& scale( const Other& scalar );
+ template< typename Other > inline DiagonalMatrix& scaleDiagonal( Other scale );
+ inline void swap( DiagonalMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void resetNonDiagonal();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend bool isDefault( const DiagonalMatrix<MT2,SO2,DF2>& m );
+
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( DiagonalMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for DiagonalMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline DiagonalMatrix<MT,SO,false>::DiagonalMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized to the zero matrix and has no free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline DiagonalMatrix<MT,SO,false>::DiagonalMatrix( size_t n )
+ : matrix_( n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized to the zero matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline DiagonalMatrix<MT,SO,false>::DiagonalMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+//
+// The matrix is initialized to the zero matrix and will have the specified capacity in each
+// row/column. Note that in case of a row-major matrix the given vector must have at least
+// \a m elements, in case of a column-major matrix at least \a n elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline DiagonalMatrix<MT,SO,false>::DiagonalMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for DiagonalMatrix.
+//
+// \param m The diagonal matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline DiagonalMatrix<MT,SO,false>::DiagonalMatrix( const DiagonalMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for DiagonalMatrix.
+//
+// \param m The diagonal matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline DiagonalMatrix<MT,SO,false>::DiagonalMatrix( DiagonalMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of diagonal matrix.
+//
+// This constructor initializes the diagonal matrix as a copy of the given matrix. In case the
+// given matrix is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline DiagonalMatrix<MT,SO,false>::DiagonalMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( ~m ) // The adapted sparse matrix
+{
+ if( !IsDiagonal<MT2>::value && !isDiagonal( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
+ }
+
+ if( !IsDiagonal<MT2>::value )
+ resetNonDiagonal();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Reference
+ DiagonalMatrix<MT,SO,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstReference
+ DiagonalMatrix<MT,SO,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Reference
+ DiagonalMatrix<MT,SO,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to non-diagonal matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstReference
+ DiagonalMatrix<MT,SO,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the diagonal matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::begin( size_t i )
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the diagonal matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstIterator
+ DiagonalMatrix<MT,SO,false>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the diagonal matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstIterator
+ DiagonalMatrix<MT,SO,false>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the diagonal matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::end( size_t i )
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the diagonal matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstIterator
+ DiagonalMatrix<MT,SO,false>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the diagonal matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstIterator
+ DiagonalMatrix<MT,SO,false>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for DiagonalMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline DiagonalMatrix<MT,SO,false>&
+ DiagonalMatrix<MT,SO,false>::operator=( const DiagonalMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for DiagonalMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline DiagonalMatrix<MT,SO,false>&
+ DiagonalMatrix<MT,SO,false>::operator=( DiagonalMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// diagonal matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,false>& >
+ DiagonalMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsDiagonal<MT2>::value && !isDiagonal( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ if( !IsDiagonal<MT2>::value )
+ resetNonDiagonal();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// diagonal matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,false>& >
+ DiagonalMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ if( IsDiagonal<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ if( !IsDiagonal<MT2>::value )
+ resetNonDiagonal();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a
+// diagonal matrix, i.e. the given matrix must be a diagonal matrix. In case the result
+// is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,false>& >
+ DiagonalMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsDiagonal<MT2>::value && !isDiagonal( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ if( !IsDiagonal<MT2>::value )
+ resetNonDiagonal();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a
+// diagonal matrix, i.e. the given matrix must be a diagonal matrix. In case the result
+// is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,false>& >
+ DiagonalMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ if( IsDiagonal<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ if( !IsDiagonal<MT2>::value )
+ resetNonDiagonal();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a
+// diagonal matrix, i.e. the given matrix must be a diagonal matrix. In case the result
+// is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,false>& >
+ DiagonalMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsDiagonal<MT2>::value && !isDiagonal( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ if( !IsDiagonal<MT2>::value )
+ resetNonDiagonal();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a
+// diagonal matrix, i.e. the given matrix must be a diagonal matrix. In case the result
+// is not a diagonal matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, DiagonalMatrix<MT,SO,false>& >
+ DiagonalMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ if( IsDiagonal<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ if( !IsDiagonal<MT2>::value )
+ resetNonDiagonal();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a diagonal matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DiagonalMatrix<MT,SO,false>&
+ DiagonalMatrix<MT,SO,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isDiagonal( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ if( !IsDiagonal<MT2>::value )
+ resetNonDiagonal();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, DiagonalMatrix<MT,SO,false> >&
+ DiagonalMatrix<MT,SO,false>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, DiagonalMatrix<MT,SO,false> >&
+ DiagonalMatrix<MT,SO,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t DiagonalMatrix<MT,SO,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t DiagonalMatrix<MT,SO,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t DiagonalMatrix<MT,SO,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the diagonal
+// matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t DiagonalMatrix<MT,SO,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the diagonal matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t DiagonalMatrix<MT,SO,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the diagonal matrix adapts a \a rowMajor sparse matrix the function returns the number
+// of non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse matrix the
+// function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t DiagonalMatrix<MT,SO,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::reset( size_t i )
+{
+ matrix_.reset( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the diagonal matrix.
+//
+// \return void
+//
+// This function clears the diagonal matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the diagonal matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to upper matrix element.
+//
+// This function sets the value of an element of the diagonal matrix. In case the diagonal matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted. The attempt to set an element in the
+// upper part of the matrix (i.e. above the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ if( i < j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to upper matrix element" );
+ }
+
+ return matrix_.set( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the diagonal matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+// \exception std::invalid_argument Invalid access to upper matrix element.
+//
+// This function inserts a new element into the diagonal matrix. However, duplicate elements
+// are not allowed. In case the diagonal matrix already contains an element with row index \a i
+// and column index \a j, a \a std::invalid_argument exception is thrown. Also, the attempt to
+// insert an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ if( i < j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to upper matrix element" );
+ }
+
+ return matrix_.insert( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the diagonal matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the diagonal matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::erase( size_t i, size_t j )
+{
+ matrix_.erase( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the diagonal matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the diagonal matrix. In case the diagonal matrix adapts
+// a \a rowMajor sparse matrix the function erases an element from row \a i, in case it adapts
+// a \a columnMajor sparse matrix the function erases an element from column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::erase( size_t i, Iterator pos )
+{
+ return matrix_.erase( i, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the diagonal matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of element from the diagonal matrix. In case the diagonal matrix
+// adapts a \a rowMajor sparse matrix the function erases a range of elements from row \a i, in
+// case it adapts a \a columnMajor matrix the function erases a range of elements from column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ return matrix_.erase( i, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the diagonal matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void DiagonalMatrix<MT,SO,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
+
+ matrix_.resize( n, n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the diagonal matrix.
+//
+// \param nonzeros The new minimum capacity of the diagonal matrix.
+// \return void
+//
+// This function increases the capacity of the diagonal matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the diagonal matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the diagonal matrix to at least
+// \a nonzeros elements. The current values of the diagonal matrix and all other individual
+// row/column capacities are preserved. In case the diagonal matrix adapts a \rowMajor sparse
+// matrix the function reserves capacity for row \a i. In case it adapts a \a columnMajor the
+// function reserves capacity for column \a i. The index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the diagonal matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline DiagonalMatrix<MT,SO,false>&
+ DiagonalMatrix<MT,SO,false>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the diagonal matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the diagonal matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline DiagonalMatrix<MT,SO,false>&
+ DiagonalMatrix<MT,SO,false>::scaleDiagonal( Other scalar )
+{
+ matrix_.scaleDiagonal( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::swap( DiagonalMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the complete upper part of the matrix to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void DiagonalMatrix<MT,SO,false>::resetNonDiagonal()
+{
+ for( size_t i=0UL; i<rows(); ++i ) {
+ matrix_.erase( i, matrix_.begin( i ), matrix_.lowerBound( i, i ) );
+ matrix_.erase( i, matrix_.upperBound( i, i ), matrix_.end( i ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the diagonal
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned diagonal matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::find( size_t i, size_t j )
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the diagonal
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned diagonal matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstIterator
+ DiagonalMatrix<MT,SO,false>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned diagonal matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::lowerBound( size_t i, size_t j )
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned diagonal matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstIterator
+ DiagonalMatrix<MT,SO,false>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned diagonal matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::Iterator
+ DiagonalMatrix<MT,SO,false>::upperBound( size_t i, size_t j )
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned diagonal matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename DiagonalMatrix<MT,SO,false>::ConstIterator
+ DiagonalMatrix<MT,SO,false>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the diagonal matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to upper matrix element.
+//
+// This function provides a very efficient way to fill a diagonal sparse matrix with elements.
+// It appends a new element to the end of the specified row/column without any additional memory
+// allocation. Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (newly created) sparse matrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DiagonalMatrix;
+ using blaze::rowMajor;
+
+ DiagonalMatrix< CompressedMatrix<double,rowMajor> > A( 4 );
+
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 0, 0, 1.0 ); // Appending the value 1 in row 0 with column index 0
+ A.finalize( 0 ); // Finalizing row 0
+ A.append( 1, 1, 2.0 ); // Appending the value 2 in row 1 with column index 1
+ A.finalize( 1 ); // Finalizing row 1
+ A.finalize( 2 ); // Finalizing the empty row 2 to prepare row 3
+ A.append( 3, 3, 3.0 ); // Appending the value 3 in row 3 with column index 3
+ A.finalize( 2 ); // Finalizing row 3
+ \endcode
+
+// Note that although append() does not allocate new memory it still invalidates all iterators
+// returned by the end() functions! Also note that the attempt to append an element within the
+// upper part of the matrix (i.e. above the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( i < j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to upper matrix element" );
+ }
+
+ matrix_.append( i, j, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void DiagonalMatrix<MT,SO,false>::finalize( size_t i )
+{
+ matrix_.finalize( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the diagonal matrix are intact.
+//
+// \return \a true in case the diagonal matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the diagonal matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool DiagonalMatrix<MT,SO,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isDiagonal( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool DiagonalMatrix<MT,SO,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool DiagonalMatrix<MT,SO,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool DiagonalMatrix<MT,SO,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/hermitianmatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/hermitianmatrix/BaseTemplate.h
new file mode 100644
index 00000000..a5fb8ca5
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/hermitianmatrix/BaseTemplate.h
@@ -0,0 +1,617 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/hermitianmatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the HeritianMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup hermitian_matrix HermitianMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for Hermitian \f$ N \times N \f$ matrices.
+// \ingroup hermitian_matrix
+//
+// \section hermitianmatrix_general General
+//
+// The HermitianMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \a MT and extends it
+// by enforcing the additional invariant of Hermitian symmetry (i.e. the matrix is always equal
+// to its conjugate transpose \f$ A = \overline{A^T} \f$). The type of the adapted matrix can
+// be specified via the first template parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF >
+ class HermitianMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. HermitianMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Also, the given matrix type must have numeric element types (i.e. all integral
+// types except \a bool, floating point and complex types). Note that the given matrix
+// type must be either resizable (as for instance HybridMatrix or DynamicMatrix) or must
+// be square at compile time (as for instance StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+// The following examples give an impression of several possible Hermitian matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense Hermitian matrix with static memory
+ blaze::HermitianMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense Hermitian matrix based on HybridMatrix
+ blaze::HermitianMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense Hermitian matrix based on DynamicMatrix
+ blaze::HermitianMatrix< blaze::DynamicMatrix<std::complex<double>,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense diagonal matrix based on CustomMatrix
+ blaze::HermitianMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision complex Hermitian matrix
+ blaze::HermitianMatrix< blaze::CompressedMatrix<std::complex<float>,rowMajor> > E;
+ \endcode
+
+// The storage order of a Hermitian matrix is depending on the storage order of the adapted matrix
+// type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified as
+// blaze::rowMajor), the Hermitian matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the Hermitian matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section hermitianmatrix_vs_symmetricmatrix Hermitian Matrices vs. Symmetric Matrices
+//
+// The blaze::HermitianMatrix adaptor and the blaze::SymmetricMatrix adaptor share several traits.
+// However, there are a couple of differences, both from a mathematical point of view as well as
+// from an implementation point of view.
+//
+// From a mathematical point of view, a matrix is called symmetric when it is equal to its
+// transpose (\f$ A = A^T \f$) and it is called Hermitian when it is equal to its conjugate
+// transpose (\f$ A = \overline{A^T} \f$). For matrices of real values, however, these two
+// conditions coincide, which means that symmetric matrices of real values are also Hermitian
+// and Hermitian matrices of real values are also symmetric.
+//
+// From an implementation point of view, \b Blaze restricts Hermitian matrices to numeric data
+// types (i.e. all integral types except \a bool, floating point and complex types), whereas
+// symmetric matrices can also be block structured (i.e. can have vector or matrix elements).
+// For built-in element types, the HermitianMatrix adaptor behaves exactly like the according
+// SymmetricMatrix implementation. For complex element types, however, the Hermitian property
+// is enforced (see also \ref hermitianmatrix_hermitian).
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::HermitianMatrix;
+ using blaze::SymmetricMatrix;
+
+ // The following two matrices provide an identical experience (including performance)
+ HermitianMatrix< DynamicMatrix<double> > A; // Both Hermitian and symmetric
+ SymmetricMatrix< DynamicMatrix<double> > B; // Both Hermitian and symmetric
+
+ // The following two matrices will behave differently
+ HermitianMatrix< DynamicMatrix< complex<double> > > C; // Only Hermitian
+ SymmetricMatrix< DynamicMatrix< complex<double> > > D; // Only symmetric
+
+ // Block-structured Hermitian matrices are not allowed
+ HermitianMatrix< DynamicMatrix< DynamicVector<double> > > E; // Compilation error!
+ SymmetricMatrix< DynamicMatrix< DynamicVector<double> > > F; // Block-structured symmetric matrix
+ \endcode
+
+// \n \section hermitianmatrix_special_properties Special Properties of Hermitian Matrices
+//
+// A Hermitian matrix is used exactly like a matrix of the underlying, adapted matrix type \a MT.
+// It also provides (nearly) the same interface as the underlying matrix type. However, there are
+// some important exceptions resulting from the Hermitian symmetry constraint:
+//
+// -# <b>\ref hermitianmatrix_square</b>
+// -# <b>\ref hermitianmatrix_hermitian</b>
+// -# <b>\ref hermitianmatrix_initialization</b>
+//
+// \n \subsection hermitianmatrix_square Hermitian Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 Hermitian dynamic matrix
+ HermitianMatrix< DynamicMatrix<std::complex<double>,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 Hermitian static matrix
+ HermitianMatrix< StaticMatrix<std::complex<float>,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ HermitianMatrix< StaticMatrix<std::complex<float>,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection hermitianmatrix_hermitian The Hermitian Property is Always Enforced!
+//
+// This means that the following properties of a Hermitian matrix are always guaranteed:
+//
+// - The diagonal elements are real numbers, i.e. the imaginary part is zero
+// - Element \f$ a_{ij} \f$ is always the complex conjugate of element \f$ a_{ji} \f$
+//
+// Thus modifying the element \f$ a_{ij} \f$ of a Hermitian matrix also modifies its
+// counterpart element \f$ a_{ji} \f$. Also, it is only possible to assign matrices that
+// are Hermitian themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+
+ typedef std::complex<double> cplx;
+
+ // Default constructed, row-major 3x3 Hermitian compressed matrix
+ HermitianMatrix< CompressedMatrix<cplx,rowMajor> > A( 3 );
+
+ // Initializing the matrix via the function call operator
+ //
+ // ( (1, 0) (0,0) (2,1) )
+ // ( (0, 0) (0,0) (0,0) )
+ // ( (2,-1) (0,0) (0,0) )
+ //
+ A(0,0) = cplx( 1.0, 0.0 ); // Initialization of the diagonal element (0,0)
+ A(0,2) = cplx( 2.0, 1.0 ); // Initialization of the elements (0,2) and (2,0)
+
+ // Inserting three more elements via the insert() function
+ //
+ // ( (1,-3) (0,0) (2, 1) )
+ // ( (0, 0) (2,0) (4,-2) )
+ // ( (2,-1) (4,2) (0, 0) )
+ //
+ A.insert( 1, 1, cplx( 2.0, 0.0 ) ); // Inserting the diagonal element (1,1)
+ A.insert( 1, 2, cplx( 4.0, -2.0 ) ); // Inserting the elements (1,2) and (2,1)
+
+ // Access via a non-const iterator
+ //
+ // ( (1,-3) (8,1) (2, 1) )
+ // ( (8,-1) (2,0) (4,-2) )
+ // ( (2,-1) (4,2) (0, 0) )
+ //
+ *A.begin(1UL) = cplx( 8.0, -1.0 ); // Modifies both elements (1,0) and (0,1)
+
+ // Erasing elements via the erase() function
+ //
+ // ( (0, 0) (8,1) (0, 0) )
+ // ( (8,-1) (2,0) (4,-2) )
+ // ( (0, 0) (4,2) (0, 0) )
+ //
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 0, 2 ); // Erasing the elements (0,2) and (2,0)
+
+ // Construction from a Hermitian dense matrix
+ StaticMatrix<cplx,3UL,3UL> B( { { cplx( 3.0, 0.0 ), cplx( 8.0, 2.0 ), cplx( -2.0, 2.0 ) },
+ { cplx( 8.0, 1.0 ), cplx( 0.0, 0.0 ), cplx( -1.0, -1.0 ) },
+ { cplx( -2.0, -2.0 ), cplx( -1.0, 1.0 ), cplx( 4.0, 0.0 ) } } );
+
+ HermitianMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-Hermitian dense matrix
+ StaticMatrix<cplx,3UL,3UL> D( { { cplx( 3.0, 0.0 ), cplx( 7.0, 2.0 ), cplx( 3.0, 2.0 ) },
+ { cplx( 8.0, 1.0 ), cplx( 0.0, 0.0 ), cplx( 6.0, 4.0 ) },
+ { cplx( -2.0, 2.0 ), cplx( -1.0, 1.0 ), cplx( 4.0, 0.0 ) } } );
+
+ C = D; // Throws an exception; Hermitian invariant would be violated!
+ \endcode
+
+// The same restriction also applies to the \c append() function for sparse matrices: Appending
+// the element \f$ a_{ij} \f$ additionally inserts the element \f$ a_{ji} \f$ into the matrix.
+// Despite the additional insertion, the \c append() function still provides the most efficient
+// way to set up a Hermitian sparse matrix. In order to achieve the maximum efficiency, the
+// capacity of the individual rows/columns of the matrix should to be specifically prepared with
+// \c reserve() calls:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+
+ typedef std::complex<double> cplx;
+
+ // Setup of the Hermitian matrix
+ //
+ // ( (0, 0) (1,2) (3,-4) )
+ // A = ( (1,-2) (2,0) (0, 0) )
+ // ( (3, 4) (0,0) (0, 0) )
+ //
+ HermitianMatrix< CompressedMatrix<cplx,rowMajor> > A( 3 );
+
+ A.reserve( 5 ); // Reserving enough space for 5 non-zero elements
+ A.reserve( 0, 2 ); // Reserving two non-zero elements in the first row
+ A.reserve( 1, 2 ); // Reserving two non-zero elements in the second row
+ A.reserve( 2, 1 ); // Reserving a single non-zero element in the third row
+
+ A.append( 0, 1, cplx( 1.0, 2.0 ) ); // Appending an element at position (0,1) and (1,0)
+ A.append( 1, 1, cplx( 2.0, 0.0 ) ); // Appending an element at position (1,1)
+ A.append( 2, 0, cplx( 3.0, 4.0 ) ); // Appending an element at position (2,0) and (0,2)
+ \endcode
+
+// The Hermitian property is also enforced for Hermitian custom matrices: In case the given array
+// of elements does not represent a Hermitian matrix, a \a std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef HermitianMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomHermitian;
+
+ // Creating a 3x3 Hermitian custom matrix from a properly initialized array
+ double array[9] = { 1.0, 2.0, 4.0,
+ 2.0, 3.0, 5.0,
+ 4.0, 5.0, 6.0 };
+ CustomHermitian A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 Hermitian custom matrix from an uninitialized array
+ CustomHermitian B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the Hermitian property is enforced for views (rows, columns, submatrices, ...) on the
+// Hermitian matrix. The following example demonstrates that modifying the elements of an entire
+// row of the Hermitian matrix also affects the counterpart elements in the according column of
+// the matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermtianMatrix;
+
+ typedef std::complex<double> cplx;
+
+ // Setup of the Hermitian matrix
+ //
+ // ( (0, 0) (1,-1) (0,0) (2, 1) )
+ // A = ( (1, 1) (3, 0) (4,2) (0, 0) )
+ // ( (0, 0) (4,-2) (0,0) (5,-3) )
+ // ( (2,-1) (0, 0) (5,3) (0, 0) )
+ //
+ HermitianMatrix< DynamicMatrix<int> > A( 4 );
+ A(0,1) = cplx( 1.0, -1.0 );
+ A(0,3) = cplx( 2.0, 1.0 );
+ A(1,1) = cplx( 3.0, 0.0 );
+ A(1,2) = cplx( 4.0, 2.0 );
+ A(2,3) = cplx( 5.0, 3.0 );
+
+ // Setting all elements in the 1st row to 0 results in the matrix
+ //
+ // ( (0, 0) (0,0) (0,0) (2, 1) )
+ // A = ( (0, 0) (0,0) (0,0) (0, 0) )
+ // ( (0, 0) (0,0) (0,0) (5,-3) )
+ // ( (2,-1) (0,0) (5,3) (0, 0) )
+ //
+ row( A, 1 ) = cplx( 0.0, 0.0 );
+ \endcode
+
+// The next example demonstrates the (compound) assignment to submatrices of Hermitian matrices.
+// Since the modification of element \f$ a_{ij} \f$ of a Hermitian matrix also modifies the
+// element \f$ a_{ji} \f$, the matrix to be assigned must be structured such that the Hermitian
+// symmetry of the matrix is preserved. Otherwise a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+
+ std::complex<double> cplx;
+
+ // Setup of two default 4x4 Hermitian matrices
+ HermitianMatrix< DynamicMatrix<cplx> > A1( 4 ), A2( 4 );
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( (1,-1) (2, 5) )
+ // B = ( (3, 0) (4,-6) )
+ // ( (5, 0) (6, 0) )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL );
+ B(0,0) = cplx( 1.0, -1.0 );
+ B(0,1) = cplx( 2.0, 5.0 );
+ B(1,0) = cplx( 3.0, 0.0 );
+ B(1,1) = cplx( 4.0, -6.0 );
+ B(2,1) = cplx( 5.0, 0.0 );
+ B(2,2) = cplx( 6.0, 7.0 );
+
+ // OK: Assigning B to a submatrix of A1 such that the Hermitian property is preserved
+ //
+ // ( (0, 0) (0, 0) (1,-1) (2, 5) )
+ // A1 = ( (0, 0) (0, 0) (3, 0) (4,-6) )
+ // ( (1, 1) (3, 0) (5, 0) (6, 0) )
+ // ( (2,-5) (4, 6) (6, 0) (0, 0) )
+ //
+ submatrix( A1, 0UL, 2UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the Hermitian property isn't preserved!
+ // The elements marked with X cannot be assigned unambiguously!
+ //
+ // ( (0, 0) (1,-1) (2,5) (0,0) )
+ // A2 = ( (1, 1) (3, 0) (X,X) (0,0) )
+ // ( (2,-5) (X, X) (6,0) (0,0) )
+ // ( (0, 0) (0, 0) (0,0) (0,0) )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection hermitianmatrix_initialization The Elements of a Dense Hermitian Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency (especially in case all default values are
+// overridden afterwards), this property is important since otherwise the Hermitian property of
+// dense Hermitian matrices could not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // Default initialized, 5x5 row-major Hermitian dynamic matrix
+ HermitianMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \section hermitianmatrix_arithmetic_operations Arithmetic Operations
+//
+// A HermitianMatrix can be used within all numerical operations in any way any other dense or
+// sparse matrix can be used. It can also be combined with any other dense or sparse vector or
+// matrix. The following code example gives an impression of the use of HermitianMatrix within
+// arithmetic operations:
+
+ \code
+ using blaze::HermitianMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef complex<float> cplx;
+
+ DynamicMatrix<cplx,rowMajor> A( 3, 3 );
+ CompressedMatrix<cplx,rowMajor> B( 3, 3 );
+
+ HermitianMatrix< DynamicMatrix<cplx,rowMajor> > C( 3 );
+ HermitianMatrix< CompressedMatrix<cplx,rowMajor> > D( 3 );
+
+ HermitianMatrix< HybridMatrix<cplx,3UL,3UL,rowMajor> > E;
+ HermitianMatrix< StaticMatrix<cplx,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major Hermitian matrix
+ F = C - D; // Matrix subtraction and assignment to a column-major Hermitian matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section hermitianmatrix_performance Performance Considerations
+//
+// When the Hermitian property of a matrix is known beforehands using the HermitianMatrix adaptor
+// instead of a general matrix can be a considerable performance advantage. This is particularly
+// true in case the Hermitian matrix is also symmetric (i.e. has built-in element types). The
+// \b Blaze library tries to exploit the properties of Hermitian (symmetric) matrices whenever
+// possible. However, there are also situations when using a Hermitian matrix introduces some
+// overhead. The following examples demonstrate several situations where Hermitian matrices can
+// positively or negatively impact performance.
+//
+// \n \subsection hermitianmatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is symmetric, \b Blaze can exploit the fact
+// that \f$ A = A^T \f$ and choose the fastest and most suited combination of storage orders for the
+// multiplication. The following example demonstrates this by means of a dense matrix/sparse matrix
+// multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ HermitianMatrix< DynamicMatrix<double,rowMajor> > A; // Both Hermitian and symmetric
+ HermitianMatrix< CompressedMatrix<double,columnMajor> > B; // Both Hermitian and symmetric
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// Intuitively, the chosen combination of a row-major and a column-major matrix is the most suited
+// for maximum performance. However, \b Blaze evaluates the multiplication as
+
+ \code
+ C = A * trans( B );
+ \endcode
+
+// which significantly increases the performance since in contrast to the original formulation the
+// optimized form can be vectorized. Therefore, in the context of matrix multiplications, using a
+// symmetric matrix is obviously an advantage.
+//
+// \n \subsection hermitianmatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar optimization is possible in case of matrix/vector multiplications:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ HermitianMatrix< DynamicMatrix<double,rowMajor> > A; // Hermitian and symmetric
+ CompressedVector<double,columnVector> x;
+ DynamicVector<double,columnVector> y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example it is not intuitively apparent that using a row-major matrix is not the best
+// possible choice in terms of performance since the computation cannot be vectorized. Choosing
+// a column-major matrix instead, however, would enable a vectorized computation. Therefore
+// \b Blaze exploits the fact that \c A is symmetric, selects the best suited storage order and
+// evaluates the multiplication as
+
+ \code
+ y = trans( A ) * x;
+ \endcode
+
+// which also significantly increases the performance.
+//
+// \n \subsection hermitianmatrix_views Positive Impact: Row/Column Views on Column/Row-Major Matrices
+//
+// Another example is the optimization of a row view on a column-major symmetric matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef HermitianMatrix< DynamicMatrix<double,columnMajor> > DynamicHermitian;
+
+ DynamicHermitian A( 10UL ); // Both Hermitian and symmetric
+ Row<DynamicHermitian> row5 = row( A, 5UL );
+ \endcode
+
+// Usually, a row view on a column-major matrix results in a considerable performance decrease in
+// comparison to a row view on a row-major matrix due to the non-contiguous storage of the matrix
+// elements. However, in case of symmetric matrices, \b Blaze instead uses the according column of
+// the matrix, which provides the same performance as if the matrix would be row-major. Note that
+// this also works for column views on row-major matrices, where \b Blaze can use the according
+// row instead of a column in order to provide maximum performance.
+//
+// \n \subsection hermitianmatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a Hermitian matrix on the right-hand side of an assignment (i.e. for read
+// access), which introduces absolutely no performance penalty, using a Hermitian matrix on the
+// left-hand side of an assignment (i.e. for write access) may introduce additional overhead when
+// it is assigned a general matrix, which is not Hermitian at compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::HermitianMatrix;
+
+ HermitianMatrix< DynamicMatrix< complex<double> > > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the Hermitian matrix; no performance penalty
+ C = A; // Assignment of a Hermitian matrix to another Hermitian matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a Hermitian matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not Hermitian matrix to a Hermitian matrix it is necessary
+// to check whether the matrix is Hermitian at runtime in order to guarantee the Hermitian property
+// of the Hermitian matrix. In case it turns out to be Hermitian, it is assigned as efficiently as
+// possible, if it is not, an exception is thrown. In order to prevent this runtime overhead it is
+// therefore generally advisable to assign Hermitian matrices to other Hermitian matrices.\n
+// In this context it is especially noteworthy that in contrast to additions and subtractions the
+// multiplication of two Hermitian matrices does not necessarily result in another Hermitian matrix:
+
+ \code
+ HermitianMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a Hermitian matrix; no runtime overhead
+ C = A - B; // Results in a Hermitian matrix; no runtime overhead
+ C = A * B; // Is not guaranteed to result in a Hermitian matrix; some runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class HermitianMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/hermitianmatrix/Dense.h b/src/cpu/blaze/math/adaptors/hermitianmatrix/Dense.h
new file mode 100644
index 00000000..e86b8096
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/hermitianmatrix/Dense.h
@@ -0,0 +1,3018 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/hermitianmatrix/Dense.h
+// \brief HermitianMatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_DENSE_H_
+#define _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/hermitianmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/hermitianmatrix/HermitianProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Column.h>
+#include <blaze/math/views/Row.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of HermitianMatrix for dense matrices.
+// \ingroup hermitian_matrix
+//
+// This specialization of HermitianMatrix adapts the class template to the requirements of dense
+// matrices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class HermitianMatrix<MT,SO,true>
+ : public DenseMatrix< HermitianMatrix<MT,SO,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef HermitianMatrix<MT,SO,true> This; //!< Type of this HermitianMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this HermitianMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef HermitianMatrix<OT,!SO,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef HermitianMatrix<TT,!SO,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef HermitianProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a HermitianMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other HermitianMatrix.
+ typedef HermitianMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense hermitian matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef HermitianProxy<MT> PointerType; //!< Pointer return type.
+ typedef HermitianProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row index of the iterator
+ , column_( column ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) noexcept {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Store function***************************************************************************
+ /*!\brief Store of a SIMD element at the current iterator position.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs a store of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void store( const SIMDType& value ) const {
+ (*matrix_).store( row_, column_, value );
+ sync();
+ }
+ //*******************************************************************************************
+
+ //**Storea function**************************************************************************
+ /*!\brief Aligned store of a SIMD element at the current iterator position.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned store of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void storea( const SIMDType& value ) const {
+ (*matrix_).storea( row_, column_, value );
+ sync();
+ }
+ //*******************************************************************************************
+
+ //**Storeu function**************************************************************************
+ /*!\brief Unaligned store of a SIMD element at the current iterator position.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an unaligned store of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void storeu( const SIMDType& value ) const {
+ (*matrix_).storeu( row_, column_, value );
+ sync();
+ }
+ //*******************************************************************************************
+
+ //**Stream function**************************************************************************
+ /*!\brief Aligned, non-temporal store of a SIMD element at the current iterator position.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned, non-temporal store of the current SIMD element at the
+ // current iterator position. This function must \b NOT be called explicitly! It is used
+ // internally for the performance optimized evaluation of expression templates. Calling
+ // this function explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void stream( const SIMDType& value ) const {
+ (*matrix_).stream( row_, column_, value );
+ sync();
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Sync function****************************************************************************
+ /*!\brief Synchronizes several paired elements after a SIMD assignment.
+ //
+ // \return void
+ */
+ void sync() const {
+ if( SO ) {
+ const size_t kend( min( row_+SIMDSIZE, (*matrix_).rows() ) );
+ for( size_t k=row_; k<kend; ++k )
+ (*matrix_)(column_,k) = conj( (*matrix_)(k,column_) );
+ }
+ else {
+ const size_t kend( min( column_+SIMDSIZE, (*matrix_).columns() ) );
+ for( size_t k=column_; k<kend; ++k )
+ (*matrix_)(k,row_) = conj( (*matrix_)(row_,k) );
+ }
+ }
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row index of the iterator.
+ size_t column_; //!< The current column index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline HermitianMatrix();
+ explicit inline HermitianMatrix( size_t n );
+ explicit inline HermitianMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline HermitianMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline HermitianMatrix( const Other (&array)[N][N] );
+
+ explicit inline HermitianMatrix( ElementType* ptr, size_t n );
+ explicit inline HermitianMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline HermitianMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline HermitianMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline HermitianMatrix( const HermitianMatrix& m );
+ inline HermitianMatrix( HermitianMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline HermitianMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline HermitianMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline HermitianMatrix& operator=( const Other (&array)[N][N] );
+
+ inline HermitianMatrix& operator=( const HermitianMatrix& rhs );
+ inline HermitianMatrix& operator=( HermitianMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, HermitianMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, HermitianMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix& >
+ operator=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, HermitianMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, HermitianMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix& >
+ operator+=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, HermitianMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, HermitianMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix& >
+ operator-=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline HermitianMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, HermitianMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, HermitianMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ inline HermitianMatrix& transpose();
+ inline HermitianMatrix& ctranspose();
+ template< typename Other > inline HermitianMatrix& scale( const Other& scalar );
+ inline void swap( HermitianMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ inline void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ inline void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ inline void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ inline void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ template< typename MT2, bool SO2, typename T >
+ inline const MT2& construct( const Matrix<MT2,SO2>& m, T );
+
+ template< typename MT2 >
+ inline TransExprTrait_<MT2> construct( const Matrix<MT2,!SO>& m, TrueType );
+ //@}
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ET>::size };
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend bool isDefault( const HermitianMatrix<MT2,SO2,DF2>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert2x2( HermitianMatrix<MT2,SO2,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert3x3( HermitianMatrix<MT2,SO2,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert4x4( HermitianMatrix<MT2,SO2,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert5x5( HermitianMatrix<MT2,SO2,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert6x6( HermitianMatrix<MT2,SO2,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invertByLU( HermitianMatrix<MT2,SO2,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invertByLDLT( HermitianMatrix<MT2,SO2,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invertByLDLH( HermitianMatrix<MT2,SO2,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invertByLLH( HermitianMatrix<MT2,SO2,true>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for HermitianMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( size_t n )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of Hermitian matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the Hermitian
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef complex<int> cplx;
+ typedef blaze::HermitianMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > MT;
+
+ MT A{ { cplx(1, 0), cplx(2, 2), cplx(4,-4) },
+ { cplx(2,-2), cplx(3, 0), cplx(5, 5) },
+ { cplx(4, 4), cplx(5,-5), cplx(4, 0) } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all Hermitian matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of Hermitian matrix.
+//
+// This constructor offers the option to directly initialize the elements of the Hermitian matrix
+// with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef complex<int> cplx;
+
+ cplx* array = new cplx[16];
+ // ... Initialization of the dynamic array
+ blaze::HermitianMatrix< blaze::DynamicMatrix<cplx,rowMajor> > v( 4UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized accoring to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a n by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also, in
+// case the given array does not represent a Hermitian matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all Hermitian matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of Hermitian matrix.
+//
+// This constructor offers the option to directly initialize the elements of the Hermitian matrix
+// with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef complex<int> cplx;
+
+ const cplx init[3][3] = { { cplx(1, 0), cplx(2, 2), cplx(4,-4) },
+ { cplx(2,-2), cplx(3, 0), cplx(5, 5) },
+ { cplx(4, 4), cplx(5,-5), cplx(4, 0) } };
+ blaze::HermitianMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a Hermitian matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a Hermitian custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of Hermitian custom matrix.
+//
+// This constructor creates an unpadded Hermitian custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a Hermitian matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded Hermitian custom matrices!
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a Hermitian custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of Hermitian custom matrix.
+//
+// This constructor creates a Hermitian custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a Hermitian matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a Hermitian custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of Hermitian custom matrix.
+//
+// This constructor creates an unpadded Hermitian custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a Hermitian matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded Hermitian custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a Hermitian custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of Hermitian custom matrix.
+//
+// This constructor creates a Hermitian custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a Hermitian matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for HermitianMatrix.
+//
+// \param m The Hermitian matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( const HermitianMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for HermitianMatrix.
+//
+// \param m The Hermitian matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( HermitianMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of Hermitian matrix.
+//
+// This constructor initializes the Hermitian matrix as a copy of the given matrix. In case the
+// given matrix is not a Hermitian matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline HermitianMatrix<MT,SO,true>::HermitianMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( construct( m, typename IsBuiltin< ElementType_<MT2> >::Type() ) ) // The adapted dense matrix
+{
+ if( !IsHermitian<MT2>::value && !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::Reference
+ HermitianMatrix<MT,SO,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::ConstReference
+ HermitianMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::Reference
+ HermitianMatrix<MT,SO,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::ConstReference
+ HermitianMatrix<MT,SO,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the Hermitian matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The Hermitian matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function. Also note that you can NOT assume that the Hermitian matrix stores all its
+// elements. It may choose to store its elements in a lower or upper triangular matrix fashion.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::ConstPointer
+ HermitianMatrix<MT,SO,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+// Note that you can NOT assume that the Hermitian matrix stores all its elements. It may choose
+// to store its elements in a lower or upper triangular matrix fashion.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::ConstPointer
+ HermitianMatrix<MT,SO,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the Hermitian matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::Iterator
+ HermitianMatrix<MT,SO,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the Hermitian matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::ConstIterator
+ HermitianMatrix<MT,SO,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the Hermitian matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::ConstIterator
+ HermitianMatrix<MT,SO,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the Hermitian matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::Iterator
+ HermitianMatrix<MT,SO,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the Hermitian matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::ConstIterator
+ HermitianMatrix<MT,SO,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the Hermitian matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename HermitianMatrix<MT,SO,true>::ConstIterator
+ HermitianMatrix<MT,SO,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the Hermitian
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef complex<int> cplx;
+
+ blaze::HermitianMatrix< blaze::StaticMatrix<cplx,3UL,3UL,rowMajor> > A;
+ A = { { cplx(1, 0), cplx(2, 2), cplx(4,-4) },
+ { cplx(2,-2), cplx(3, 0), cplx(5, 5) },
+ { cplx(4, 4), cplx(5,-5), cplx(4, 0) } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>&
+ HermitianMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all Hermitian matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// This assignment operator offers the option to directly set all elements of the Hermitian matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef complex<int> cplx;
+
+ const cplx init[3][3] = { { cplx(1, 0), cplx(2, 2), cplx(4,-4) },
+ { cplx(2,-2), cplx(3, 0), cplx(5, 5) },
+ { cplx(4, 4), cplx(5,-5), cplx(4, 0) } };
+ blaze::HermitianMatrix< blaze::StaticMatrix<cplx,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a Hermitian matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline HermitianMatrix<MT,SO,true>&
+ HermitianMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for HermitianMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>&
+ HermitianMatrix<MT,SO,true>::operator=( const HermitianMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for HermitianMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>&
+ HermitianMatrix<MT,SO,true>::operator=( HermitianMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// Hermitian matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsHermitian<MT2>::value && !isHermitian( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// Hermitian matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ if( IsHermitian<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrices with opposite storage order.
+//
+// \param rhs The right-hand side matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// Hermitian matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a Hermitian matrix, i.e.
+// the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsHermitian<MT2>::value && !isHermitian( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a Hermitian matrix, i.e.
+// the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ if( IsHermitian<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix with opposite storage order
+// (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a Hermitian matrix, i.e.
+// the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator+=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator+=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a Hermitian matrix,
+// i.e. the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsHermitian<MT2>::value && !isHermitian( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a Hermitian matrix,
+// i.e. the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ if( IsHermitian<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix with opposite storage
+// order (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a Hermitian matrix,
+// i.e. the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix<MT,SO,true>& >
+ HermitianMatrix<MT,SO,true>::operator-=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator-=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a Hermitian matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline HermitianMatrix<MT,SO,true>&
+ HermitianMatrix<MT,SO,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, HermitianMatrix<MT,SO,true> >&
+ HermitianMatrix<MT,SO,true>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, HermitianMatrix<MT,SO,true> >&
+ HermitianMatrix<MT,SO,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t HermitianMatrix<MT,SO,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t HermitianMatrix<MT,SO,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e.
+// the total number of elements of a row/column. In case the Hermitian matrix adapts a
+// \a rowMajor dense matrix the function returns the spacing between two rows, in case
+// it adapts a \a columnMajor dense matrix the function returns the spacing between two
+// columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t HermitianMatrix<MT,SO,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t HermitianMatrix<MT,SO,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the Hermitian
+// matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor dense matrix the function returns the capacity of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t HermitianMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the Hermitian matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t HermitianMatrix<MT,SO,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column. In
+// case the Hermitian matrix adapts a \a rowMajor dense matrix the function returns the number of
+// non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix the function
+// returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t HermitianMatrix<MT,SO,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void HermitianMatrix<MT,SO,true>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row \b and column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row \b and column to their default value.
+// The following example demonstrates this by means of a \f$ 5 \times 5 \f$ Hermitian matrix:
+
+ \code
+ blaze::HermitianMatrix< blaze::DynamicMatrix< blaze::complex<double> > > A;
+
+ // Initializing the Hermitian matrix A to
+ //
+ // ( ( 0, 0) ( 2, 1) ( 5, 0) (-4,-2) ( 0,-1) )
+ // ( ( 2,-1) ( 1, 0) (-3, 1) ( 7, 2) ( 0,-3) )
+ // A = ( ( 5, 0) (-3,-1) ( 8, 0) (-1, 0) (-2,-1) )
+ // ( (-4, 2) ( 7,-2) (-1, 0) ( 0, 0) (-6, 2) )
+ // ( ( 0, 1) ( 0, 3) (-2, 1) (-6,-2) ( 1, 0) )
+ // ...
+
+ // Resetting the 1st row/column results in the matrix
+ //
+ // ( ( 0, 0) ( 0, 0) ( 5, 0) (-4,-2) ( 0,-1) )
+ // ( ( 0, 0) ( 0, 0) ( 0, 0) ( 0, 0) ( 0, 0) )
+ // A = ( ( 5, 0) ( 0, 0) ( 8, 0) (-1, 0) (-2,-1) )
+ // ( (-4, 2) ( 0, 0) (-1, 0) ( 0, 0) (-6, 2) )
+ // ( ( 0, 1) ( 0, 0) (-2, 1) (-6,-2) ( 1, 0) )
+ //
+ A.reset( 1UL );
+ \endcode
+
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void HermitianMatrix<MT,SO,true>::reset( size_t i )
+{
+ row ( matrix_, i ).reset();
+ column( matrix_, i ).reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the Hermitian matrix.
+//
+// \return void
+//
+// This function clears the Hermitian matrix and returns it to its default state. The function has
+// the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
+// matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
+// to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
+// be reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void HermitianMatrix<MT,SO,true>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the Hermitian matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the Hermitian matrix adapts a resizable matrix, this function resizes the matrix using
+// the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
+// in case the capacity of the matrix is too small. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, the resize operation potentially changes all matrix elements. In order
+// to preserve the old matrix values, the \a preserve flag can be set to \a true. In case the
+// size of the matrix is increased, new elements are default initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 2 & 4 & 5 \\
+ 3 & 5 & 6 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & 0 \\
+ 2 & 4 & 5 & 0 \\
+ 3 & 5 & 6 & 0 \\
+ 0 & 0 & 0 & 0 \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void HermitianMatrix<MT,SO,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize ) {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, 0UL, oldsize, oldsize, increment ).reset();
+ submatrix( matrix_, oldsize, 0UL, increment, n ).reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void HermitianMatrix<MT,SO,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the Hermitian matrix.
+// \return void
+//
+// This function increases the capacity of the Hermitian matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void HermitianMatrix<MT,SO,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the Hermitian matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>& HermitianMatrix<MT,SO,true>::transpose()
+{
+ if( IsComplex<ElementType>::value )
+ matrix_.transpose();
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the Hermitian matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline HermitianMatrix<MT,SO,true>& HermitianMatrix<MT,SO,true>::ctranspose()
+{
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the scalar value
+inline HermitianMatrix<MT,SO,true>&
+ HermitianMatrix<MT,SO,true>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void HermitianMatrix<MT,SO,true>::swap( HermitianMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the Hermitian matrix are intact.
+//
+// \return \a true in case the Hermitian matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the Hermitian matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool HermitianMatrix<MT,SO,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isHermitian( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool HermitianMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool HermitianMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool HermitianMatrix<MT,SO,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool HermitianMatrix<MT,SO,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the Hermitian matrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than the
+// number of columns. Additionally, the column index (in case of a row-major matrix) or the row
+// index (in case of a column-major matrix) must be a multiple of the number or values inside
+// the SIMD element. This function must \b NOT be called explicitly! It is used internally
+// for the performance optimized evaluation of expression templates. Calling this function
+// explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename HermitianMatrix<MT,SO,true>::SIMDType
+ HermitianMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the Hermitian matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename HermitianMatrix<MT,SO,true>::SIMDType
+ HermitianMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the Hermitian matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename HermitianMatrix<MT,SO,true>::SIMDType
+ HermitianMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void
+ HermitianMatrix<MT,SO,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ matrix_.store( i, j, value );
+
+ if( SO ) {
+ const size_t kend( min( i+SIMDSIZE, rows() ) );
+ for( size_t k=i; k<kend; ++k )
+ matrix_(j,k) = conj( matrix_(k,j) );
+ }
+ else {
+ const size_t kend( min( j+SIMDSIZE, columns() ) );
+ for( size_t k=j; k<kend; ++k )
+ matrix_(k,i) = conj( matrix_(i,k) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void
+ HermitianMatrix<MT,SO,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ matrix_.storea( i, j, value );
+
+ if( SO ) {
+ const size_t kend( min( i+SIMDSIZE, rows() ) );
+ for( size_t k=i; k<kend; ++k )
+ matrix_(j,k) = conj( matrix_(k,j) );
+ }
+ else {
+ const size_t kend( min( j+SIMDSIZE, columns() ) );
+ for( size_t k=j; k<kend; ++k )
+ matrix_(k,i) = conj( matrix_(i,k) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void
+ HermitianMatrix<MT,SO,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ matrix_.storeu( i, j, value );
+
+ if( SO ) {
+ const size_t kend( min( i+SIMDSIZE, rows() ) );
+ for( size_t k=i; k<kend; ++k )
+ matrix_(j,k) = conj( matrix_(k,j) );
+ }
+ else {
+ const size_t kend( min( j+SIMDSIZE, columns() ) );
+ for( size_t k=j; k<kend; ++k )
+ matrix_(k,i) = conj( matrix_(i,k) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the dense
+// matrix. The row index must be smaller than the number of rows and the column index must be
+// smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void
+ HermitianMatrix<MT,SO,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ matrix_.stream( i, j, value );
+
+ if( SO ) {
+ const size_t kend( min( i+SIMDSIZE, rows() ) );
+ for( size_t k=i; k<kend; ++k )
+ matrix_(j,k) = conj( matrix_(k,j) );
+ }
+ else {
+ const size_t kend( min( j+SIMDSIZE, columns() ) );
+ for( size_t k=j; k<kend; ++k )
+ matrix_(k,i) = conj( matrix_(i,k) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT2& HermitianMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ return ~m;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the foreign matrix
+inline TransExprTrait_<MT2>
+ HermitianMatrix<MT,SO,true>::construct( const Matrix<MT2,!SO>& m, TrueType )
+{
+ return trans( ~m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianElement.h b/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianElement.h
new file mode 100644
index 00000000..b1e141ca
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianElement.h
@@ -0,0 +1,434 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/hermitianmatrix/HermitianElement.h
+// \brief Header file for the HermitianElement class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_HERMITIANELEMENT_H_
+#define _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_HERMITIANELEMENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/hermitianmatrix/HermitianValue.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Representation of two synchronized elements within the sparse Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// The HermitianElement class represents two synchronized elements (i.e. two value/index pairs)
+// within a sparse Hermitian matrix. It guarantees that a modification of element \f$ a_{ij} \f$
+// via iterator is also applied to element \f$ a_{ji} \f$. The following example illustrates this
+// by means of a \f$ 3 \times 3 \f$ dense Hermitian matrix:
+
+ \code
+ typedef std::complex<double> cplx;
+ typedef blaze::HermitianMatrix< blaze::CompressedMatrix<cplx> > Hermitian;
+
+ // Creating a 3x3 Hermitian dense matrix
+ //
+ // ( ( 0, 0) (0, 0) (-2,1) )
+ // ( ( 0, 0) (3, 0) ( 5,2) )
+ // ( (-2,-1) (5,-2) ( 0,0) )
+ //
+ Hermitian A( 3UL );
+ A(0,2) = cplx(-2,1);
+ A(1,1) = cplx( 3,0);
+ A(1,2) = cplx( 5,2);
+
+ // Modification of the elements at position (2,0) and (0,2)
+ //
+ // ( (0,0) (0, 0) (4,-3) )
+ // ( (0,0) (3, 0) (5, 2) )
+ // ( (4,3) (5,-2) (0, 0) )
+ //
+ Hermitian::Iterator it = A.begin( 2UL );
+ *it = cplx(4,3);
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class HermitianElement : private SparseElement
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> ElementType; //!< Type of the represented matrix element.
+ typedef Iterator_<MT> IteratorType; //!< Type of the underlying sparse matrix iterators.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef HermitianValue<MT> ValueType; //!< The value type of the value-index-pair.
+ typedef size_t IndexType; //!< The index type of the value-index-pair.
+ typedef HermitianValue<MT> Reference; //!< Reference return type.
+ typedef const HermitianValue<MT> ConstReference; //!< Reference-to-const return type.
+ typedef HermitianElement* Pointer; //!< Pointer return type.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline HermitianElement( IteratorType pos, MT* matrix, size_t idx );
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ template< typename T > inline HermitianElement& operator= ( const T& v );
+ template< typename T > inline HermitianElement& operator+=( const T& v );
+ template< typename T > inline HermitianElement& operator-=( const T& v );
+ template< typename T > inline HermitianElement& operator*=( const T& v );
+ template< typename T > inline HermitianElement& operator/=( const T& v );
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline Pointer operator->() noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline Reference value() const;
+ inline IndexType index() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void sync();
+ inline bool isSynced() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse Hermitian matrix element.
+ MT* matrix_; //!< The sparse matrix containing the iterator.
+ size_t index_; //!< The row/column index of the iterator.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( ElementType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the HermitianElement class.
+//
+// \param pos The initial position of the iterator.
+// \param matrix The sparse matrix containing the iterator.
+// \param idx The row/column index of the iterator.
+*/
+template< typename MT > // Type of the adapted matrix
+inline HermitianElement<MT>::HermitianElement( IteratorType pos, MT* matrix, size_t idx )
+ : pos_ ( pos ) // Iterator to the current sparse Hermitian matrix element
+ , matrix_( matrix ) // The sparse matrix containing the iterator
+ , index_ ( idx ) // The row/column index of the iterator
+{
+ BLAZE_INTERNAL_ASSERT( isSynced(), "Missing matrix element detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Assignment to the Hermitian element.
+//
+// \param v The new value of the Hermitian element.
+// \return Reference to the assigned Hermitian element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianElement<MT>& HermitianElement<MT>::operator=( const T& v )
+{
+ if( IsComplex<ElementType>::value && pos_->index() == index_ && !isReal( v ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ = v;
+ sync();
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the Hermitian element.
+//
+// \param v The right-hand side value for the addition.
+// \return Reference to the assigned Hermitian element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianElement<MT>& HermitianElement<MT>::operator+=( const T& v )
+{
+ if( IsComplex<ElementType>::value && pos_->index() == index_ && !isReal( v ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ += v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the Hermitian element.
+//
+// \param v The right-hand side value for the subtraction.
+// \return Reference to the assigned Hermitian element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianElement<MT>& HermitianElement<MT>::operator-=( const T& v )
+{
+ if( IsComplex<ElementType>::value && pos_->index() == index_ && !isReal( v ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ -= v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the Hermitian element.
+//
+// \param v The right-hand side value for the multiplication.
+// \return Reference to the assigned Hermitian element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianElement<MT>& HermitianElement<MT>::operator*=( const T& v )
+{
+ if( IsComplex<ElementType>::value && pos_->index() == index_ && !isReal( v ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ *= v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the Hermitian element.
+//
+// \param v The right-hand side value for the division.
+// \return Reference to the assigned Hermitian element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianElement<MT>& HermitianElement<MT>::operator/=( const T& v )
+{
+ if( IsComplex<ElementType>::value && pos_->index() == index_ && !isReal( v ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ /= v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the Hermitian element.
+//
+// \return Reference to the value of the Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianElement<MT>::Pointer HermitianElement<MT>::operator->() noexcept
+{
+ return this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access to the current value of the Hermitian element.
+//
+// \return The current value of the Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianElement<MT>::Reference HermitianElement<MT>::value() const
+{
+ return Reference( pos_, matrix_, index_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the current index of the Hermitian element.
+//
+// \return The current index of the Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianElement<MT>::IndexType HermitianElement<MT>::index() const
+{
+ return pos_->index();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Synchronization of the current sparse element to the according paired element.
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianElement<MT>::sync()
+{
+ if( pos_->index() == index_ || isDefault( pos_->value() ) )
+ return;
+
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+
+ matrix_->set( row, column, conj( pos_->value() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checking if the current sparse element is in sync.
+//
+// \return \a true if the current sparse element is in sync, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool HermitianElement<MT>::isSynced() const
+{
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+
+ const IteratorType pos2( matrix_->find( row, column ) );
+ const IteratorType end( matrix_->end( pos_->index() ) );
+
+ return ( isDefault( pos_->value() ) && ( pos2 == end || isDefault( pos2->value() ) ) ) ||
+ ( pos2 != end && pos_->value() == conj( pos2->value() ) );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianProxy.h b/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianProxy.h
new file mode 100644
index 00000000..f325639f
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianProxy.h
@@ -0,0 +1,851 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/hermitianmatrix/HermitianProxy.h
+// \brief Header file for the HermitianProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_HERMITIANPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_HERMITIANPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for Hermitian matrices.
+// \ingroup hermitian_matrix
+//
+// The HermitianProxy provides controlled access to the elements of a non-const Hermitian matrix.
+// It guarantees that a modification of element \f$ a_{ij} \f$ of the accessed matrix is also
+// applied to element \f$ a_{ji} \f$. The following example illustrates this by means of a
+// \f$ 3 \times 3 \f$ dense Hermitian matrix:
+
+ \code
+ // Creating a 3x3 Hermitian dense matrix
+ blaze::HermitianMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(0,2) = -2; // ( 0 0 -2 )
+ A(1,1) = 3; // => A = ( 0 3 5 )
+ A(1,2) = 5; // ( -2 5 0 )
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class HermitianProxy : public Proxy< HermitianProxy<MT> >
+{
+ private:
+ //**struct BuiltinType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct BuiltinType { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct ComplexType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct ComplexType { typedef typename T::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+ typedef Reference_<MT> Reference; //!< Reference to the represented element.
+ typedef ConstReference_<MT> ConstReference; //!< Reference-to-const to the represented element.
+ typedef HermitianProxy* Pointer; //!< Pointer to the represented element.
+ typedef const HermitianProxy* ConstPointer; //!< Pointer-to-const to the represented element.
+
+ //! Value type of the represented complex element.
+ typedef typename If_< IsComplex<RepresentedType>
+ , ComplexType<RepresentedType>
+ , BuiltinType<RepresentedType> >::Type ValueType;
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline HermitianProxy( MT& matrix, size_t row, size_t column );
+ inline HermitianProxy( const HermitianProxy& hp );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline HermitianProxy& operator= ( const HermitianProxy& hp );
+ template< typename T > inline HermitianProxy& operator= ( const T& value );
+ template< typename T > inline HermitianProxy& operator+=( const T& value );
+ template< typename T > inline HermitianProxy& operator-=( const T& value );
+ template< typename T > inline HermitianProxy& operator*=( const T& value );
+ template< typename T > inline HermitianProxy& operator/=( const T& value );
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline Pointer operator->() noexcept;
+ inline ConstPointer operator->() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void reset () const;
+ inline void clear () const;
+ inline void invert() const;
+
+ inline ConstReference get() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator ConstReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Complex data access functions***************************************************************
+ /*!\name Complex data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Reference value1_; //!< Reference to the first accessed matrix element.
+ Reference value2_; //!< Reference to the second accessed matrix element.
+ const bool diagonal_; //!< Flag for the accessed matrix element.
+ /*!< The flag indicates if the accessed element is a diagonal element.
+ It is \a true in case the proxy represents an element on the
+ diagonal. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a HermitianProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline HermitianProxy<MT>::HermitianProxy( MT& matrix, size_t row, size_t column )
+ : value1_ ( matrix(row,column) ) // Reference to the first accessed matrix element
+ , value2_ ( matrix(column,row) ) // Reference to the second accessed matrix element
+ , diagonal_( row == column ) // Flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for HermitianProxy.
+//
+// \param hp Numeric proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline HermitianProxy<MT>::HermitianProxy( const HermitianProxy& hp )
+ : value1_ ( hp.value1_ ) // Reference to the first accessed matrix element
+ , value2_ ( hp.value2_ ) // Reference to the second accessed matrix element
+ , diagonal_( hp.diagonal_ ) // Flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for HermitianProxy.
+//
+// \param hp Numeric proxy to be copied.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// In case the proxy represents a diagonal element and the assigned value does not represent
+// a real number, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline HermitianProxy<MT>& HermitianProxy<MT>::operator=( const HermitianProxy& hp )
+{
+ typedef ElementType_<MT> ET;
+
+ if( IsComplex<ET>::value && diagonal_ && !isReal( hp.value1_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ value1_ = hp.value1_;
+ if( !diagonal_ )
+ value2_ = conj( value1_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// In case the proxy represents a diagonal element and the assigned value does not represent
+// a real number, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianProxy<MT>& HermitianProxy<MT>::operator=( const T& value )
+{
+ typedef ElementType_<MT> ET;
+
+ if( IsComplex<ET>::value && diagonal_ && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ value1_ = value;
+ if( !diagonal_ )
+ value2_ = conj( value1_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// In case the proxy represents a diagonal element and the assigned value does not represent
+// a real number, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianProxy<MT>& HermitianProxy<MT>::operator+=( const T& value )
+{
+ typedef ElementType_<MT> ET;
+
+ if( IsComplex<ET>::value && diagonal_ && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ value1_ += value;
+ if( !diagonal_ )
+ value2_ = conj( value1_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// In case the proxy represents a diagonal element and the assigned value does not represent
+// a real number, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianProxy<MT>& HermitianProxy<MT>::operator-=( const T& value )
+{
+ typedef ElementType_<MT> ET;
+
+ if( IsComplex<ET>::value && diagonal_ && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ value1_ -= value;
+ if( !diagonal_ )
+ value2_ = conj( value1_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// In case the proxy represents a diagonal element and the assigned value does not represent
+// a real number, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianProxy<MT>& HermitianProxy<MT>::operator*=( const T& value )
+{
+ typedef ElementType_<MT> ET;
+
+ if( IsComplex<ET>::value && diagonal_ && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ value1_ *= value;
+ if( !diagonal_ )
+ value2_ = conj( value1_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// In case the proxy represents a diagonal element and the assigned value does not represent
+// a real number, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianProxy<MT>& HermitianProxy<MT>::operator/=( const T& value )
+{
+ typedef ElementType_<MT> ET;
+
+ if( IsComplex<ET>::value && diagonal_ && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ value1_ /= value;
+ if( !diagonal_ )
+ value2_ = conj( value1_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the represented matrix element.
+//
+// \return Pointer to the represented matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianProxy<MT>::Pointer HermitianProxy<MT>::operator->() noexcept
+{
+ return this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the represented matrix element.
+//
+// \return Pointer to the represented matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianProxy<MT>::ConstPointer HermitianProxy<MT>::operator->() const noexcept
+{
+ return this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reset the represented element to its default initial value.
+//
+// \return void
+//
+// This function resets the element represented by the proxy to its default initial value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianProxy<MT>::reset() const
+{
+ using blaze::reset;
+
+ reset( value1_ );
+ if( !diagonal_ )
+ reset( value2_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+//
+// \return void
+//
+// This function clears the element represented by the proxy to its default initial state.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianProxy<MT>::clear() const
+{
+ using blaze::clear;
+
+ clear( value1_ );
+ if( !diagonal_ )
+ clear( value2_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianProxy<MT>::invert() const
+{
+ using blaze::invert;
+
+ invert( value1_ );
+ if( !diagonal_ )
+ value2_ = conj( value1_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianProxy<MT>::ConstReference HermitianProxy<MT>::get() const noexcept
+{
+ return value1_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline HermitianProxy<MT>::operator ConstReference() const noexcept
+{
+ return get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianProxy<MT>::ValueType HermitianProxy<MT>::real() const
+{
+ return value1_.real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+//
+// In case the proxy represents a complex number, this function sets a new value to its real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianProxy<MT>::real( ValueType value ) const
+{
+ value1_.real( value );
+ if( !diagonal_ )
+ value2_.real( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianProxy<MT>::ValueType HermitianProxy<MT>::imag() const
+{
+ return value1_.imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its imaginary
+// part. In case the proxy represents a diagonal element and the given value is not zero, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianProxy<MT>::imag( ValueType value ) const
+{
+ if( diagonal_ && !isZero( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal matrix element" );
+ }
+
+ value1_.imag( value );
+ if( !diagonal_ )
+ value2_.imag( -value );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name HermitianProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const HermitianProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const HermitianProxy<MT>& proxy );
+
+template< typename MT >
+inline void invert( const HermitianProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const HermitianProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const HermitianProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const HermitianProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const HermitianProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const HermitianProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup hermitian_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const HermitianProxy<MT>& proxy )
+{
+ proxy.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup hermitian_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const HermitianProxy<MT>& proxy )
+{
+ proxy.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element.
+// \ingroup hermitian_matrix
+//
+// \param proxy The given proxy instance.
+// \return void
+*/
+template< typename MT >
+inline void invert( const HermitianProxy<MT>& proxy )
+{
+ proxy.invert();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup hermitian_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const HermitianProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup hermitian_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const HermitianProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup hermitian_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const HermitianProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup hermitian_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const HermitianProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup hermitian_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const HermitianProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianValue.h b/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianValue.h
new file mode 100644
index 00000000..6eca2938
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianValue.h
@@ -0,0 +1,811 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/hermitianmatrix/HermitianValue.h
+// \brief Header file for the HermitianValue class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_HERMITIANVALUE_H_
+#define _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_HERMITIANVALUE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Representation of two synchronized values within a sparse Hermitian matrix.
+// \ingroup hermitian_matrix
+//
+// The HermitianValue class represents two synchronized values within a sparse Hermitian matrix.
+// It guarantees that a modification of value \f$ a_{ij} \f$ via iterator is also applied to the
+// value \f$ a_{ji} \f$. The following example illustrates this by means of a \f$ 3 \times 3 \f$
+// sparse Hermitian matrix:
+
+ \code
+ typedef std::complex<double> cplx;
+ typedef blaze::HermitianMatrix< blaze::CompressedMatrix<cplx> > Hermitian;
+
+ // Creating a 3x3 Hermitian dense matrix
+ //
+ // ( ( 0, 0) (0, 0) (-2,1) )
+ // ( ( 0, 0) (3, 0) ( 5,2) )
+ // ( (-2,-1) (5,-2) ( 0,0) )
+ //
+ Hermitian A( 3UL );
+ A(0,2) = cplx(-2,1);
+ A(1,1) = cplx( 3,0);
+ A(1,2) = cplx( 5,2);
+
+ // Modification of the values at position (2,0) and (0,2)
+ //
+ // ( (0,0) (0, 0) (4,-3) )
+ // ( (0,0) (3, 0) (5, 2) )
+ // ( (4,3) (5,-2) (0, 0) )
+ //
+ Hermitian::Iterator it = A.begin( 2UL );
+ it->value() = cplx(4,3);
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class HermitianValue : public Proxy< HermitianValue<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef typename MT::Iterator IteratorType; //!< Type of the underlying sparse matrix iterators.
+ //**********************************************************************************************
+
+ //**struct BuiltinType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct BuiltinType { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct ComplexType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct ComplexType { typedef typename T::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+
+ //! Value type of the represented complex element.
+ typedef typename If_< IsComplex<RepresentedType>
+ , ComplexType<RepresentedType>
+ , BuiltinType<RepresentedType> >::Type ValueType;
+
+ typedef ValueType value_type; //!< Value type of the represented complex element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline HermitianValue( IteratorType pos, MT* matrix, size_t index );
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline HermitianValue& operator= ( const HermitianValue& hv );
+ template< typename T > inline HermitianValue& operator= ( const T& value );
+ template< typename T > inline HermitianValue& operator+=( const T& value );
+ template< typename T > inline HermitianValue& operator-=( const T& value );
+ template< typename T > inline HermitianValue& operator*=( const T& value );
+ template< typename T > inline HermitianValue& operator/=( const T& value );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void reset () const;
+ inline void clear () const;
+ inline void invert() const;
+
+ inline RepresentedType get() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RepresentedType() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Complex data access functions***************************************************************
+ /*!\name Complex data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void sync() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse Hermitian matrix element.
+ MT* matrix_; //!< The sparse matrix containing the iterator.
+ size_t index_; //!< The row/column index of the iterator.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the HermitianValue class.
+//
+// \param pos The initial position of the iterator.
+// \param matrix The sparse matrix containing the iterator.
+// \param index The row/column index of the iterator.
+*/
+template< typename MT > // Type of the adapted matrix
+inline HermitianValue<MT>::HermitianValue( IteratorType pos, MT* matrix, size_t index )
+ : pos_ ( pos ) // Iterator to the current sparse Hermitian matrix element
+ , matrix_( matrix ) // The sparse matrix containing the iterator
+ , index_ ( index ) // The row/column index of the iterator
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for HermitianValue.
+//
+// \param hv The Hermitian value to be copied.
+// \return Reference to the assigned Hermitian value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline HermitianValue<MT>& HermitianValue<MT>::operator=( const HermitianValue& hv )
+{
+ const bool isDiagonal( pos_->index() == index_ );
+
+ if( IsComplex<RepresentedType>::value && isDiagonal && !isReal( hv.pos_->value() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ pos_->value() = hv.pos_->value();
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the Hermitian value.
+//
+// \param value The new value of the Hermitian value.
+// \return Reference to the assigned Hermitian value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianValue<MT>& HermitianValue<MT>::operator=( const T& value )
+{
+ const bool isDiagonal( pos_->index() == index_ );
+
+ if( IsComplex<RepresentedType>::value && isDiagonal && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ pos_->value() = value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the Hermitian value.
+//
+// \param value The right-hand side value to be added to the Hermitian value.
+// \return Reference to the assigned Hermitian value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianValue<MT>& HermitianValue<MT>::operator+=( const T& value )
+{
+ const bool isDiagonal( pos_->index() == index_ );
+
+ if( IsComplex<RepresentedType>::value && isDiagonal && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ pos_->value() += value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the Hermitian value.
+//
+// \param value The right-hand side value to be subtracted from the Hermitian value.
+// \return Reference to the assigned Hermitian value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianValue<MT>& HermitianValue<MT>::operator-=( const T& value )
+{
+ const bool isDiagonal( pos_->index() == index_ );
+
+ if( IsComplex<RepresentedType>::value && isDiagonal && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ pos_->value() -= value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the Hermitian value.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned Hermitian value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianValue<MT>& HermitianValue<MT>::operator*=( const T& value )
+{
+ const bool isDiagonal( pos_->index() == index_ );
+
+ if( IsComplex<RepresentedType>::value && isDiagonal && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ pos_->value() *= value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the Hermitian value.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned Hermitian value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline HermitianValue<MT>& HermitianValue<MT>::operator/=( const T& value )
+{
+ const bool isDiagonal( pos_->index() == index_ );
+
+ if( IsComplex<RepresentedType>::value && isDiagonal && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ pos_->value() /= value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reset the Hermitian value to its default initial value.
+//
+// \return void
+//
+// This function resets the Hermitian value to its default initial value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianValue<MT>::reset() const
+{
+ using blaze::reset;
+
+ reset( pos_->value() );
+
+ if( pos_->index() != index_ )
+ {
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+ const IteratorType pos2( matrix_->find( row, column ) );
+
+ reset( pos2->value() );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the Hermitian value.
+//
+// \return void
+//
+// This function clears the Hermitian value to its default initial state.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianValue<MT>::clear() const
+{
+ using blaze::clear;
+
+ clear( pos_->value() );
+
+ if( pos_->index() != index_ )
+ {
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+ const IteratorType pos2( matrix_->find( row, column ) );
+
+ clear( pos2->value() );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the Hermitian value
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianValue<MT>::invert() const
+{
+ using blaze::invert;
+
+ invert( pos_->value() );
+
+ if( pos_->index() != index_ )
+ {
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+ const IteratorType pos2( matrix_->find( row, column ) );
+
+ pos2->value() = conj( pos_->value() );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the represented value.
+//
+// \return Copy of the represented value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianValue<MT>::RepresentedType HermitianValue<MT>::get() const noexcept
+{
+ return pos_->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Synchronization of the current sparse element to the according paired element.
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianValue<MT>::sync() const
+{
+ if( pos_->index() == index_ || isDefault( pos_->value() ) )
+ return;
+
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+
+ matrix_->set( row, column, conj( pos_->value() ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the represented value.
+//
+// \return Copy of the represented value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline HermitianValue<MT>::operator RepresentedType() const noexcept
+{
+ return pos_->value();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// In case the value represents a complex number, this function returns the current value
+// of its real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianValue<MT>::ValueType HermitianValue<MT>::real() const
+{
+ return pos_->value().real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+//
+// In case the value represents a complex number, this function sets a new value to its
+// real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianValue<MT>::real( ValueType value ) const
+{
+ pos_->value().real() = value;
+ sync();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// In case the value represents a complex number, this function returns the current value of its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename HermitianValue<MT>::ValueType HermitianValue<MT>::imag() const
+{
+ return pos_->value.imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+//
+// In case the proxy represents a complex number, this function sets a new value to its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void HermitianValue<MT>::imag( ValueType value ) const
+{
+ pos_->value().imag( value );
+ sync();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name HermitianValue global functions */
+//@{
+template< typename MT >
+inline void reset( const HermitianValue<MT>& value );
+
+template< typename MT >
+inline void clear( const HermitianValue<MT>& value );
+
+template< typename MT >
+inline void invert( const HermitianValue<MT>& value );
+
+template< typename MT >
+inline bool isDefault( const HermitianValue<MT>& value );
+
+template< typename MT >
+inline bool isReal( const HermitianValue<MT>& value );
+
+template< typename MT >
+inline bool isZero( const HermitianValue<MT>& value );
+
+template< typename MT >
+inline bool isOne( const HermitianValue<MT>& value );
+
+template< typename MT >
+inline bool isnan( const HermitianValue<MT>& value );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the Hermitian value to the default initial values.
+// \ingroup hermitian_matrix
+//
+// \param value The given Hermitian value.
+// \return void
+//
+// This function resets the Hermitian value to its default initial value.
+*/
+template< typename MT >
+inline void reset( const HermitianValue<MT>& value )
+{
+ value.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the Hermitian value.
+// \ingroup hermitian_matrix
+//
+// \param value The given Hermitian value.
+// \return void
+//
+// This function clears the Hermitian value to its default initial state.
+*/
+template< typename MT >
+inline void clear( const HermitianValue<MT>& value )
+{
+ value.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the Hermitian value.
+// \ingroup hermitian_matrix
+//
+// \param value The given Hermitian value.
+// \return void
+*/
+template< typename MT >
+inline void invert( const HermitianValue<MT>& value )
+{
+ value.invert();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the Hermitian value is in default state.
+// \ingroup hermitian_matrix
+//
+// \param value The given Hermitian value.
+// \return \a true in case the Hermitian value is in default state, \a false otherwise.
+//
+// This function checks whether the Hermitian value is in default state. In case it is in
+// default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const HermitianValue<MT>& value )
+{
+ using blaze::isDefault;
+
+ return isDefault( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the Hermitian value represents a real number.
+// \ingroup hermitian_matrix
+//
+// \param value The given Hermitian value.
+// \return \a true in case the Hermitian value represents a real number, \a false otherwise.
+//
+// This function checks whether the Hermitian value represents the a real number. In case the
+// value is of built-in type, the function returns \a true. In case the element is of complex
+// type, the function returns \a true if the imaginary part is equal to 0. Otherwise it returns
+// \a false.
+*/
+template< typename MT >
+inline bool isReal( const HermitianValue<MT>& value )
+{
+ using blaze::isReal;
+
+ return isReal( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the Hermitian value is 0.
+// \ingroup hermitian_matrix
+//
+// \param value The given Hermitian value.
+// \return \a true in case the Hermitian value is 0, \a false otherwise.
+//
+// This function checks whether the Hermitian value represents the numeric value 0. In case it
+// is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const HermitianValue<MT>& value )
+{
+ using blaze::isZero;
+
+ return isZero( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the Hermitian value is 1.
+// \ingroup hermitian_matrix
+//
+// \param value The given Hermitian value.
+// \return \a true in case the Hermitian value is 1, \a false otherwise.
+//
+// This function checks whether the Hermitian value represents the numeric value 1. In case it
+// is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const HermitianValue<MT>& value )
+{
+ using blaze::isOne;
+
+ return isOne( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the Hermitian value is not a number.
+// \ingroup hermitian_matrix
+//
+// \param value The given Hermitian value.
+// \return \a true in case the Hermitian value is in not a number, \a false otherwise.
+//
+// This function checks whether the Hermitian value is not a number (NaN). In case it is not a
+// number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const HermitianValue<MT>& value )
+{
+ using blaze::isnan;
+
+ return isnan( value.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/hermitianmatrix/Sparse.h b/src/cpu/blaze/math/adaptors/hermitianmatrix/Sparse.h
new file mode 100644
index 00000000..ac2bcf75
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/hermitianmatrix/Sparse.h
@@ -0,0 +1,2404 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/hermitianmatrix/Sparse.h
+// \brief HermitianMatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_SPARSE_H_
+#define _BLAZE_MATH_ADAPTORS_HERMITIANMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/hermitianmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/hermitianmatrix/HermitianElement.h>
+#include <blaze/math/adaptors/hermitianmatrix/HermitianProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of HermitianMatrix for sparse matrices.
+// \ingroup hermitian_matrix
+//
+// This specialization of HermitianMatrix adapts the class template to the requirements of sparse
+// matrices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class HermitianMatrix<MT,SO,false>
+ : public SparseMatrix< HermitianMatrix<MT,SO,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef HermitianMatrix<MT,SO,false> This; //!< Type of this HermitianMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this HermitianMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef HermitianMatrix<OT,!SO,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef HermitianMatrix<TT,!SO,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef HermitianProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a HermitianMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other HermitianMatrix.
+ typedef HermitianMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the elements of the sparse Hermitian matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef Iterator_<MT> IteratorType; //!< Type of the underlying sparse matrix iterators.
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef HermitianElement<MT> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Default constructor**********************************************************************
+ /*!\brief Default constructor for the Iterator class.
+ */
+ inline Iterator()
+ : pos_ () // Iterator to the current sparse Hermitian matrix element
+ , matrix_( nullptr ) // The sparse matrix containing the iterator
+ , index_ ( 0UL ) // The row/column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param pos The initial position of the iterator.
+ // \param matrix The sparse matrix containing the iterator.
+ // \param index The row/column index of the iterator.
+ */
+ inline Iterator( IteratorType pos, MT& matrix, size_t index )
+ : pos_ ( pos ) // Iterator to the current sparse Hermitian matrix element
+ , matrix_( &matrix ) // The sparse matrix containing the iterator
+ , index_ ( index ) // The row/column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() {
+ ++pos_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Reference to the current sparse matrix element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, matrix_, index_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Pointer to the current sparse matrix element.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, matrix_, index_ );
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const Iterator& rhs ) const {
+ return pos_ == rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const Iterator& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two matrix iterators.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return The number of elements between the two matrix iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const {
+ return pos_ - rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the matrix iterator.
+ //
+ // \return The current position of the matrix iterator.
+ */
+ inline IteratorType base() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse Hermitian matrix element.
+ MT* matrix_; //!< The sparse matrix containing the iterator.
+ size_t index_; //!< The row/column index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline HermitianMatrix();
+ explicit inline HermitianMatrix( size_t n );
+ explicit inline HermitianMatrix( size_t n, size_t nonzeros );
+ explicit inline HermitianMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline HermitianMatrix( const HermitianMatrix& m );
+ inline HermitianMatrix( HermitianMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline HermitianMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline HermitianMatrix& operator=( const HermitianMatrix& rhs );
+ inline HermitianMatrix& operator=( HermitianMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, HermitianMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, HermitianMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix& >
+ operator=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, HermitianMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, HermitianMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix& >
+ operator+=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, HermitianMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, HermitianMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix& >
+ operator-=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline HermitianMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, HermitianMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, HermitianMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ inline HermitianMatrix& transpose();
+ inline HermitianMatrix& ctranspose();
+ template< typename Other > inline HermitianMatrix& scale( const Other& scalar );
+ template< typename Other > inline HermitianMatrix& scaleDiagonal( Other scale );
+ inline void swap( HermitianMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ template< typename MT2, bool SO2, typename T >
+ inline const MT2& construct( const Matrix<MT2,SO2>& m, T );
+
+ template< typename MT2 >
+ inline TransExprTrait_<MT2> construct( const Matrix<MT2,!SO>& m, TrueType );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend bool isDefault( const HermitianMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for HermitianMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>::HermitianMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized to the zero matrix and has no free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>::HermitianMatrix( size_t n )
+ : matrix_( n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized to the zero matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>::HermitianMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+//
+// The matrix is initialized to the zero matrix and will have the specified capacity in each
+// row/column. Note that in case of a row-major matrix the given vector must have at least
+// \a m elements, in case of a column-major matrix at least \a n elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>::HermitianMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for HermitianMatrix.
+//
+// \param m The Hermitian matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>::HermitianMatrix( const HermitianMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for HermitianMatrix.
+//
+// \param m The Hermitian matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>::HermitianMatrix( HermitianMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of Hermitian matrix.
+//
+// This constructor initializes the Hermitian matrix as a copy of the given matrix. In case the
+// given matrix is not a Hermitian matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline HermitianMatrix<MT,SO,false>::HermitianMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( construct( m, typename IsBuiltin< ElementType_<MT2> >::Type() ) ) // The adapted sparse matrix
+{
+ if( !IsHermitian<MT2>::value && !isHermitian( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of Hermitian matrix" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// The function call operator provides access to both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$.
+// In order to preserve the Hermitian symmetry of the matrix, any modification to one of the
+// elements will also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Reference
+ HermitianMatrix<MT,SO,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// The function call operator provides access to both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$.
+// In order to preserve the Hermitian symmetry of the matrix, any modification to one of the
+// elements will also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstReference
+ HermitianMatrix<MT,SO,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Reference
+ HermitianMatrix<MT,SO,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstReference
+ HermitianMatrix<MT,SO,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the Hermitian matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::begin( size_t i )
+{
+ return Iterator( matrix_.begin(i), matrix_, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the Hermitian matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstIterator
+ HermitianMatrix<MT,SO,false>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the Hermitian matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstIterator
+ HermitianMatrix<MT,SO,false>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the Hermitian matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::end( size_t i )
+{
+ return Iterator( matrix_.end(i), matrix_, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the Hermitian matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstIterator
+ HermitianMatrix<MT,SO,false>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the Hermitian matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstIterator
+ HermitianMatrix<MT,SO,false>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for HermitianMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>&
+ HermitianMatrix<MT,SO,false>::operator=( const HermitianMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for HermitianMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>&
+ HermitianMatrix<MT,SO,false>::operator=( HermitianMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// Hermitian matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsHermitian<MT2>::value && !isHermitian( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// Hermitian matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ if( IsHermitian<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrices with opposite storage order.
+//
+// \param rhs The right-hand side matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// Hermitian matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a Hermitian matrix, i.e.
+// the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsHermitian<MT2>::value && !isHermitian( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a Hermitian matrix, i.e.
+// the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ if( IsHermitian<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix with opposite storage order
+// (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a Hermitian matrix, i.e.
+// the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator+=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator+=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a Hermitian matrix,
+// i.e. the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsHermitian<MT2>::value && !isHermitian( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a Hermitian matrix,
+// i.e. the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ if( IsHermitian<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix with opposite storage
+// order (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to Hermitian matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a Hermitian matrix,
+// i.e. the given matrix must be a Hermitian matrix. In case the result is not a Hermitian matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsBuiltin< ElementType_<MT2> >, HermitianMatrix<MT,SO,false>& >
+ HermitianMatrix<MT,SO,false>::operator-=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator-=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a Hermitian matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline HermitianMatrix<MT,SO,false>&
+ HermitianMatrix<MT,SO,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isHermitian( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, HermitianMatrix<MT,SO,false> >&
+ HermitianMatrix<MT,SO,false>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, HermitianMatrix<MT,SO,false> >&
+ HermitianMatrix<MT,SO,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t HermitianMatrix<MT,SO,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t HermitianMatrix<MT,SO,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t HermitianMatrix<MT,SO,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the Hermitian
+// matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function returns the capacity of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t HermitianMatrix<MT,SO,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the Hermitian matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t HermitianMatrix<MT,SO,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column. In
+// case the Hermitian matrix adapts a \a rowMajor sparse matrix the function returns the number of
+// non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse matrix the function
+// returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t HermitianMatrix<MT,SO,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row \b and column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row \b and column to their default value.
+// The following example demonstrates this by means of a \f$ 5 \times 5 \f$ Hermitian matrix:
+
+ \code
+ blaze::HermitianMatrix< blaze::CompressedMatrix<int> > A;
+
+ // Initializing the Hermitian matrix A to
+ //
+ // ( ( 0, 0) ( 2, 1) ( 5, 0) (-4,-2) ( 0,-1) )
+ // ( ( 2,-1) ( 1, 0) (-3, 1) ( 7, 2) ( 0,-3) )
+ // A = ( ( 5, 0) (-3,-1) ( 8, 0) (-1, 0) (-2,-1) )
+ // ( (-4, 2) ( 7,-2) (-1, 0) ( 0, 0) (-6, 2) )
+ // ( ( 0, 1) ( 0, 3) (-2, 1) (-6,-2) ( 1, 0) )
+ // ...
+
+ // Resetting the 1st row/column results in the matrix
+ //
+ // ( ( 0, 0) ( 0, 0) ( 5, 0) (-4,-2) ( 0,-1) )
+ // ( ( 0, 0) ( 0, 0) ( 0, 0) ( 0, 0) ( 0, 0) )
+ // A = ( ( 5, 0) ( 0, 0) ( 8, 0) (-1, 0) (-2,-1) )
+ // ( (-4, 2) ( 0, 0) (-1, 0) ( 0, 0) (-6, 2) )
+ // ( ( 0, 1) ( 0, 0) (-2, 1) (-6,-2) ( 1, 0) )
+ //
+ A.reset( 1UL );
+ \endcode
+
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::reset( size_t i )
+{
+ for( Iterator_<MT> it=matrix_.begin(i); it!=matrix_.end(i); ++it )
+ {
+ const size_t j( it->index() );
+
+ if( i == j )
+ continue;
+
+ if( SO ) {
+ const Iterator_<MT> pos( matrix_.find( i, j ) );
+ BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, pos );
+ }
+ else {
+ const Iterator_<MT> pos( matrix_.find( j, i ) );
+ BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, pos );
+ }
+ }
+
+ matrix_.reset( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the Hermitian matrix.
+//
+// \return void
+//
+// This function clears the Hermitian matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the Hermitian matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function sets the value of both the elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ of the
+// Hermitian matrix and returns an iterator to the successfully set element \f$ a_{ij} \f$. In
+// case the Hermitian matrix already contains the two elements with index \a i and \a j their
+// values are modified, else two new elements with the given \a value are inserted.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ const bool isDiagonal( i == j );
+
+ if( IsComplex<ElementType>::value && isDiagonal && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+
+ if( !isDiagonal )
+ matrix_.set( j, i, conj( value ) );
+ return Iterator( matrix_.set( i, j, value ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the Hermitian matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function inserts both the elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ into the Hermitian
+// matrix and returns an iterator to the successfully inserted element \f$ a_{ij} \f$. However,
+// duplicate elements are not allowed. In case the Hermitian matrix an element with row index
+// \a i and column index \a j, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ const bool isDiagonal( i == j );
+
+ if( IsComplex<ElementType>::value && isDiagonal && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+
+ if( !isDiagonal )
+ matrix_.insert( j, i, conj( value ) );
+ return Iterator( matrix_.insert( i, j, value ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the Hermitian matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ from the Hermitian matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::erase( size_t i, size_t j )
+{
+ matrix_.erase( i, j );
+ if( i != j )
+ matrix_.erase( j, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the Hermitian matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases both the specified element and its according Hermitian counterpart from
+// the Hermitian matrix. In case the storage order is set to \a rowMajor the given index \a i
+// refers to a row, in case the storage flag is set to \a columnMajor \a i refers to a column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::erase( size_t i, Iterator pos )
+{
+ const Iterator_<MT> base( pos.base() );
+
+ if( base == matrix_.end( i ) )
+ return pos;
+
+ const size_t j( base->index() );
+
+ if( i == j ) {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( i, i ) != matrix_.end( i ), "Missing element detected" );
+ return Iterator( matrix_.erase( i, base ), matrix_, i );
+ }
+
+ if( SO ) {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( i, j ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, matrix_.find( i, j ) );
+ return Iterator( matrix_.erase( i, base ), matrix_, i );
+ }
+ else {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( j, i ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, matrix_.find( j, i ) );
+ return Iterator( matrix_.erase( i, base ), matrix_, i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the Hermitian matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases both the range of elements specified by the iterator pair \a first and
+// \a last and their according Hermitian counterparts from the Hermitian matrix. In case the
+// storage order is set to \a rowMajor the given index \a i refers to a row, in case the storage
+// flag is set to \a columnMajor \a i refers to a column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ for( Iterator_<MT> it=first.base(); it!=last.base(); ++it )
+ {
+ const size_t j( it->index() );
+
+ if( i == j )
+ continue;
+
+ if( SO ) {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( i, j ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( i, j );
+ }
+ else {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( j, i ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, i );
+ }
+ }
+
+ return Iterator( matrix_.erase( i, first.base(), last.base() ), matrix_, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the Hermitian matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void HermitianMatrix<MT,SO,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square Hermitian matrix detected" );
+
+ matrix_.resize( n, n, true );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the Hermitian matrix.
+//
+// \param nonzeros The new minimum capacity of the Hermitian matrix.
+// \return void
+//
+// This function increases the capacity of the Hermitian matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the Hermitian matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the Hermitian matrix to at least
+// \a nonzeros elements. The current values of the Hermitian matrix and all other individual
+// row/column capacities are preserved. In case the storage order is set to \a rowMajor, the
+// function reserves capacity for row \a i. In case the storage order is set to \a columnMajor,
+// the function reserves capacity for column \a i. The index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the Hermitian matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the Hermitian matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>& HermitianMatrix<MT,SO,false>::transpose()
+{
+ if( IsComplex<ElementType>::value )
+ matrix_.transpose();
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the Hermitian matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline HermitianMatrix<MT,SO,false>& HermitianMatrix<MT,SO,false>::ctranspose()
+{
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline HermitianMatrix<MT,SO,false>&
+ HermitianMatrix<MT,SO,false>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the Hermitian matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the Hermitian matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline HermitianMatrix<MT,SO,false>&
+ HermitianMatrix<MT,SO,false>::scaleDiagonal( Other scalar )
+{
+ matrix_.scaleDiagonal( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::swap( HermitianMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the Hermitian
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned Hermitian matrix iterator is subject
+// to invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::find( size_t i, size_t j )
+{
+ return Iterator( matrix_.find( i, j ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the Hermitian
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned Hermitian matrix iterator is subject
+// to invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstIterator
+ HermitianMatrix<MT,SO,false>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned Hermitian matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::lowerBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.lowerBound( i, j ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned Hermitian matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstIterator
+ HermitianMatrix<MT,SO,false>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned Hermitian matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::Iterator
+ HermitianMatrix<MT,SO,false>::upperBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.upperBound( i, j ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned Hermitian matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename HermitianMatrix<MT,SO,false>::ConstIterator
+ HermitianMatrix<MT,SO,false>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the Hermitian matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function both appends the element \f$ a_{ij} \f$ to the specified row/column and inserts
+// its according counterpart \f$ a_{ji} \f$ into the Hermitian matrix. Since element \f$ a_{ij} \f$
+// is appended without any additional memory allocation, it is strictly necessary to keep the
+// following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// Although in addition to element \f$ a_{ij} \f$ a second element \f$ a_{ji} \f$ is inserted into
+// the matrix, this function still provides the most efficient way to fill a Hermitian matrix with
+// values. However, in order to achieve maximum efficiency, the matrix has to be specifically
+// prepared with reserve() calls:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::HermitianMatrix;
+ using blaze::rowMajor;
+
+ typedef std::complex<double> cplx;
+
+ // Setup of the Hermitian matrix
+ //
+ // ( (0, 0) (1,2) (3,-4) )
+ // A = ( (1,-2) (2,0) (0, 0) )
+ // ( (3, 4) (0,0) (0, 0) )
+ //
+ HermitianMatrix< CompressedMatrix<double,rowMajor> > A( 3 );
+
+ A.reserve( 5 ); // Reserving enough capacity for 5 non-zero elements
+ A.reserve( 0, 2 ); // Reserving two non-zero elements in the first row
+ A.reserve( 1, 2 ); // Reserving two non-zero elements in the second row
+ A.reserve( 2, 1 ); // Reserving a single non-zero element in the third row
+
+ A.append( 0, 1, cplx( 1.0, 2.0 ) ); // Appending an element at position (0,1) and (1,0)
+ A.append( 1, 1, cplx( 2.0, 0.0 ) ); // Appending an element at position (1,1)
+ A.append( 2, 0, cplx( 3.0, 4.0 ) ); // Appending an element at position (2,0) and (0,2)
+ \endcode
+
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ const bool isDiagonal( i == j );
+
+ if( IsComplex<ElementType>::value && isDiagonal && !isReal( value ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+
+ matrix_.append( i, j, value, check );
+ if( !isDiagonal && ( !check || !isDefault( value ) ) )
+ matrix_.insert( j, i, conj( value ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void HermitianMatrix<MT,SO,false>::finalize( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the Hermitian matrix are intact.
+//
+// \return \a true in case the Hermitian matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the Hermitian matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool HermitianMatrix<MT,SO,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isHermitian( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool HermitianMatrix<MT,SO,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool HermitianMatrix<MT,SO,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool HermitianMatrix<MT,SO,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT2& HermitianMatrix<MT,SO,false>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ return ~m;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the foreign matrix
+inline TransExprTrait_<MT2>
+ HermitianMatrix<MT,SO,false>::construct( const Matrix<MT2,!SO>& m, TrueType )
+{
+ return trans( ~m );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/lowermatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/lowermatrix/BaseTemplate.h
new file mode 100644
index 00000000..a8e9b8a9
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/lowermatrix/BaseTemplate.h
@@ -0,0 +1,555 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/lowermatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the LowerMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_LOWERMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_LOWERMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup lower_matrix LowerMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for lower triangular \f$ N \times N \f$ matrices.
+// \ingroup lower_matrix
+//
+// \section lowermatrix_general General
+//
+// The LowerMatrix class template is an adapter for existing dense and sparse matrix types. It
+// inherits the properties and the interface of the given matrix type \a MT and extends it by
+// enforcing the additional invariant that all matrix elements above the diagonal are 0 (lower
+// triangular matrix). The type of the adapted matrix can be specified via the first template
+// parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF >
+ class LowerMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. LowerMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Note that the given matrix type must be either resizable (as for instance
+// HybridMatrix or DynamicMatrix) or must be square at compile time (as for instance
+// StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+// The following examples give an impression of several possible lower matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense lower matrix with static memory
+ blaze::LowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense lower matrix based on HybridMatrix
+ blaze::LowerMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense lower matrix based on DynamicMatrix
+ blaze::LowerMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense lower matrix based on CustomMatrix
+ blaze::LowerMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision lower matrix
+ blaze::LowerMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of a lower matrix is depending on the storage order of the adapted matrix
+// type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified
+// as blaze::rowMajor), the lower matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the lower matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section lowermatrix_special_properties Special Properties of Lower Triangular Matrices
+//
+// A lower matrix is used exactly like a matrix of the underlying, adapted matrix type \a MT. It
+// also provides (nearly) the same interface as the underlying matrix type. However, there are
+// some important exceptions resulting from the lower matrix constraint:
+//
+// -# <b>\ref lowermatrix_square</b>
+// -# <b>\ref lowermatrix_lower</b>
+// -# <b>\ref lowermatrix_initialization</b>
+// -# <b>\ref lowermatrix_storage</b>
+//
+// \n \subsection lowermatrix_square Lower Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 lower dynamic matrix
+ LowerMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::LowerMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 lower static matrix
+ LowerMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ LowerMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection lowermatrix_lower The Lower Matrix Property is Always Enforced!
+//
+// This means that it is only allowed to modify elements in the lower part or the diagonal of
+// the matrix, but not the elements in the upper part of the matrix. Also, it is only possible
+// to assign matrices that are lower matrices themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+
+ typedef LowerMatrix< CompressedMatrix<double,rowMajor> > CompressedLower;
+
+ // Default constructed, row-major 3x3 lower compressed matrix
+ CompressedLower A( 3 );
+
+ // Initializing elements via the function call operator
+ A(0,0) = 1.0; // Initialization of the diagonal element (0,0)
+ A(2,0) = 2.0; // Initialization of the lower element (2,0)
+ A(1,2) = 9.0; // Throws an exception; invalid modification of upper element
+
+ // Inserting two more elements via the insert() function
+ A.insert( 1, 0, 3.0 ); // Inserting the lower element (1,0)
+ A.insert( 2, 1, 4.0 ); // Inserting the lower element (2,1)
+ A.insert( 0, 2, 9.0 ); // Throws an exception; invalid insertion of upper element
+
+ // Appending an element via the append() function
+ A.reserve( 1, 3 ); // Reserving enough capacity in row 1
+ A.append( 1, 1, 5.0 ); // Appending the diagonal element (1,1)
+ A.append( 1, 2, 9.0 ); // Throws an exception; appending an element in the upper part
+
+ // Access via a non-const iterator
+ CompressedLower::Iterator it = A.begin(1);
+ *it = 6.0; // Modifies the lower element (1,0)
+ ++it;
+ *it = 9.0; // Modifies the diagonal element (1,1)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 2, 0 ); // Erasing the lower element (2,0)
+
+ // Construction from a lower dense matrix
+ StaticMatrix<double,3UL,3UL> B( 3.0, 0.0, 0.0,
+ 8.0, 0.0, 0.0,
+ -2.0, -1.0, 4.0 );
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-lower dense matrix
+ StaticMatrix<double,3UL,3UL> D( 3.0, 0.0, -2.0,
+ 8.0, 0.0, 0.0,
+ -2.0, -1.0, 4.0 );
+
+ C = D; // Throws an exception; lower matrix invariant would be violated!
+ \endcode
+
+// The lower matrix property is also enforced for lower custom matrices: In case the given array
+// of elements does not represent a lower matrix, a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::LowerMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef LowerMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomLower;
+
+ // Creating a 3x3 lower custom matrix from a properly initialized array
+ double array[9] = { 1.0, 0.0, 0.0,
+ 2.0, 3.0, 0.0,
+ 4.0, 5.0, 6.0 };
+ CustomLower A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 lower custom matrix from an uninitialized array
+ CustomLower B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the lower matrix property is enforced for views (rows, columns, submatrices, ...) on
+// the lower matrix. The following example demonstrates that modifying the elements of an entire
+// row and submatrix of a lower matrix only affects the lower and diagonal matrix elements:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+
+ // Setup of the lower matrix
+ //
+ // ( 0 0 0 0 )
+ // A = ( 1 2 0 0 )
+ // ( 0 3 0 0 )
+ // ( 4 0 5 0 )
+ //
+ LowerMatrix< DynamicMatrix<int> > A( 4 );
+ A(1,0) = 1;
+ A(1,1) = 2;
+ A(2,1) = 3;
+ A(3,0) = 4;
+ A(3,2) = 5;
+
+ // Setting the lower and diagonal elements in the 2nd row to 9 results in the matrix
+ //
+ // ( 0 0 0 0 )
+ // A = ( 1 2 0 0 )
+ // ( 9 9 9 0 )
+ // ( 4 0 5 0 )
+ //
+ row( A, 2 ) = 9;
+
+ // Setting the lower and diagonal elements in the 1st and 2nd column to 7 results in
+ //
+ // ( 0 0 0 0 )
+ // A = ( 1 7 0 0 )
+ // ( 9 7 7 0 )
+ // ( 4 7 7 0 )
+ //
+ submatrix( A, 0, 1, 4, 2 ) = 7;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to rows/columns and submatrices of
+// lower matrices. Since only lower and diagonal elements may be modified the matrix to be
+// assigned must be structured such that the lower matrix invariant of the lower matrix is
+// preserved. Otherwise a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::LowerMatrix;
+ using blaze::rowVector;
+
+ // Setup of two default 4x4 lower matrices
+ LowerMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of a 4-dimensional vector
+ //
+ // v = ( 1 2 3 0 )
+ //
+ DynamicVector<int,rowVector> v( 4, 0 );
+ v[0] = 1;
+ v[1] = 2;
+ v[2] = 3;
+
+ // OK: Assigning v to the 2nd row of A1 preserves the lower matrix invariant
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 0 0 0 )
+ // ( 1 2 3 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 2 ) = v; // OK
+
+ // Error: Assigning v to the 1st row of A1 violates the lower matrix invariant! The element
+ // marked with X cannot be assigned and triggers an exception.
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 1 2 X 0 )
+ // ( 1 2 3 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 1 ) = v; // Assignment throws an exception!
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 0 0 )
+ // B = ( 7 0 )
+ // ( 8 9 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL, 0 );
+ B(1,0) = 7;
+ B(2,0) = 8;
+ B(2,1) = 9;
+
+ // OK: Assigning B to a submatrix of A2 such that the lower matrix invariant can be preserved
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 7 0 0 )
+ // ( 0 8 9 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the lower matrix invariant cannot be
+ // preserved! The elements marked with X cannot be assigned without violating the invariant!
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 7 X 0 )
+ // ( 0 8 8 X )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 2UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection lowermatrix_initialization The Upper Elements of a Dense Lower Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency during the creation of a dense lower matrix
+// this initialization is important since otherwise the lower matrix property of dense lower
+// matrices would not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // 5x5 row-major lower dynamic matrix with default initialized upper matrix
+ LowerMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \subsection lowermatrix_storage Dense Lower Matrices Also Store the Upper Elements!
+//
+// It is important to note that dense lower matrices store all elements, including the elements
+// in the upper part of the matrix, and therefore don't provide any kind of memory reduction!
+// There are two main reasons for this: First, storing also the upper elements guarantees maximum
+// performance for many algorithms that perform vectorized operations on the lower matrix, which
+// is especially true for small dense matrices. Second, conceptually the LowerMatrix adaptor
+// merely restricts the interface to the matrix type \a MT and does not change the data layout
+// or the underlying matrix type.
+//
+//
+// \n \section lowermatrix_arithmetic_operations Arithmetic Operations
+//
+// A LowerMatrix matrix can participate in numerical operations in any way any other dense or
+// sparse matrix can participate. It can also be combined with any other dense or sparse vector
+// or matrix. The following code example gives an impression of the use of LowerMatrix within
+// arithmetic operations:
+
+ \code
+ using blaze::LowerMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ LowerMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ LowerMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > E;
+ LowerMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major lower matrix
+ F = C - D; // Matrix subtraction and assignment to a column-major lower matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section lowermatrix_block_structured Block-Structured Lower Matrices
+//
+// It is also possible to use block-structured lower matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticMatrix;
+ using blaze::LowerMatrix;
+
+ // Definition of a 5x5 block-structured lower matrix based on CompressedMatrix
+ LowerMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > A( 5 );
+ \endcode
+
+// Also in this case the lower matrix invariant is enforced, i.e. it is not possible to manipulate
+// elements in the upper part of the matrix:
+
+ \code
+ const StaticMatrix<int,3UL,3UL> B( { { 1, -4, 5 },
+ { 6, 8, -3 },
+ { 2, -1, 2 } } )
+
+ A.insert( 4, 2, B ); // Inserting the elements (4,2)
+ A(2,4)(1,1) = -5; // Invalid manipulation of upper matrix element; Results in an exception
+ \endcode
+
+// \n \section lowermatrix_performance Performance Considerations
+//
+// The \b Blaze library tries to exploit the properties of lower matrices whenever and wherever
+// possible. Thus using a lower triangular matrix instead of a general matrix can result in a
+// considerable performance improvement. However, there are also situations when using a lower
+// triangular matrix introduces some overhead. The following examples demonstrate several common
+// situations where lower matrices can positively or negatively impact performance.
+//
+// \n \subsection lowermatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is lower triangular, \b Blaze can exploit
+// the fact that the upper part of the matrix contains only default elements and restrict the
+// algorithm to the lower and diagonal elements. The following example demonstrates this by means
+// of a dense matrix/dense matrix multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ LowerMatrix< DynamicMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// In comparison to a general matrix multiplication, the performance advantage is significant,
+// especially for large matrices. Therefore is it highly recommended to use the LowerMatrix
+// adaptor when a matrix is known to be lower triangular. Note however that the performance
+// advantage is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection lowermatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar performance improvement can be gained when using a lower matrix in a matrix/vector
+// multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ LowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicVector<double,columnVector> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example, \b Blaze also exploits the structure of the matrix and approx. halves the
+// runtime of the multiplication. Also in case of matrix/vector multiplications the performance
+// improvement is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection lowermatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a lower triangular matrix on the right-hand side of an assignment (i.e.
+// for read access), which introduces absolutely no performance penalty, using a lower matrix on
+// the left-hand side of an assignment (i.e. for write access) may introduce additional overhead
+// when it is assigned a general matrix, which is not lower triangular at compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::LowerMatrix;
+
+ LowerMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the lower matrix; no performance penalty
+ C = A; // Assignment of a lower matrix to another lower matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a lower matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not lower matrix to a lower matrix it is necessary to
+// check whether the matrix is lower at runtime in order to guarantee the lower triangular property
+// of the lower matrix. In case it turns out to be lower triangular, it is assigned as efficiently
+// as possible, if it is not, an exception is thrown. In order to prevent this runtime overhead it
+// is therefore generally advisable to assign lower matrices to other lower matrices.\n
+// In this context it is especially noteworthy that the addition, subtraction, and multiplication
+// of two lower triangular matrices always results in another lower matrix:
+
+ \code
+ LowerMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a lower matrix; no runtime overhead
+ C = A - B; // Results in a lower matrix; no runtime overhead
+ C = A * B; // Results in a lower matrix; no runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class LowerMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/lowermatrix/Dense.h b/src/cpu/blaze/math/adaptors/lowermatrix/Dense.h
new file mode 100644
index 00000000..4532d762
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/lowermatrix/Dense.h
@@ -0,0 +1,2740 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/lowermatrix/Dense.h
+// \brief LowerMatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_LOWERMATRIX_DENSE_H_
+#define _BLAZE_MATH_ADAPTORS_LOWERMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/lowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/lowermatrix/LowerProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/Square.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of LowerMatrix for dense matrices.
+// \ingroup lower_matrix
+//
+// This specialization of LowerMatrix adapts the class template to the requirements of dense
+// matrices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class LowerMatrix<MT,SO,true>
+ : public DenseMatrix< LowerMatrix<MT,SO,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef LowerMatrix<MT,SO,true> This; //!< Type of this LowerMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this LowerMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef LowerMatrix<OT,!SO,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef UpperMatrix<TT,!SO,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef LowerProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a LowerMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other LowerMatrix.
+ typedef LowerMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense lower matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef LowerProxy<MT> PointerType; //!< Pointer return type.
+ typedef LowerProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row-index of the iterator
+ , column_( column ) // The current column-index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) noexcept {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row-index of the iterator.
+ size_t column_; //!< The current column-index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline LowerMatrix();
+ template< typename A1 > explicit inline LowerMatrix( const A1& a1 );
+ explicit inline LowerMatrix( size_t n, const ElementType& init );
+
+ explicit inline LowerMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline LowerMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline LowerMatrix( const Other (&array)[N][N] );
+
+ explicit inline LowerMatrix( ElementType* ptr, size_t n );
+ explicit inline LowerMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline LowerMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline LowerMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline LowerMatrix( const LowerMatrix& m );
+ inline LowerMatrix( LowerMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline LowerMatrix& operator=( const ElementType& rhs );
+ inline LowerMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline LowerMatrix& operator=( const Other (&array)[N][N] );
+
+ inline LowerMatrix& operator=( const LowerMatrix& rhs );
+ inline LowerMatrix& operator=( LowerMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, LowerMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, LowerMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, LowerMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, LowerMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, LowerMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, LowerMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline LowerMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, LowerMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, LowerMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ template< typename Other > inline LowerMatrix& scale( const Other& scalar );
+ inline void swap( LowerMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ inline const MT construct( size_t n , TrueType );
+ inline const MT construct( const ElementType& value, FalseType );
+
+ template< typename MT2, bool SO2, typename T >
+ inline const MT construct( const Matrix<MT2,SO2>& m, T );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend bool isDefault( const LowerMatrix<MT2,SO2,DF2>& m );
+
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( LowerMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for LowerMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>::LowerMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Single argument constructor for a lower matrix.
+//
+// \param a1 The single constructor argument.
+// \exception std::invalid_argument Invalid setup of lower matrix.
+//
+// This constructor constructs the lower matrix based on the given argument and the type of
+// the underlying matrix \a MT:
+// - in case the given argument is a matrix, the lower matrix is initialized as a copy of
+// the given matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// resizable, the given argument \a a1 specifies the number of rows and columns of the
+// lower matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// a matrix with fixed size, the given argument \a a1 specifies the initial value of the
+// lower and diagonal elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename A1 > // Type of the constructor argument
+inline LowerMatrix<MT,SO,true>::LowerMatrix( const A1& a1 )
+ : matrix_( construct( a1, typename IsResizable<MT>::Type() ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a \f$ n \times n \f$ matrix with initialized lower and diagonal elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param init The initial value of the lower and diagonal matrix elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>::LowerMatrix( size_t n, const ElementType& init )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=j; i<rows(); ++i )
+ matrix_(i,j) = init;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) = init;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of lower matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the lower
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::LowerMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A{ { 1, 0, 0 },
+ { 2, 3 },
+ { 4, 5 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>::LowerMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all lower matrix elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of lower matrix.
+//
+// This constructor offers the option to directly initialize the elements of the lower matrix
+// with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[16];
+ // ... Initialization of the dynamic array
+ blaze::LowerMatrix< blaze::DynamicMatrix<int,rowMajor> > v( 4UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized accoring to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a n by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also, in
+// case the given array does not represent a lower triangular matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline LowerMatrix<MT,SO,true>::LowerMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all lower matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of lower matrix.
+//
+// This constructor offers the option to directly initialize the elements of the lower matrix
+// with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 0, 0 },
+ { 2, 3 },
+ { 4, 5 } };
+ blaze::LowerMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a lower triangular matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline LowerMatrix<MT,SO,true>::LowerMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a lower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of lower custom matrix.
+//
+// This constructor creates an unpadded lower custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded lower custom matrices!
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>::LowerMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a lower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of lower custom matrix.
+//
+// This constructor creates a lower custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>::LowerMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a lower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of lower custom matrix.
+//
+// This constructor creates an unpadded lower custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded lower custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline LowerMatrix<MT,SO,true>::LowerMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a lower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of lower custom matrix.
+//
+// This constructor creates a lower custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline LowerMatrix<MT,SO,true>::LowerMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for LowerMatrix.
+//
+// \param m The lower matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>::LowerMatrix( const LowerMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for LowerMatrix.
+//
+// \param m The lower matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>::LowerMatrix( LowerMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::Reference
+ LowerMatrix<MT,SO,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::ConstReference
+ LowerMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::Reference
+ LowerMatrix<MT,SO,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::ConstReference
+ LowerMatrix<MT,SO,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the lower matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The lower matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::ConstPointer
+ LowerMatrix<MT,SO,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::ConstPointer
+ LowerMatrix<MT,SO,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the lower matrix adapts a \a rowMajor dense matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::Iterator
+ LowerMatrix<MT,SO,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the lower matrix adapts a \a rowMajor dense matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::ConstIterator
+ LowerMatrix<MT,SO,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the lower matrix adapts a \a rowMajor dense matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::ConstIterator
+ LowerMatrix<MT,SO,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the lower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::Iterator
+ LowerMatrix<MT,SO,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the lower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::ConstIterator
+ LowerMatrix<MT,SO,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the lower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename LowerMatrix<MT,SO,true>::ConstIterator
+ LowerMatrix<MT,SO,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all lower and diagonal matrix elements.
+//
+// \param rhs Scalar value to be assigned to the lower and diagonal matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>&
+ LowerMatrix<MT,SO,true>::operator=( const ElementType& rhs )
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=j; i<rows(); ++i )
+ matrix_(i,j) = rhs;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the lower
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::LowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = { { 1, 0, 0 },
+ { 2, 3 },
+ { 4, 5 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>&
+ LowerMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all lower matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// This assignment operator offers the option to directly set all elements of the lower matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 0, 0 },
+ { 2, 3 },
+ { 4, 5 } };
+ blaze::LowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a lower triangular matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline LowerMatrix<MT,SO,true>&
+ LowerMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for LowerMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>&
+ LowerMatrix<MT,SO,true>::operator=( const LowerMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for LowerMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline LowerMatrix<MT,SO,true>&
+ LowerMatrix<MT,SO,true>::operator=( LowerMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// lower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,true>& >
+ LowerMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsLower<MT2>::value && !isLower( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// lower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,true>& >
+ LowerMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ if( IsLower<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a lower
+// matrix, i.e. the given matrix must be a lower matrix. In case the result is not a lower
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,true>& >
+ LowerMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsLower<MT2>::value && !isLower( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a lower
+// matrix, i.e. the given matrix must be a lower matrix. In case the result is not a lower
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,true>& >
+ LowerMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ if( IsLower<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a
+// lower matrix, i.e. the given matrix must be a lower matrix. In case the result is not
+// a lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,true>& >
+ LowerMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsLower<MT2>::value && !isLower( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a
+// lower matrix, i.e. the given matrix must be a lower matrix. In case the result is not
+// a lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,true>& >
+ LowerMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ if( IsLower<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a lower matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline LowerMatrix<MT,SO,true>&
+ LowerMatrix<MT,SO,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, LowerMatrix<MT,SO,true> >&
+ LowerMatrix<MT,SO,true>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, LowerMatrix<MT,SO,true> >&
+ LowerMatrix<MT,SO,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t LowerMatrix<MT,SO,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t LowerMatrix<MT,SO,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the total
+// number of elements of a row/column. In case the lower matrix adapts a \a rowMajor dense
+// matrix the function returns the spacing between two rows, in case it adapts a \a columnMajor
+// dense matrix the function returns the spacing between two columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t LowerMatrix<MT,SO,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t LowerMatrix<MT,SO,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the lower
+// matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor dense matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t LowerMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the lower matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t LowerMatrix<MT,SO,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the lower matrix adapts a \a rowMajor dense matrix the function returns the number
+// of non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix the
+// function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t LowerMatrix<MT,SO,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void LowerMatrix<MT,SO,true>::reset()
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=j; i<rows(); ++i )
+ clear( matrix_(i,j) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void LowerMatrix<MT,SO,true>::reset( size_t i )
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=i; j<rows(); ++j )
+ clear( matrix_(j,i) );
+ }
+ else {
+ for( size_t j=0UL; j<=i; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the lower matrix.
+//
+// \return void
+//
+// This function clears the lower matrix and returns it to its default state. The function has
+// the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
+// matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
+// to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
+// be reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void LowerMatrix<MT,SO,true>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the lower matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the lower matrix adapts a resizable matrix, this function resizes the matrix using
+// the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
+// in case the capacity of the matrix is too small. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, the resize operation potentially changes all matrix elements. In order
+// to preserve the old matrix values, the \a preserve flag can be set to \a true. Also note that
+// in case the size of the matrix is increased, only the new elements in the upper part of the
+// matrix are default initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 0 & 0 \\
+ 2 & 3 & 0 \\
+ 4 & 5 & 6 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 0 & 0 & 0 \\
+ 2 & 3 & 0 & 0 \\
+ 4 & 5 & 6 & 0 \\
+ x & x & x & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void LowerMatrix<MT,SO,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize ) {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, 0UL, oldsize, n-1UL, increment ).reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void LowerMatrix<MT,SO,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the lower matrix.
+// \return void
+//
+// This function increases the capacity of the lower matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void LowerMatrix<MT,SO,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the scalar value
+inline LowerMatrix<MT,SO,true>& LowerMatrix<MT,SO,true>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void LowerMatrix<MT,SO,true>::swap( LowerMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a lower triangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a lower triangular
+// matrix with fixed-size adapted matrix of type \a MT. Note that this function can only be
+// called in case the adapted dense matrix is a fixed-size matrix (as for instance StaticMatrix).
+// The attempt to call this function in case the adapted matrix is resizable matrix will result
+// in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t LowerMatrix<MT,SO,true>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a lower triangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a lower triangular
+// matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t LowerMatrix<MT,SO,true>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n + 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the lower matrix are intact.
+//
+// \return \a true in case the lower matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the lower matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool LowerMatrix<MT,SO,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isLower( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool LowerMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool LowerMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool LowerMatrix<MT,SO,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool LowerMatrix<MT,SO,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the lower matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename LowerMatrix<MT,SO,true>::SIMDType
+ LowerMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the lower matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename LowerMatrix<MT,SO,true>::SIMDType
+ LowerMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the lower matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename LowerMatrix<MT,SO,true>::SIMDType
+ LowerMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a resizable matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT LowerMatrix<MT,SO,true>::construct( size_t n, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ return MT( n, n, ElementType() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a fixed-size matrix with homogeneously initialized lower and diagonal elements.
+//
+// \param init The initial value of the lower and diagonal matrix elements.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT LowerMatrix<MT,SO,true>::construct( const ElementType& init, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SQUARE( MT );
+
+ MT tmp;
+
+ if( SO ) {
+ for( size_t j=0UL; j<tmp.columns(); ++j )
+ for( size_t i=j; i<tmp.rows(); ++i )
+ tmp(i,j) = init;
+ }
+ else {
+ for( size_t i=0UL; i<tmp.rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ tmp(i,j) = init;
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a matrix as a copy from another matrix.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of lower matrix.
+// \return The newly constructed matrix.
+//
+// In case the given matrix is not a lower matrix, a \a std::invalid_argument exception is
+// thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT LowerMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ const MT tmp( ~m );
+
+ if( !IsLower<MT2>::value && !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/lowermatrix/LowerProxy.h b/src/cpu/blaze/math/adaptors/lowermatrix/LowerProxy.h
new file mode 100644
index 00000000..865a47c4
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/lowermatrix/LowerProxy.h
@@ -0,0 +1,665 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/lowermatrix/LowerProxy.h
+// \brief Header file for the LowerProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_LOWERMATRIX_LOWERPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_LOWERMATRIX_LOWERPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/typetraits/AddConst.h>
+#include <blaze/util/typetraits/AddReference.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for lower triangular matrices.
+// \ingroup lower_matrix
+//
+// The LowerProxy provides controlled access to the elements of a non-const lower triangular
+// matrix. It guarantees that the lower matrix invariant is not violated, i.e. that elements
+// in the upper part of the matrix remain default values. The following example illustrates
+// this by means of a \f$ 3 \times 3 \f$ dense lower matrix:
+
+ \code
+ // Creating a 3x3 lower dense matrix
+ blaze::LowerMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(0,0) = -2; // ( -2 0 0 )
+ A(1,0) = 3; // => A = ( 3 0 0 )
+ A(2,1) = 5; // ( 0 5 0 )
+
+ A(0,2) = 7; // Invalid assignment to upper matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class LowerProxy : public Proxy< LowerProxy<MT>, ElementType_<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Reference type of the underlying matrix type.
+ typedef AddConst_< Reference_<MT> > ReferenceType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+ typedef AddReference_<ReferenceType> RawReference; //!< Reference-to-non-const to the represented element.
+ typedef const RepresentedType& ConstReference; //!< Reference-to-const to the represented element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline LowerProxy( MT& matrix, size_t row, size_t column );
+ inline LowerProxy( const LowerProxy& lp );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline const LowerProxy& operator=( const LowerProxy& lp ) const;
+
+ template< typename T >
+ inline const LowerProxy& operator=( initializer_list<T> list ) const;
+
+ template< typename T >
+ inline const LowerProxy& operator=( initializer_list< initializer_list<T> > list ) const;
+
+ template< typename T > inline const LowerProxy& operator= ( const T& value ) const;
+ template< typename T > inline const LowerProxy& operator+=( const T& value ) const;
+ template< typename T > inline const LowerProxy& operator-=( const T& value ) const;
+ template< typename T > inline const LowerProxy& operator*=( const T& value ) const;
+ template< typename T > inline const LowerProxy& operator/=( const T& value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline RawReference get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator ConstReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ ReferenceType value_; //!< Reference to the accessed matrix element.
+ const bool restricted_; //!< Access flag for the accessed matrix element.
+ /*!< The flag indicates if access to the matrix element is
+ restricted. It is \a true in case the proxy represents
+ an element in the upper part of the matrix. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a LowerProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline LowerProxy<MT>::LowerProxy( MT& matrix, size_t row, size_t column )
+ : value_ ( matrix( row, column ) ) // Reference to the accessed matrix element
+ , restricted_( row < column ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for LowerProxy.
+//
+// \param lp Lower proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline LowerProxy<MT>::LowerProxy( const LowerProxy& lp )
+ : value_ ( lp.value_ ) // Reference to the accessed matrix element
+ , restricted_( lp.restricted_ ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for LowerProxy.
+//
+// \param lp Lower proxy to be copied.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// In case the proxy represents an element in the upper matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline const LowerProxy<MT>& LowerProxy<MT>::operator=( const LowerProxy& lp ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix element" );
+ }
+
+ value_ = lp.value_;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// In case the proxy represents an element in the upper matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const LowerProxy<MT>& LowerProxy<MT>::operator=( initializer_list<T> list ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// In case the proxy represents an element in the upper matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const LowerProxy<MT>& LowerProxy<MT>::operator=( initializer_list< initializer_list<T> > list ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// In case the proxy represents an element in the upper matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const LowerProxy<MT>& LowerProxy<MT>::operator=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix element" );
+ }
+
+ value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// In case the proxy represents an element in the upper matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const LowerProxy<MT>& LowerProxy<MT>::operator+=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix element" );
+ }
+
+ value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// In case the proxy represents an element in the upper matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const LowerProxy<MT>& LowerProxy<MT>::operator-=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix element" );
+ }
+
+ value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// In case the proxy represents an element in the upper matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const LowerProxy<MT>& LowerProxy<MT>::operator*=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix element" );
+ }
+
+ value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// In case the proxy represents an element in the upper matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const LowerProxy<MT>& LowerProxy<MT>::operator/=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix element" );
+ }
+
+ value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename LowerProxy<MT>::RawReference LowerProxy<MT>::get() const noexcept
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted matrix element.
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool LowerProxy<MT>::isRestricted() const noexcept
+{
+ return restricted_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Reference-to-const to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline LowerProxy<MT>::operator ConstReference() const noexcept
+{
+ return static_cast<ConstReference>( value_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LowerProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const LowerProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const LowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const LowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const LowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const LowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const LowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const LowerProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup lower_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const LowerProxy<MT>& proxy )
+{
+ using blaze::reset;
+
+ reset( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup lower_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const LowerProxy<MT>& proxy )
+{
+ using blaze::clear;
+
+ clear( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup lower_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const LowerProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup lower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const LowerProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup lower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const LowerProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup lower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const LowerProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup lower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const LowerProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/lowermatrix/Sparse.h b/src/cpu/blaze/math/adaptors/lowermatrix/Sparse.h
new file mode 100644
index 00000000..fcf18bf0
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/lowermatrix/Sparse.h
@@ -0,0 +1,2072 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/lowermatrix/Sparse.h
+// \brief LowerMatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_LOWERMATRIX_SPARSE_H_
+#define _BLAZE_MATH_ADAPTORS_LOWERMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/lowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/lowermatrix/LowerProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of LowerMatrix for sparse matrices.
+// \ingroup lower_matrix
+//
+// This specialization of LowerMatrix adapts the class template to the requirements of sparse
+// matrices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class LowerMatrix<MT,SO,false>
+ : public SparseMatrix< LowerMatrix<MT,SO,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef LowerMatrix<MT,SO,false> This; //!< Type of this LowerMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this LowerMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef LowerMatrix<OT,!SO,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef UpperMatrix<TT,!SO,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef LowerProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a LowerMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other LowerMatrix.
+ typedef LowerMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline LowerMatrix();
+ explicit inline LowerMatrix( size_t n );
+ explicit inline LowerMatrix( size_t n, size_t nonzeros );
+ explicit inline LowerMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline LowerMatrix( const LowerMatrix& m );
+ inline LowerMatrix( LowerMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline LowerMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline LowerMatrix& operator=( const LowerMatrix& rhs );
+ inline LowerMatrix& operator=( LowerMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, LowerMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, LowerMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, LowerMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, LowerMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, LowerMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, LowerMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline LowerMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, LowerMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, LowerMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ template< typename Other > inline LowerMatrix& scale( const Other& scalar );
+ template< typename Other > inline LowerMatrix& scaleDiagonal( Other scale );
+ inline void swap( LowerMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void resetUpper();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend bool isDefault( const LowerMatrix<MT2,SO2,DF2>& m );
+
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( LowerMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for LowerMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline LowerMatrix<MT,SO,false>::LowerMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized to the zero matrix and has no free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline LowerMatrix<MT,SO,false>::LowerMatrix( size_t n )
+ : matrix_( n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized to the zero matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline LowerMatrix<MT,SO,false>::LowerMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+//
+// The matrix is initialized to the zero matrix and will have the specified capacity in each
+// row/column. Note that in case of a row-major matrix the given vector must have at least
+// \a m elements, in case of a column-major matrix at least \a n elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline LowerMatrix<MT,SO,false>::LowerMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for LowerMatrix.
+//
+// \param m The lower matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline LowerMatrix<MT,SO,false>::LowerMatrix( const LowerMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for LowerMatrix.
+//
+// \param m The lower matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline LowerMatrix<MT,SO,false>::LowerMatrix( LowerMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of lower matrix.
+//
+// This constructor initializes the lower matrix as a copy of the given matrix. In case the
+// given matrix is not a lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline LowerMatrix<MT,SO,false>::LowerMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( ~m ) // The adapted sparse matrix
+{
+ if( !IsLower<MT2>::value && !isLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" );
+ }
+
+ if( !IsLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Reference
+ LowerMatrix<MT,SO,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstReference
+ LowerMatrix<MT,SO,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Reference
+ LowerMatrix<MT,SO,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstReference
+ LowerMatrix<MT,SO,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::begin( size_t i )
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstIterator
+ LowerMatrix<MT,SO,false>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstIterator
+ LowerMatrix<MT,SO,false>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::end( size_t i )
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstIterator
+ LowerMatrix<MT,SO,false>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstIterator
+ LowerMatrix<MT,SO,false>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for LowerMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline LowerMatrix<MT,SO,false>&
+ LowerMatrix<MT,SO,false>::operator=( const LowerMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for LowerMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline LowerMatrix<MT,SO,false>&
+ LowerMatrix<MT,SO,false>::operator=( LowerMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// lower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,false>& >
+ LowerMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsLower<MT2>::value && !isLower( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ if( !IsLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// lower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,false>& >
+ LowerMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ if( IsLower<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ if( !IsLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a lower
+// matrix, i.e. the given matrix must be a lower matrix. In case the result is not a lower
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,false>& >
+ LowerMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsLower<MT2>::value && !isLower( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ if( !IsLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a lower
+// matrix, i.e. the given matrix must be a lower matrix. In case the result is not a lower
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,false>& >
+ LowerMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ if( IsLower<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ if( !IsLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a
+// lower matrix, i.e. the given matrix must be a lower matrix. In case the result is not
+// a lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,false>& >
+ LowerMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsLower<MT2>::value && !isLower( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ if( !IsLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a
+// lower matrix, i.e. the given matrix must be a lower matrix. In case the result is not
+// a lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, LowerMatrix<MT,SO,false>& >
+ LowerMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ if( IsLower<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ if( !IsLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a lower matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline LowerMatrix<MT,SO,false>&
+ LowerMatrix<MT,SO,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ if( !IsLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, LowerMatrix<MT,SO,false> >&
+ LowerMatrix<MT,SO,false>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, LowerMatrix<MT,SO,false> >&
+ LowerMatrix<MT,SO,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t LowerMatrix<MT,SO,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t LowerMatrix<MT,SO,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t LowerMatrix<MT,SO,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the lower
+// matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t LowerMatrix<MT,SO,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the lower matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t LowerMatrix<MT,SO,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the lower matrix adapts a \a rowMajor sparse matrix the function returns the number
+// of non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse matrix the
+// function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t LowerMatrix<MT,SO,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::reset( size_t i )
+{
+ matrix_.reset( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the lower matrix.
+//
+// \return void
+//
+// This function clears the lower matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the lower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to upper matrix element.
+//
+// This function sets the value of an element of the lower matrix. In case the lower matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted. The attempt to set an element in the
+// upper part of the matrix (i.e. above the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ if( i < j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to upper matrix element" );
+ }
+
+ return matrix_.set( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the lower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+// \exception std::invalid_argument Invalid access to upper matrix element.
+//
+// This function inserts a new element into the lower matrix. However, duplicate elements are
+// not allowed. In case the lower matrix already contains an element with row index \a i and
+// column index \a j, a \a std::invalid_argument exception is thrown. Also, the attempt to
+// insert an element in the upper part of the matrix (i.e. above the diagonal) will result in
+// a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ if( i < j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to upper matrix element" );
+ }
+
+ return matrix_.insert( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the lower matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the lower matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::erase( size_t i, size_t j )
+{
+ matrix_.erase( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the lower matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the lower matrix. In case the lower matrix adapts a
+// \a rowMajor sparse matrix the function erases an element from row \a i, in case it adapts
+// a \a columnMajor sparse matrix the function erases an element from column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::erase( size_t i, Iterator pos )
+{
+ return matrix_.erase( i, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the lower matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of element from the lower matrix. In case the lower matrix adapts
+// a \a rowMajor sparse matrix the function erases a range of elements from row \a i, in case it
+// adapts a \a columnMajor matrix the function erases a range of elements from column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ return matrix_.erase( i, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the lower matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void LowerMatrix<MT,SO,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square lower matrix detected" );
+
+ matrix_.resize( n, n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the lower matrix.
+//
+// \param nonzeros The new minimum capacity of the lower matrix.
+// \return void
+//
+// This function increases the capacity of the lower matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the lower matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the lower matrix to at least
+// \a nonzeros elements. The current values of the lower matrix and all other individual
+// row/column capacities are preserved. In case the lower matrix adapts a \rowMajor sparse
+// matrix the function reserves capacity for row \a i. In case it adapts a \a columnMajor the
+// function reserves capacity for column \a i. The index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the lower matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline LowerMatrix<MT,SO,false>&
+ LowerMatrix<MT,SO,false>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the lower matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the lower matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline LowerMatrix<MT,SO,false>&
+ LowerMatrix<MT,SO,false>::scaleDiagonal( Other scalar )
+{
+ matrix_.scaleDiagonal( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::swap( LowerMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a lower triangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a lower triangular
+// matrix with fixed-size adapted matrix of type \a MT. Note that this function can only be
+// called in case the adapted dense matrix is a fixed-size matrix. The attempt to call this
+// function in case the adapted matrix is resizable matrix will result in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t LowerMatrix<MT,SO,false>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a lower triangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a lower triangular
+// matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t LowerMatrix<MT,SO,false>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n + 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the complete upper part of the matrix to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void LowerMatrix<MT,SO,false>::resetUpper()
+{
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j )
+ matrix_.erase( j, matrix_.begin( j ), matrix_.lowerBound( j, j ) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ matrix_.erase( i, matrix_.upperBound( i, i ), matrix_.end( i ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the lower
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned lower matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::find( size_t i, size_t j )
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the lower
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned lower matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstIterator
+ LowerMatrix<MT,SO,false>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned lower matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::lowerBound( size_t i, size_t j )
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned lower matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstIterator
+ LowerMatrix<MT,SO,false>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned lower matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::Iterator
+ LowerMatrix<MT,SO,false>::upperBound( size_t i, size_t j )
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned lower matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename LowerMatrix<MT,SO,false>::ConstIterator
+ LowerMatrix<MT,SO,false>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the lower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to upper matrix element.
+//
+// This function provides a very efficient way to fill a lower sparse matrix with elements. It
+// appends a new element to the end of the specified row/column without any additional memory
+// allocation. Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (newly created) sparse matrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::LowerMatrix;
+ using blaze::rowMajor;
+
+ LowerMatrix< CompressedMatrix<double,rowMajor> > A( 4 );
+
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 0, 0, 1.0 ); // Appending the value 1 in row 0 with column index 0
+ A.finalize( 0 ); // Finalizing row 0
+ A.append( 1, 0, 2.0 ); // Appending the value 2 in row 1 with column index 0
+ A.finalize( 1 ); // Finalizing row 1
+ A.finalize( 2 ); // Finalizing the empty row 2 to prepare row 3
+ A.append( 3, 2, 3.0 ); // Appending the value 3 in row 3 with column index 2
+ A.finalize( 3 ); // Finalizing row 3
+ \endcode
+
+// Note that although append() does not allocate new memory it still invalidates all iterators
+// returned by the end() functions! Also note that the attempt to append an element within the
+// upper part of the matrix (i.e. above the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( i < j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to upper matrix element" );
+ }
+
+ matrix_.append( i, j, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void LowerMatrix<MT,SO,false>::finalize( size_t i )
+{
+ matrix_.finalize( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the lower matrix are intact.
+//
+// \return \a true in case the lower matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the lower matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool LowerMatrix<MT,SO,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isLower( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool LowerMatrix<MT,SO,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool LowerMatrix<MT,SO,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool LowerMatrix<MT,SO,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h
new file mode 100644
index 00000000..dd9ab311
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h
@@ -0,0 +1,560 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the StrictlyLowerMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYLOWERMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYLOWERMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup strictly_lower_matrix StrictlyLowerMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for strictly lower triangular \f$ N \times N \f$ matrices.
+// \ingroup strictly_lower_matrix
+//
+// \section strictlylowermatrix_general General
+//
+// The StrictlyLowerMatrix class template is an adapter for existing dense and sparse matrix
+// types. It inherits the properties and the interface of the given matrix type \a MT and extends
+// it by enforcing the additional invariant that all diagonal matrix elements and all matrix
+// elements above the diagonal are 0 (strictly lower triangular matrix). The type of the adapted
+// matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF >
+ class StrictlyLowerMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. StrictlyLowerMatrix can be used
+// with any non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse
+// matrix type. Note that the given matrix type must be either resizable (as for instance
+// HybridMatrix or DynamicMatrix) or must be square at compile time (as for instance
+// StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+// The following examples give an impression of several possible strictly lower triangular matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense strictly lower matrix with static memory
+ blaze::StrictlyLowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense strictly lower matrix based on HybridMatrix
+ blaze::StrictlyLowerMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense strictly lower matrix based on DynamicMatrix
+ blaze::StrictlyLowerMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense strictly lower matrix based on CustomMatrix
+ blaze::StrictlyLowerMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision strictly lower matrix
+ blaze::StrictlyLowerMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of a strictly lower triangular matrix is depending on the storage order of
+// the adapted matrix type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e.
+// is specified as blaze::rowMajor), the strictly lower matrix will also be a row-major matrix.
+// Otherwise if the adapted matrix is column-major (i.e. is specified as blaze::columnMajor),
+// the strictly lower matrix will also be a column-major matrix.
+//
+//
+// \n \section strictlylowermatrix_special_properties Special Properties of Strictly Lower Triangular Matrices
+//
+// A strictly lower triangular matrix is used exactly like a matrix of the underlying, adapted
+// matrix type \a MT. It also provides (nearly) the same interface as the underlying matrix type.
+// However, there are some important exceptions resulting from the strictly lower triangular
+// matrix constraint:
+//
+// -# <b>\ref strictlylowermatrix_square</b>
+// -# <b>\ref strictlylowermatrix_strictlylower</b>
+// -# <b>\ref strictlylowermatrix_initialization</b>
+// -# <b>\ref strictlylowermatrix_storage</b>
+//
+// \n \subsection strictlylowermatrix_square Strictly Lower Triangular Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyLowerMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 strictly lower dynamic matrix
+ StrictlyLowerMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::StrictlyLowerMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 strictly lower static matrix
+ StrictlyLowerMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ StrictlyLowerMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+//
+// \n \subsection strictlylowermatrix_strictlylower The Strictly Lower Triangular Matrix Property is Always Enforced!
+//
+// This means that it is only allowed to modify elements in the lower part of the matrix, but not
+// the elements on the diagonal or in the upper part of the matrix. Also, it is only possible to
+// to assign matrices that are strictly lower matrices themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::StrictlyLowerMatrix;
+ using blaze::rowMajor;
+
+ typedef StrictlyLowerMatrix< CompressedMatrix<double,rowMajor> > CompressedStrictlyLower;
+
+ // Default constructed, row-major 3x3 strictly lower compressed matrix
+ CompressedStrictlyLower A( 3 );
+
+ // Initializing elements via the function call operator
+ A(0,0) = 9.0; // Throws an exception; invalid modification of diagonal element
+ A(2,0) = 2.0; // Initialization of the lower element (2,0)
+ A(1,2) = 9.0; // Throws an exception; invalid modification of upper element
+
+ // Inserting elements via the insert() function
+ A.insert( 1, 0, 3.0 ); // Inserting the lower element (1,0)
+ A.insert( 1, 1, 9.0 ); // Throws an exception; invalid insertion of diagonal element
+ A.insert( 0, 2, 9.0 ); // Throws an exception; invalid insertion of upper element
+
+ // Appending an element via the append() function
+ A.reserve( 2, 2 ); // Reserving enough capacity in row 2
+ A.append( 1, 1, 9.0 ); // Throws an exception; appending a diagonal element
+ A.append( 2, 1, 4.0 ); // Appending the lower element (2,1)
+
+ // Access via a non-const iterator
+ CompressedStrictlyLower::Iterator it = A.begin(2);
+ *it = 7.0; // Modifies the lower element (2,0)
+ ++it;
+ *it = 8.0; // Modifies the lower element (2,1)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 2, 0 ); // Erasing the lower element (2,0)
+
+ // Construction from a strictly lower dense matrix
+ StaticMatrix<double,3UL,3UL> B( 0.0, 0.0, 0.0,
+ 8.0, 0.0, 0.0,
+ -2.0, -1.0, 0.0 );
+
+ StrictlyLowerMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a general dense matrix
+ StaticMatrix<double,3UL,3UL> D( 3.0, 0.0, -2.0,
+ 8.0, 0.0, 0.0,
+ -2.0, -1.0, 4.0 );
+
+ C = D; // Throws an exception; strictly lower triangular matrix invariant would be violated!
+ \endcode
+
+// The strictly lower matrix property is also enforced for strictly lower custom matrices: In case
+// the given array of elements does not represent a strictly lower matrix, a \a std::invalid_argument
+// exception is thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::StrictlyLowerMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef StrictlyLowerMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomStrictlyLower;
+
+ // Creating a 3x3 strictly lower custom matrix from a properly initialized array
+ double array[9] = { 0.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 2.0, 3.0, 0.0 };
+ CustomStrictlyLower A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 strictly lower custom matrix from an uninitialized array
+ CustomStrictlyLower B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the strictly lower matrix property is enforced for views (rows, columns, submatrices,
+// ...) on the strictly lower matrix. The following example demonstrates that modifying the
+// elements of an entire row and submatrix of a strictly lower matrix only affects the lower
+// matrix elements:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyLowerMatrix;
+
+ // Setup of the strictly lower matrix
+ //
+ // ( 0 0 0 0 )
+ // A = ( 2 0 0 0 )
+ // ( 0 3 0 0 )
+ // ( 4 0 5 0 )
+ //
+ StrictlyLowerMatrix< DynamicMatrix<int> > A( 4 );
+ A(1,0) = 2;
+ A(2,1) = 3;
+ A(3,0) = 4;
+ A(3,2) = 5;
+
+ // Setting the lower elements in the 2nd row to 9 results in the matrix
+ //
+ // ( 0 0 0 0 )
+ // A = ( 2 0 0 0 )
+ // ( 9 9 0 0 )
+ // ( 4 0 5 0 )
+ //
+ row( A, 2 ) = 9;
+
+ // Setting the lower elements in the 1st and 2nd column to 7 results in
+ //
+ // ( 0 0 0 0 )
+ // A = ( 1 0 0 0 )
+ // ( 9 7 0 0 )
+ // ( 4 7 7 0 )
+ //
+ submatrix( A, 0, 1, 4, 2 ) = 7;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to rows/columns and submatrices of
+// strictly lower matrices. Since only lower elements may be modified the matrix to be assigned
+// must be structured such that the strictly lower triangular matrix invariant of the strictly
+// lower matrix is preserved. Otherwise a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::StrictlyLowerMatrix;
+ using blaze::rowVector;
+
+ // Setup of two default 4x4 strictly lower matrices
+ StrictlyLowerMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of a 4-dimensional vector
+ //
+ // v = ( 3 2 0 0 )
+ //
+ DynamicVector<int,rowVector> v( 4, 0 );
+ v[0] = 3;
+ v[1] = 2;
+
+ // OK: Assigning v to the 2nd row of A1 preserves the strictly lower matrix invariant
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 0 0 0 )
+ // ( 3 2 0 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 2 ) = v; // OK
+
+ // Error: Assigning v to the 1st row of A1 violates the strictly lower matrix invariant! The
+ // element marked with X cannot be assigned and triggers an exception.
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 3 X 0 0 )
+ // ( 3 2 0 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 1 ) = v; // Assignment throws an exception!
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 0 0 )
+ // B = ( 7 0 )
+ // ( 8 9 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL, 0 );
+ B(1,0) = 7;
+ B(2,0) = 8;
+ B(2,1) = 9;
+
+ // OK: Assigning B to a submatrix of A2 such that the invariant can be preserved
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 0 0 0 )
+ // ( 0 7 0 0 )
+ // ( 0 8 9 0 )
+ //
+ submatrix( A2, 1UL, 1UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the lower matrix invariant cannot be
+ // preserved! The elements marked with X cannot be assigned without violating the invariant!
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 0 0 0 )
+ // ( 0 7 X 0 )
+ // ( 0 8 8 X )
+ //
+ submatrix( A2, 1UL, 2UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection strictlylowermatrix_initialization The Diagonal and Upper Elements of a Dense Strictly Lower Triangular Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency during the creation of a dense strictly
+// lower matrix this initialization is important since otherwise the strictly lower triangular
+// matrix property of dense strictly lower matrices would not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyLowerMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // 5x5 row-major strictly lower dynamic matrix with default initialized diagonal and upper matrix
+ StrictlyLowerMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \subsection strictlylowermatrix_storage Dense Strictly Lower Matrices Also Store the Diagonal and Upper Elements!
+//
+// It is important to note that dense strictly lower matrices store all elements, including the
+// elements on the diagonal and in the upper part of the matrix, and therefore don't provide any
+// kind of memory reduction! There are two main reasons for this: First, storing also the diagonal
+// and upper elements guarantees maximum performance for many algorithms that perform vectorized
+// operations on the lower matrix, which is especially true for small dense matrices. Second,
+// conceptually the StrictlyLowerMatrix adaptor merely restricts the interface to the matrix type
+// \a MT and does not change the data layout or the underlying matrix type.
+//
+//
+// \n \section strictlylowermatrix_arithmetic_operations Arithmetic Operations
+//
+// A StrictlyLowerMatrix matrix can participate in numerical operations in any way any other dense
+// or sparse matrix can participate. It can also be combined with any other dense or sparse vector
+// or matrix. The following code example gives an impression of the use of StrictlyLowerMatrix
+// within arithmetic operations:
+
+ \code
+ using blaze::StrictlyLowerMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ StrictlyLowerMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ StrictlyLowerMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ StrictlyLowerMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > E;
+ StrictlyLowerMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major strictly lower matrix
+ F = C - D; // Matrix subtraction and assignment to a column-major strictly lower matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section strictlylowermatrix_block_structured Block-Structured Strictly Lower Matrices
+//
+// It is also possible to use block-structured strictly lower matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticMatrix;
+ using blaze::StrictlyLowerMatrix;
+
+ // Definition of a 5x5 block-structured strictly lower matrix based on CompressedMatrix
+ StrictlyLowerMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > A( 5 );
+ \endcode
+
+// Also in this case the strictly lower matrix invariant is enforced, i.e. it is not possible to
+// manipulate elements in the upper part of the matrix:
+
+ \code
+ const StaticMatrix<int,3UL,3UL> B( { { 1, -4, 5 },
+ { 6, 8, -3 },
+ { 2, -1, 2 } } )
+
+ A.insert( 4, 2, B ); // Inserting the elements (4,2)
+ A(2,4)(1,1) = -5; // Invalid manipulation of upper matrix element; Results in an exception
+ \endcode
+
+// \n \section strictlylowermatrix_performance Performance Considerations
+//
+// The \b Blaze library tries to exploit the properties of strictly lower triangular matrices
+// whenever and wherever possible. Thus using a strictly lower triangular matrix instead of
+// a general matrix can result in a considerable performance improvement. However, there are
+// also situations when using a strictly lower matrix introduces some overhead. The following
+// examples demonstrate several common situations where strictly lower matrices can positively
+// or negatively impact performance.
+//
+// \n \subsection strictlylowermatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is strictly lower triangular, \b Blaze
+// can exploit the fact that the diagonal and the upper part of the matrix contains only default
+// elements and restrict the algorithm to the lower elements. The following example demonstrates
+// this by means of a dense matrix/dense matrix multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyLowerMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ StrictlyLowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ StrictlyLowerMatrix< DynamicMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// In comparison to a general matrix multiplication, the performance advantage is significant,
+// especially for large and medium-sized matrices. Therefore is it highly recommended to use
+// the StrictlyLowerMatrix adaptor when a matrix is known to be strictly lower triangular. Note
+// however that the performance advantage is most pronounced for dense matrices and much less
+// so for sparse matrices.
+//
+// \n \subsection strictlylowermatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar performance improvement can be gained when using a strictly lower triangular matrix
+// in a matrix/vector multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::StrictlyLowerMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ StrictlyLowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicVector<double,columnVector> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example, \b Blaze also exploits the structure of the matrix and approx. halves the
+// runtime of the multiplication. Also in case of matrix/vector multiplications the performance
+// improvement is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection strictlylowermatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a strictly lower triangular matrix on the right-hand side of an assignment
+// (i.e. for read access), which introduces absolutely no performance penalty, using a strictly
+// lower matrix on the left-hand side of an assignment (i.e. for write access) may introduce
+// additional overhead when it is assigned a matrix, which is not strictly lower triangular at
+// compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyLowerMatrix;
+
+ StrictlyLowerMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the strictly lower matrix; no performance penalty
+ C = A; // Assignment of a strictly lower matrix to another strictly lower matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a strictly lower matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not strictly lower matrix to a strictly lower matrix it
+// is necessary to check at runtime whether the general matrix is strictly lower in order to
+// guarantee the strictly lower triangular property of the strictly lower matrix. In case it
+// turns out to be strictly lower triangular, it is assigned as efficiently as possible, if it
+// is not, an exception is thrown. In order to prevent this runtime overhead it is therefore
+// generally advisable to assign strictly lower matrices to other strictly lower matrices.\n
+// In this context it is especially noteworthy that the addition, subtraction, and multiplication
+// of two strictly lower triangular matrices always results in another strictly lower matrix:
+
+ \code
+ StrictlyLowerMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a strictly lower matrix; no runtime overhead
+ C = A - B; // Results in a strictly lower matrix; no runtime overhead
+ C = A * B; // Results in a strictly lower matrix; no runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class StrictlyLowerMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/strictlylowermatrix/Dense.h b/src/cpu/blaze/math/adaptors/strictlylowermatrix/Dense.h
new file mode 100644
index 00000000..46f620e8
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/strictlylowermatrix/Dense.h
@@ -0,0 +1,2757 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/strictlylowermatrix/Dense.h
+// \brief StrictlyLowerMatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYLOWERMATRIX_DENSE_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYLOWERMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlylowermatrix/StrictlyLowerProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/Square.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StrictlyLowerMatrix for dense matrices.
+// \ingroup strictly_lower_matrix
+//
+// This specialization of StrictlyLowerMatrix adapts the class template to the requirements of
+// dense matrices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class StrictlyLowerMatrix<MT,SO,true>
+ : public DenseMatrix< StrictlyLowerMatrix<MT,SO,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef StrictlyLowerMatrix<MT,SO,true> This; //!< Type of this StrictlyLowerMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this StrictlyLowerMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef StrictlyLowerMatrix<OT,!SO,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef StrictlyUpperMatrix<TT,!SO,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef StrictlyLowerProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a StrictlyLowerMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other StrictlyLowerMatrix.
+ typedef StrictlyLowerMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense strictly lower matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef StrictlyLowerProxy<MT> PointerType; //!< Pointer return type.
+ typedef StrictlyLowerProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row-index of the iterator
+ , column_( column ) // The current column-index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) noexcept {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row-index of the iterator.
+ size_t column_; //!< The current column-index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StrictlyLowerMatrix();
+ template< typename A1 > explicit inline StrictlyLowerMatrix( const A1& a1 );
+ explicit inline StrictlyLowerMatrix( size_t n, const ElementType& init );
+
+ explicit inline StrictlyLowerMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline StrictlyLowerMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline StrictlyLowerMatrix( const Other (&array)[N][N] );
+
+ explicit inline StrictlyLowerMatrix( ElementType* ptr, size_t n );
+ explicit inline StrictlyLowerMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline StrictlyLowerMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline StrictlyLowerMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline StrictlyLowerMatrix( const StrictlyLowerMatrix& m );
+ inline StrictlyLowerMatrix( StrictlyLowerMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline StrictlyLowerMatrix& operator=( const ElementType& rhs );
+ inline StrictlyLowerMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline StrictlyLowerMatrix& operator=( const Other (&array)[N][N] );
+
+ inline StrictlyLowerMatrix& operator=( const StrictlyLowerMatrix& rhs );
+ inline StrictlyLowerMatrix& operator=( StrictlyLowerMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline StrictlyLowerMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, StrictlyLowerMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, StrictlyLowerMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+
+ template< typename Other > inline StrictlyLowerMatrix& scale( const Other& scalar );
+
+ inline void swap( StrictlyLowerMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ inline const MT construct( size_t n , TrueType );
+ inline const MT construct( const ElementType& value, FalseType );
+
+ template< typename MT2, bool SO2, typename T >
+ inline const MT construct( const Matrix<MT2,SO2>& m, T );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( StrictlyLowerMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for StrictlyLowerMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Single argument constructor for a strictly lower matrix.
+//
+// \param a1 The single constructor argument.
+// \exception std::invalid_argument Invalid setup of strictly lower matrix.
+//
+// This constructor constructs the strictly lower matrix based on the given argument and the
+// type of the underlying matrix \a MT:
+// - in case the given argument is a matrix, the strictly lower matrix is initialized as a copy
+// of the given matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// resizable, the given argument \a a1 specifies the number of rows and columns of the
+// strictly lower matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// a matrix with fixed size, the given argument \a a1 specifies the initial value of the
+// lower elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename A1 > // Type of the constructor argument
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( const A1& a1 )
+ : matrix_( construct( a1, typename IsResizable<MT>::Type() ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a \f$ n \times n \f$ matrix with initialized lower elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param init The initial value of the lower matrix elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( size_t n, const ElementType& init )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ for( size_t i=j+1UL; i<rows(); ++i )
+ matrix_(i,j) = init;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j )
+ matrix_(i,j) = init;
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of strictly lower matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the strictly
+// lower matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::StrictlyLowerMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A{ { },
+ { 2 },
+ { 4, 5 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isStrictlyLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all strictly lower matrix elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of strictly lower matrix.
+//
+// This constructor offers the option to directly initialize the elements of the strictly lower
+// matrix with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[16];
+ // ... Initialization of the dynamic array
+ blaze::StrictlyLowerMatrix< blaze::DynamicMatrix<int,rowMajor> > v( 4UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized accoring to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a n by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also,
+// in case the given array does not represent a strictly lower triangular matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isStrictlyLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all strictly lower matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of strictly lower matrix.
+//
+// This constructor offers the option to directly initialize the elements of the strictly lower
+// matrix with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { },
+ { 2 },
+ { 4, 5 } };
+ blaze::StrictlyLowerMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a strictly lower triangular
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isStrictlyLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a strictly lower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of strictly lower custom matrix.
+//
+// This constructor creates an unpadded strictly lower custom matrix of size \f$ n \times n \f$.
+// The construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a strictly lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded strictly lower custom matrices!
+// \note The strictly lower custom matrix does \b NOT take responsibility for the given array of
+// elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isStrictlyLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a strictly lower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of strictly lower custom matrix.
+//
+// This constructor creates a strictly lower custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a strictly lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isStrictlyLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a strictly lower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of strictly lower custom matrix.
+//
+// This constructor creates an unpadded strictly lower custom matrix of size \f$ n \times n \f$.
+// The construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a strictly lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded strictly lower custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isStrictlyLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a strictly lower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of strictly lower custom matrix.
+//
+// This constructor creates a strictly lower custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a strictly lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isStrictlyLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for StrictlyLowerMatrix.
+//
+// \param m The strictly lower matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( const StrictlyLowerMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for StrictlyLowerMatrix.
+//
+// \param m The strictly lower matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>::StrictlyLowerMatrix( StrictlyLowerMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::Reference
+ StrictlyLowerMatrix<MT,SO,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::ConstReference
+ StrictlyLowerMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::Reference
+ StrictlyLowerMatrix<MT,SO,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::ConstReference
+ StrictlyLowerMatrix<MT,SO,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the strictly lower matrix. Note
+// that you can NOT assume that all matrix elements lie adjacent to each other! The strictly
+// lower matrix may use techniques such as padding to improve the alignment of the data. Whereas
+// the number of elements within a row/column are given by the \c rows() and \c columns() member
+// functions, respectively, the total number of elements including padding is given by the
+// \c spacing() member function.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::ConstPointer
+ StrictlyLowerMatrix<MT,SO,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::ConstPointer
+ StrictlyLowerMatrix<MT,SO,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly lower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::Iterator
+ StrictlyLowerMatrix<MT,SO,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly lower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly lower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly lower matrix adapts a \a rowMajor dense matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor dense
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::Iterator
+ StrictlyLowerMatrix<MT,SO,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly lower matrix adapts a \a rowMajor dense matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor dense
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly lower matrix adapts a \a rowMajor dense matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor dense
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyLowerMatrix<MT,SO,true>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all lower matrix elements.
+//
+// \param rhs Scalar value to be assigned to the lower matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>&
+ StrictlyLowerMatrix<MT,SO,true>::operator=( const ElementType& rhs )
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=j+1UL; i<rows(); ++i )
+ matrix_(i,j) = rhs;
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i )
+ for( size_t j=0UL; j<i; ++j )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the strictly
+// lower matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::StrictlyLowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = { { },
+ { 2 },
+ { 4, 5 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>&
+ StrictlyLowerMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all strictly lower matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// This assignment operator offers the option to directly set all elements of the strictly lower
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { },
+ { 2 },
+ { 4, 5 } };
+ blaze::StrictlyLowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a strictly lower triangular matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline StrictlyLowerMatrix<MT,SO,true>&
+ StrictlyLowerMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for StrictlyLowerMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>&
+ StrictlyLowerMatrix<MT,SO,true>::operator=( const StrictlyLowerMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for StrictlyLowerMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyLowerMatrix<MT,SO,true>&
+ StrictlyLowerMatrix<MT,SO,true>::operator=( StrictlyLowerMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// strictly lower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,true>& >
+ StrictlyLowerMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// strictly lower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,true>& >
+ StrictlyLowerMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a strictly
+// lower matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is
+// not a strictly lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,true>& >
+ StrictlyLowerMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a strictly
+// lower matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is
+// not a strictly lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,true>& >
+ StrictlyLowerMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a strictly
+// lower matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is not
+// a strictly lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,true>& >
+ StrictlyLowerMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a strictly
+// lower matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is not
+// a strictly lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,true>& >
+ StrictlyLowerMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a strictly lower
+// matrix. In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline StrictlyLowerMatrix<MT,SO,true>&
+ StrictlyLowerMatrix<MT,SO,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, StrictlyLowerMatrix<MT,SO,true> >&
+ StrictlyLowerMatrix<MT,SO,true>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, StrictlyLowerMatrix<MT,SO,true> >&
+ StrictlyLowerMatrix<MT,SO,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyLowerMatrix<MT,SO,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyLowerMatrix<MT,SO,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the total
+// number of elements of a row/column. In case the strictly lower matrix adapts a \a rowMajor
+// dense matrix the function returns the spacing between two rows, in case it adapts a
+// \a columnMajor dense matrix the function returns the spacing between two columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyLowerMatrix<MT,SO,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyLowerMatrix<MT,SO,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the strictly
+// lower matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i,
+// in case it adapts a \a columnMajor dense matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyLowerMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the strictly lower matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyLowerMatrix<MT,SO,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the strictly lower matrix adapts a \a rowMajor dense matrix the function returns the
+// number of non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix
+// the function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyLowerMatrix<MT,SO,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyLowerMatrix<MT,SO,true>::reset()
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=j+1UL; i<rows(); ++i )
+ clear( matrix_(i,j) );
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i )
+ for( size_t j=0UL; j<i; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyLowerMatrix<MT,SO,true>::reset( size_t i )
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=i+1UL; j<rows(); ++j )
+ clear( matrix_(j,i) );
+ }
+ else {
+ for( size_t j=0UL; j<i; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the strictly lower matrix.
+//
+// \return void
+//
+// This function clears the matrix and returns it to its default state. The function has the same
+// effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable matrix
+// (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set to 0,
+// whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will be
+// reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyLowerMatrix<MT,SO,true>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the strictly lower matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the strictly lower matrix adapts a resizable matrix, this function resizes the matrix
+// using the given size to \f$ n \times n \f$. During this operation, new dynamic memory may
+// be allocated in case the capacity of the matrix is too small. Note that this function may
+// invalidate all existing views (submatrices, rows, columns, ...) on the matrix if it is used to
+// shrink the matrix. Additionally, the resize operation potentially changes all matrix elements.
+// In order to preserve the old matrix values, the \a preserve flag can be set to \a true. Also
+// note that in case the size of the matrix is increased, only the new elements on the diagonal
+// and in the upper part of the matrix are initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 0 & 0 \\
+ 2 & 1 & 0 \\
+ 3 & 4 & 1 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 0 & 0 & 0 \\
+ 2 & 1 & 0 & 0 \\
+ 3 & 4 & 1 & 0 \\
+ x & x & x & 1 \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void StrictlyLowerMatrix<MT,SO,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize )
+ {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, 0UL, oldsize, n, increment ).reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyLowerMatrix<MT,SO,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the strictly lower matrix.
+// \return void
+//
+// This function increases the capacity of the strictly lower matrix to at least \a elements
+// elements. The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyLowerMatrix<MT,SO,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the scalar value
+inline StrictlyLowerMatrix<MT,SO,true>&
+ StrictlyLowerMatrix<MT,SO,true>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyLowerMatrix<MT,SO,true>::swap( StrictlyLowerMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a strictly lower triangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a strictly lower
+// triangular matrix with fixed-size adapted matrix of type \a MT. Note that this function
+// can only be called in case the adapted dense matrix is a fixed-size matrix (as for instance
+// StaticMatrix). The attempt to call this function in case the adapted matrix is resizable
+// matrix will result in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t StrictlyLowerMatrix<MT,SO,true>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a strictly lower triangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a strictly lower
+// triangular matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t StrictlyLowerMatrix<MT,SO,true>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n - 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the strictly lower matrix are intact.
+//
+// \return \a true in case the strictly lower matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the strictly lower matrix are intact, i.e. if
+// its state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool StrictlyLowerMatrix<MT,SO,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isStrictlyLower( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool StrictlyLowerMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool StrictlyLowerMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool StrictlyLowerMatrix<MT,SO,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool StrictlyLowerMatrix<MT,SO,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the strictly lower matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename StrictlyLowerMatrix<MT,SO,true>::SIMDType
+ StrictlyLowerMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the strictly lower
+// matrix. The row index must be smaller than the number of rows and the column index must be
+// smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename StrictlyLowerMatrix<MT,SO,true>::SIMDType
+ StrictlyLowerMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the strictly lower
+// matrix. The row index must be smaller than the number of rows and the column index must be
+// smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename StrictlyLowerMatrix<MT,SO,true>::SIMDType
+ StrictlyLowerMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a resizable matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT StrictlyLowerMatrix<MT,SO,true>::construct( size_t n, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ return MT( n, n, ElementType() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a fixed-size matrix with homogeneously initialized lower elements.
+//
+// \param init The initial value of the lower matrix elements.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT StrictlyLowerMatrix<MT,SO,true>::construct( const ElementType& init, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SQUARE( MT );
+
+ MT tmp;
+
+ if( SO ) {
+ for( size_t j=0UL; j<tmp.columns(); ++j ) {
+ for( size_t i=j+1UL; i<tmp.rows(); ++i )
+ tmp(i,j) = init;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<tmp.rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j )
+ tmp(i,j) = init;
+ }
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a matrix as a copy from another matrix.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of strictly lower matrix.
+// \return The newly constructed matrix.
+//
+// In case the given matrix is not a strictly lower matrix, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT StrictlyLowerMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ const MT tmp( ~m );
+
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( tmp ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/strictlylowermatrix/Sparse.h b/src/cpu/blaze/math/adaptors/strictlylowermatrix/Sparse.h
new file mode 100644
index 00000000..4642c636
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/strictlylowermatrix/Sparse.h
@@ -0,0 +1,2112 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/strictlylowermatrix/Sparse.h
+// \brief StrictlyLowerMatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYLOWERMATRIX_SPARSE_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYLOWERMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlylowermatrix/StrictlyLowerProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StrictlyLowerMatrix for sparse matrices.
+// \ingroup strictly_lower_matrix
+//
+// This specialization of StrictlyLowerMatrix adapts the class template to the requirements of sparse
+// matrices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class StrictlyLowerMatrix<MT,SO,false>
+ : public SparseMatrix< StrictlyLowerMatrix<MT,SO,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef StrictlyLowerMatrix<MT,SO,false> This; //!< Type of this StrictlyLowerMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this StrictlyLowerMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef StrictlyLowerMatrix<OT,!SO,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef StrictlyUpperMatrix<TT,!SO,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef StrictlyLowerProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a StrictlyLowerMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other StrictlyLowerMatrix.
+ typedef StrictlyLowerMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StrictlyLowerMatrix();
+ explicit inline StrictlyLowerMatrix( size_t n );
+ explicit inline StrictlyLowerMatrix( size_t n, size_t nonzeros );
+ explicit inline StrictlyLowerMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline StrictlyLowerMatrix( const StrictlyLowerMatrix& m );
+ inline StrictlyLowerMatrix( StrictlyLowerMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline StrictlyLowerMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline StrictlyLowerMatrix& operator=( const StrictlyLowerMatrix& rhs );
+ inline StrictlyLowerMatrix& operator=( StrictlyLowerMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline StrictlyLowerMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, StrictlyLowerMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, StrictlyLowerMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+
+ template< typename Other > inline StrictlyLowerMatrix& scale( const Other& scalar );
+ template< typename Other > inline StrictlyLowerMatrix& scaleDiagonal( Other scale );
+
+ inline void swap( StrictlyLowerMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void resetUpper();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( StrictlyLowerMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for StrictlyLowerMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyLowerMatrix<MT,SO,false>::StrictlyLowerMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized as identity matrix and has no additional free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyLowerMatrix<MT,SO,false>::StrictlyLowerMatrix( size_t n )
+ : matrix_( n, n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized as identity matrix and will have at least the capacity for
+// \a nonzeros non-zero elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyLowerMatrix<MT,SO,false>::StrictlyLowerMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, max( nonzeros, n ) ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+// \exception std::invalid_argument Invalid capacity specification.
+//
+// The matrix is initialized as identity matrix and will have the specified capacity in each
+// row/column. Note that since the matrix is initialized as \f$ n \times n \f$ identity matrix
+// the given vector must have at least \a n elements, all of which must not be 0. If the number
+// of non-zero elements of any row/column is specified as 0, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyLowerMatrix<MT,SO,false>::StrictlyLowerMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for StrictlyLowerMatrix.
+//
+// \param m The strictly lower matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyLowerMatrix<MT,SO,false>::StrictlyLowerMatrix( const StrictlyLowerMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for StrictlyLowerMatrix.
+//
+// \param m The strictly lower matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyLowerMatrix<MT,SO,false>::StrictlyLowerMatrix( StrictlyLowerMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of strictly lower matrix.
+//
+// This constructor initializes the strictly lower matrix as a copy of the given matrix. In
+// case the given matrix is not an strictly lower matrix, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline StrictlyLowerMatrix<MT,SO,false>::StrictlyLowerMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( ~m ) // The adapted sparse matrix
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( matrix_ ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" );
+ }
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Reference
+ StrictlyLowerMatrix<MT,SO,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstReference
+ StrictlyLowerMatrix<MT,SO,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Reference
+ StrictlyLowerMatrix<MT,SO,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstReference
+ StrictlyLowerMatrix<MT,SO,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::begin( size_t i )
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,false>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly lower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,false>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly lower matrix adapts a \a rowMajor sparse matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor sparse
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::end( size_t i )
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly lower matrix adapts a \a rowMajor sparse matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor sparse
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,false>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly lower matrix adapts a \a rowMajor sparse matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor sparse
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,false>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for StrictlyLowerMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyLowerMatrix<MT,SO,false>&
+ StrictlyLowerMatrix<MT,SO,false>::operator=( const StrictlyLowerMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for StrictlyLowerMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyLowerMatrix<MT,SO,false>&
+ StrictlyLowerMatrix<MT,SO,false>::operator=( StrictlyLowerMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// strictly lower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,false>& >
+ StrictlyLowerMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// strictly lower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,false>& >
+ StrictlyLowerMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a strictly
+// lower matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is
+// not a strictly lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,false>& >
+ StrictlyLowerMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a strictly
+// lower matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is
+// not a strictly lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,false>& >
+ StrictlyLowerMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a strictly
+// lower matrix, i.e. the given matrix must be a strictly lower matrix. In case the the result is
+// not a strictly lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,false>& >
+ StrictlyLowerMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly lower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a strictly
+// lower matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is not
+// a strictly lower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyLowerMatrix<MT,SO,false>& >
+ StrictlyLowerMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a strictly lower
+// matrix. In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline StrictlyLowerMatrix<MT,SO,false>&
+ StrictlyLowerMatrix<MT,SO,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, StrictlyLowerMatrix<MT,SO,false> >&
+ StrictlyLowerMatrix<MT,SO,false>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, StrictlyLowerMatrix<MT,SO,false> >&
+ StrictlyLowerMatrix<MT,SO,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyLowerMatrix<MT,SO,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyLowerMatrix<MT,SO,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyLowerMatrix<MT,SO,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the strictly
+// lower matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i,
+// in case it adapts a \a columnMajor sparse matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyLowerMatrix<MT,SO,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the strictly lower matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyLowerMatrix<MT,SO,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the strictly lower matrix adapts a \a rowMajor sparse matrix the function returns
+// the number of non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse
+// matrix the function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyLowerMatrix<MT,SO,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::reset()
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ matrix_.erase( j, matrix_.lowerBound(j+1UL,j), matrix_.end(j) );
+ }
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i ) {
+ matrix_.erase( i, matrix_.begin(i), matrix_.lowerBound(i,i) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::reset( size_t i )
+{
+ if( SO ) {
+ matrix_.erase( i, matrix_.lowerBound(i+1UL,i), matrix_.end(i) );
+ }
+ else {
+ matrix_.erase( i, matrix_.begin(i), matrix_.lowerBound(i,i) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the strictly lower matrix.
+//
+// \return void
+//
+// This function clears the strictly lower matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the strictly lower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to diagonal or upper matrix element.
+//
+// This function sets the value of an element of the strictly lower matrix. In case the matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted. The attempt to set an element on the
+// diagonal or in the upper part of the matrix (i.e. above the diagonal) will result in a
+// \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ if( i <= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or upper matrix element" );
+ }
+
+ return matrix_.set( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the strictly lower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+// \exception std::invalid_argument Invalid access to diagonal or upper matrix element.
+//
+// This function inserts a new element into the strictly lower matrix. However, duplicate elements
+// are not allowed. In case the matrix already contains an element with row index \a i and column
+// index \a j, a \a std::invalid_argument exception is thrown. Also, the attempt to insert an
+// element on the diagonal or in the upper part of the matrix (i.e. above the diagonal) will
+// result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ if( i <= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or upper matrix element" );
+ }
+
+ return matrix_.insert( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the strictly lower matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the strictly lower matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::erase( size_t i, size_t j )
+{
+ matrix_.erase( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the strictly lower matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the strictly lower matrix. In case the strictly lower
+// matrix adapts a \a rowMajor sparse matrix the function erases an element from row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function erases an element from column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::erase( size_t i, Iterator pos )
+{
+ return matrix_.erase( i, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the strictly lower matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the strictly lower matrix. In case the matrix
+// adapts a \a rowMajor sparse matrix the function erases a range of elements from row \a i, in
+// case it adapts a \a columnMajor matrix the function erases a range of elements from column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ return matrix_.erase( i, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the strictly lower matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void StrictlyLowerMatrix<MT,SO,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly lower matrix detected" );
+
+ matrix_.resize( n, n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the strictly lower matrix.
+//
+// \param nonzeros The new minimum capacity of the strictly lower matrix.
+// \return void
+//
+// This function increases the capacity of the strictly lower matrix to at least \a nonzeros
+// elements. The current values of the matrix elements and the individual capacities of the
+// matrix rows are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the strictly lower matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the strictly lower matrix to at
+// least \a nonzeros elements. The current values of the strictly lower matrix and all other
+// individual row/column capacities are preserved. In case the strictly lower matrix adapts a
+// \a rowMajor sparse matrix the function reserves capacity for row \a i. In case it adapts a
+// \a columnMajor the function reserves capacity for column \a i. The index has to be in the
+// range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the strictly lower matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline StrictlyLowerMatrix<MT,SO,false>&
+ StrictlyLowerMatrix<MT,SO,false>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the lower matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the lower matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline StrictlyLowerMatrix<MT,SO,false>&
+ StrictlyLowerMatrix<MT,SO,false>::scaleDiagonal( Other scalar )
+{
+ matrix_.scaleDiagonal( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::swap( StrictlyLowerMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a strictly lower triangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a strictly lower
+// triangular matrix with fixed-size adapted matrix of type \a MT. Note that this function can
+// only be called in case the adapted dense matrix is a fixed-size matrix. The attempt to call
+// this function in case the adapted matrix is resizable matrix will result in a compile time
+// error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t StrictlyLowerMatrix<MT,SO,false>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a strictly lower triangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a strictly lower
+// triangular matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t StrictlyLowerMatrix<MT,SO,false>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n - 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the complete upper part of the matrix to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::resetUpper()
+{
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j )
+ matrix_.erase( j, matrix_.begin( j ), matrix_.lowerBound( j, j ) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ matrix_.erase( i, matrix_.upperBound( i, i ), matrix_.end( i ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the strictly
+// lower matrix. It specifically searches for the element with row index \a i and column index
+// \a j. In case the element is found, the function returns an row/column iterator to the
+// element. Otherwise an iterator just past the last non-zero element of row \a i or column
+// \a j (the end() iterator) is returned. Note that the returned unilower matrix iterator is
+// subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::find( size_t i, size_t j )
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the strictly
+// lower matrix. It specifically searches for the element with row index \a i and column index
+// \a j. In case the element is found, the function returns an row/column iterator to the
+// element. Otherwise an iterator just past the last non-zero element of row \a i or column
+// \a j (the end() iterator) is returned. Note that the returned strictly lower matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,false>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned strictly lower
+// matrix iterator is subject to invalidation due to inserting operations via the function
+// call operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::lowerBound( size_t i, size_t j )
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned strictly lower
+// matrix iterator is subject to invalidation due to inserting operations via the function
+// call operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,false>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned strictly lower
+// matrix iterator is subject to invalidation due to inserting operations via the function
+// call operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::Iterator
+ StrictlyLowerMatrix<MT,SO,false>::upperBound( size_t i, size_t j )
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned strictly lower
+// matrix iterator is subject to invalidation due to inserting operations via the function
+// call operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyLowerMatrix<MT,SO,false>::ConstIterator
+ StrictlyLowerMatrix<MT,SO,false>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the strictly lower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to diagonal or upper matrix element.
+//
+// This function provides a very efficient way to fill a sparse matrix with elements. It appends
+// a new element to the end of the specified row/column without any additional memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (newly created) sparse matrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StrictlyLowerMatrix;
+ using blaze::columnMajor;
+
+ StrictlyLowerMatrix< CompressedMatrix<double,columnMajor> > A( 4 );
+
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 1, 0, 1.0 ); // Appending the value 1 in column 0 with row index 1
+ A.finalize( 0 ); // Finalizing column 0
+ A.append( 2, 1, 2.0 ); // Appending the value 2 in column 1 with row index 2
+ A.finalize( 1 ); // Finalizing column 1
+ A.append( 3, 2, 3.0 ); // Appending the value 3 in column 2 with row index 3
+ A.finalize( 2 ); // Finalizing column 2
+ A.finalize( 3 ); // Finalizing the empty column 3
+ \endcode
+
+// Note that although append() does not allocate new memory it still invalidates all iterators
+// returned by the end() functions! Also note that the attempt to append an element within the
+// upper part of the matrix (i.e. above the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( i <= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or upper matrix element" );
+ }
+
+ matrix_.append( i, j, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyLowerMatrix<MT,SO,false>::finalize( size_t i )
+{
+ matrix_.finalize( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the strictly lower matrix are intact.
+//
+// \return \a true in case the strictly lower matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the strictly lower matrix are intact, i.e. if
+// its state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool StrictlyLowerMatrix<MT,SO,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isStrictlyLower( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool StrictlyLowerMatrix<MT,SO,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool StrictlyLowerMatrix<MT,SO,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool StrictlyLowerMatrix<MT,SO,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/strictlylowermatrix/StrictlyLowerProxy.h b/src/cpu/blaze/math/adaptors/strictlylowermatrix/StrictlyLowerProxy.h
new file mode 100644
index 00000000..89e0d149
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/strictlylowermatrix/StrictlyLowerProxy.h
@@ -0,0 +1,670 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/strictlylowermatrix/StrictlyLowerProxy.h
+// \brief Header file for the StrictlyLowerProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_LOWERMATRIX_STRICTLYLOWERPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_LOWERMATRIX_STRICTLYLOWERPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/typetraits/AddConst.h>
+#include <blaze/util/typetraits/AddReference.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for strictly lower triangular matrices.
+// \ingroup strictly_lower_matrix
+//
+// The StrictlyLowerProxy provides controlled access to the elements of a non-const strictly lower
+// triangular matrix. It guarantees that the strictly lower matrix invariant is not violated, i.e.
+// that elements on the diagonal and in the upper part of the matrix remain 0. The following
+// example illustrates this by means of a \f$ 3 \times 3 \f$ dense strictly lower triangular
+// matrix:
+
+ \code
+ // Creating a 3x3 strictly lower triangular dense matrix
+ blaze::StrictlyLowerMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(0,1) = -2; // ( 0 0 0 )
+ A(2,1) = 3; // => A = ( -2 0 0 )
+ A(2,2) = 5; // ( 3 5 0 )
+
+ A(1,1) = 4; // Invalid assignment to diagonal matrix element; results in an exception!
+ A(0,2) = 7; // Invalid assignment to upper matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class StrictlyLowerProxy : public Proxy< StrictlyLowerProxy<MT>, ElementType_<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Reference type of the underlying matrix type.
+ typedef AddConst_< Reference_<MT> > ReferenceType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+ typedef AddReference_<ReferenceType> RawReference; //!< Reference-to-non-const to the represented element.
+ typedef const RepresentedType& ConstReference; //!< Reference-to-const to the represented element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StrictlyLowerProxy( MT& matrix, size_t row, size_t column );
+ inline StrictlyLowerProxy( const StrictlyLowerProxy& ulp );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline const StrictlyLowerProxy& operator=( const StrictlyLowerProxy& ulp ) const;
+
+ template< typename T >
+ inline const StrictlyLowerProxy& operator=( initializer_list<T> list ) const;
+
+ template< typename T >
+ inline const StrictlyLowerProxy& operator=( initializer_list< initializer_list<T> > list ) const;
+
+ template< typename T > inline const StrictlyLowerProxy& operator= ( const T& value ) const;
+ template< typename T > inline const StrictlyLowerProxy& operator+=( const T& value ) const;
+ template< typename T > inline const StrictlyLowerProxy& operator-=( const T& value ) const;
+ template< typename T > inline const StrictlyLowerProxy& operator*=( const T& value ) const;
+ template< typename T > inline const StrictlyLowerProxy& operator/=( const T& value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline RawReference get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator ConstReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ ReferenceType value_; //!< Reference to the accessed matrix element.
+ const bool restricted_; //!< Access flag for the accessed matrix element.
+ /*!< The flag indicates if access to the matrix element is
+ restricted. It is \a true in case the proxy represents an
+ element on the diagonal or in the upper part of the matrix. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for an StrictlyLowerProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline StrictlyLowerProxy<MT>::StrictlyLowerProxy( MT& matrix, size_t row, size_t column )
+ : value_ ( matrix( row, column ) ) // Reference to the accessed matrix element
+ , restricted_( row <= column ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for LowerProxy.
+//
+// \param slp Proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline StrictlyLowerProxy<MT>::StrictlyLowerProxy( const StrictlyLowerProxy& slp )
+ : value_ ( slp.value_ ) // Reference to the accessed matrix element
+ , restricted_( slp.restricted_ ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for StrictlyLowerProxy.
+//
+// \param slp Proxy to be copied.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline const StrictlyLowerProxy<MT>&
+ StrictlyLowerProxy<MT>::operator=( const StrictlyLowerProxy& slp ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ = slp.value_;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyLowerProxy<MT>&
+ StrictlyLowerProxy<MT>::operator=( initializer_list<T> list ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyLowerProxy<MT>&
+ StrictlyLowerProxy<MT>::operator=( initializer_list< initializer_list<T> > list ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyLowerProxy<MT>& StrictlyLowerProxy<MT>::operator=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyLowerProxy<MT>& StrictlyLowerProxy<MT>::operator+=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyLowerProxy<MT>& StrictlyLowerProxy<MT>::operator-=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyLowerProxy<MT>& StrictlyLowerProxy<MT>::operator*=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyLowerProxy<MT>& StrictlyLowerProxy<MT>::operator/=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename StrictlyLowerProxy<MT>::RawReference StrictlyLowerProxy<MT>::get() const noexcept
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted matrix element..
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool StrictlyLowerProxy<MT>::isRestricted() const noexcept
+{
+ return restricted_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Reference-to-const to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline StrictlyLowerProxy<MT>::operator ConstReference() const noexcept
+{
+ return static_cast<ConstReference>( value_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name StrictlyLowerProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const StrictlyLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const StrictlyLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const StrictlyLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const StrictlyLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const StrictlyLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const StrictlyLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const StrictlyLowerProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup strictly_lower_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const StrictlyLowerProxy<MT>& proxy )
+{
+ using blaze::reset;
+
+ reset( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup strictly_lower_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const StrictlyLowerProxy<MT>& proxy )
+{
+ using blaze::clear;
+
+ clear( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup strictly_lower_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const StrictlyLowerProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup strictly_lower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const StrictlyLowerProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup strictly_lower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const StrictlyLowerProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup strictly_lower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const StrictlyLowerProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup strictly_lower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const StrictlyLowerProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h
new file mode 100644
index 00000000..175a2b99
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h
@@ -0,0 +1,560 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the StrictlyUpperMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup strictly_upper_matrix StrictlyUpperMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for strictly upper triangular \f$ N \times N \f$ matrices.
+// \ingroup strictly_upper_matrix
+//
+// \section strictlyuppermatrix_general General
+//
+// The StrictlyUpperMatrix class template is an adapter for existing dense and sparse matrix
+// types. It inherits the properties and the interface of the given matrix type \a MT and extends
+// it by enforcing the additional invariant that all diagonal matrix elements and all matrix
+// elements below the diagonal are 0 (strictly upper triangular matrix). The type of the adapted
+// matrix can be specified via the first template parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF >
+ class StrictlyUpperMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. StricltyUpperMatrix can be used
+// with any non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse
+// matrix type. Note that the given matrix type must be either resizable (as for instance
+// HybridMatrix or DynamicMatrix) or must be square at compile time (as for instance
+// StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+// The following examples give an impression of several possible strictly upper triangular matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense strictly upper matrix with static memory
+ blaze::StrictlyUpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense strictly upper matrix based on HybridMatrix
+ blaze::StrictlyUpperMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense strictly upper matrix based on DynamicMatrix
+ blaze::StrictlyUpperMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense strictly upper matrix based on CustomMatrix
+ blaze::StrictlyUpperMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision strictly upper matrix
+ blaze::StrictlyUpperMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of a strictly upper triangular matrix is depending on the storage order of
+// the adapted matrix type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e.
+// is specified as blaze::rowMajor), the strictly upper matrix will also be a row-major matrix.
+// Otherwise, if the adapted matrix is column-major (i.e. is specified as blaze::columnMajor),
+// the strictly upper matrix will also be a column-major matrix.
+//
+//
+// \n \section strictlyuppermatrix_special_properties Special Properties of Strictly Upper Triangular Matrices
+//
+// A strictly upper triangular matrix is used exactly like a matrix of the underlying, adapted
+// matrix type \a MT. It also provides (nearly) the same interface as the underlying matrix type.
+// However, there are some important exceptions resulting from the strictly upper triangular
+// matrix constraint:
+//
+// -# <b>\ref strictlyuppermatrix_square</b>
+// -# <b>\ref strictlyuppermatrix_strictlyupper</b>
+// -# <b>\ref strictlyuppermatrix_initialization</b>
+// -# <b>\ref strictlyuppermatrix_storage</b>
+//
+// \n \subsection strictlyuppermatrix_square Strictly Upper Triangular Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 strictly upper dynamic matrix
+ StrictlyUpperMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 strictly upper static matrix
+ StrictlyUpperMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ StrictlyUpperMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection strictlyuppermatrix_strictlyupper The Strictly Upper triangular Matrix Property is Always Enforced!
+//
+// This means that it is only allowed to modify elements in the upper part of the matrix, but not
+// the elements on the diagonal or in the lower part of the matrix. Also, it is only possible to
+// assign matrices that are strictly upper triangular matrices themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::rowMajor;
+
+ typedef StrictlyUpperMatrix< CompressedMatrix<double,rowMajor> > CompressedStrictlyUpper;
+
+ // Default constructed, row-major 3x3 strictly upper compressed matrix
+ CompressedStrictlyUpper A( 3 );
+
+ // Initializing elements via the function call operator
+ A(0,0) = 9.0; // Throws an exception; invalid modification of diagonal element
+ A(0,2) = 2.0; // Initialization of the upper element (0,2)
+ A(2,1) = 9.0; // Throws an exception; invalid modification of lower element
+
+ // Inserting elements via the insert() function
+ A.insert( 0, 1, 3.0 ); // Inserting the upper element (0,1)
+ A.insert( 1, 1, 9.0 ); // Throws an exception; invalid insertion of diagonal element
+ A.insert( 2, 0, 9.0 ); // Throws an exception; invalid insertion of lower element
+
+ // Appending an element via the append() function
+ A.reserve( 1, 1 ); // Reserving enough capacity in row 1
+ A.append( 1, 2, 5.0 ); // Appending the upper element (1,2)
+ A.append( 2, 1, 9.0 ); // Throws an exception; appending an element in the lower part
+
+ // Access via a non-const iterator
+ CompressedStrictlyUpper::Iterator it = A.begin(0);
+ *it = 7.0; // Modifies the upper element (0,1)
+ ++it;
+ *it = 8.0; // Modifies the upper element (0,2)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Throws an exception; invalid erasure of the diagonal element (0,0)
+ A.erase( 0, 2 ); // Erasing the upper element (0,2)
+
+ // Construction from a strictly upper dense matrix
+ StaticMatrix<double,3UL,3UL> B( { { 0.0, 8.0, -2.0 },
+ { 0.0, 0.0, -1.0 },
+ { 0.0, 0.0, 0.0 } } );
+
+ StrictlyUpperMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a general dense matrix
+ StaticMatrix<double,3UL,3UL> D( { { 3.0, 8.0, -2.0 },
+ { 0.0, 0.0, -1.0 },
+ { -2.0, 0.0, 4.0 } } );
+
+ C = D; // Throws an exception; strictly upper triangular matrix invariant would be violated!
+ \endcode
+
+// The strictly upper matrix property is also enforced for strictly upper custom matrices: In case
+// the given array of elements does not represent a strictly upper matrix, a \a std::invalid_argument
+// exception is thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef StrictlyUpperMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomStrictlyUpper;
+
+ // Creating a 3x3 strictly upper custom matrix from a properly initialized array
+ double array[9] = { 0.0, 1.0, 2.0,
+ 0.0, 0.0, 3.0,
+ 0.0, 0.0, 0.0 };
+ CustomStrictlyUpper A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 strictly upper custom matrix from an uninitialized array
+ CustomStrictlyUpper B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the strictly upper matrix property is enforced for views (rows, columns, submatrices,
+// ...) on the strictly upper matrix. The following example demonstrates that modifying the
+// elements of an entire row and submatrix of a strictly upper matrix only affects the upper
+// matrix elements:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyUpperMatrix;
+
+ // Setup of the upper matrix
+ //
+ // ( 0 2 0 4 )
+ // A = ( 0 0 3 0 )
+ // ( 0 0 0 5 )
+ // ( 0 0 0 0 )
+ //
+ StrictlyUpperMatrix< DynamicMatrix<int> > A( 4 );
+ A(0,1) = 2;
+ A(0,3) = 4;
+ A(1,2) = 3;
+ A(2,3) = 5;
+
+ // Setting the upper elements in the 1st row to 9 results in the matrix
+ //
+ // ( 0 1 0 4 )
+ // A = ( 0 0 9 9 )
+ // ( 0 0 0 5 )
+ // ( 0 0 0 0 )
+ //
+ row( A, 1 ) = 9;
+
+ // Setting the upper elements in the 1st and 2nd column to 7 results in
+ //
+ // ( 0 7 7 4 )
+ // A = ( 0 0 7 9 )
+ // ( 0 0 0 5 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A, 0, 1, 4, 2 ) = 7;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to rows/columns and submatrices of
+// strictly upper matrices. Since only upper elements may be modified the matrix to be assigned
+// must be structured such that the strictly upper triangular matrix invariant of the strictly
+// upper matrix is preserved. Otherwise a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::rowVector;
+
+ // Setup of two default 4x4 upper matrices
+ StrictlyUpperMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of a 4-dimensional vector
+ //
+ // v = ( 0 0 2 3 )
+ //
+ DynamicVector<int,rowVector> v( 4, 0 );
+ v[2] = 2;
+ v[3] = 3;
+
+ // OK: Assigning v to the 1st row of A1 preserves the upper matrix invariant
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 0 2 3 )
+ // ( 0 0 0 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 1 ) = v; // OK
+
+ // Error: Assigning v to the 2nd row of A1 violates the strictly upper matrix invariant! The
+ // element marked with X cannot be assigned and triggers an exception.
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 0 2 3 )
+ // ( 0 0 X 3 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 2 ) = v; // Assignment throws an exception!
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 7 8 )
+ // B = ( 0 9 )
+ // ( 0 0 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL, 0 );
+ B(0,0) = 7;
+ B(0,1) = 8;
+ B(1,1) = 9;
+
+ // OK: Assigning B to a submatrix of A2 such that the invariant can be preserved
+ //
+ // ( 0 7 8 0 )
+ // A2 = ( 0 0 9 0 )
+ // ( 0 0 0 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the upper matrix invariant cannot be
+ // preserved! The elements marked with X cannot be assigned without violating the invariant!
+ //
+ // ( X 8 8 0 )
+ // A2 = ( 0 X 9 0 )
+ // ( 0 0 0 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 0UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection strictlyuppermatrix_initialization The Diagonal and Lower Elements of a Dense Strictly Upper Triangular Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency during the creation of a dense strictly
+// upper matrix this initialization is important since otherwise the strictly upper triangular
+// matrix property of dense strictly upper matrices would not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyUpperMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // 5x5 row-major strictly upper dynamic matrix with default initialized lower matrix
+ StrictlyUpperMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \subsection strictlyuppermatrix_storage Dense Strictly Upper Matrices Also Store the Diagonal and Lower Elements!
+//
+// It is important to note that dense strictly upper matrices store all elements, including the
+// elements on the diagonal and in the lower part of the matrix, and therefore don't provide any
+// kind of memory reduction! There are two main reasons for this: First, storing also the diagonal
+// and lower elements guarantees maximum performance for many algorithms that perform vectorized
+// operations on the upper matrix, which is especially true for small dense matrices. Second,
+// conceptually the StrictlyUpperMatrix adaptor merely restricts the interface to the matrix type
+// \a MT and does not change the data layout or the underlying matrix type.
+//
+//
+// \n \section strictlyuppermatrix_arithmetic_operations Arithmetic Operations
+//
+// An StrictlyUpperMatrix matrix can participate in numerical operations in any way any other dense
+// or sparse matrix can participate. It can also be combined with any other dense or sparse vector
+// or matrix. The following code example gives an impression of the use of StrictlyUpperMatrix
+// within arithmetic operations:
+
+ \code
+ using blaze::StrictlyUpperMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ StrictlyUpperMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ StrictlyUpperMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ StrictlyUpperMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > E;
+ StrictlyUpperMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major strictly upper matrix
+ F = A - C; // Matrix subtraction and assignment to a column-major strictly upper matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section strictlyuppermatrix_block_structured Block-Structured Strictly Upper Matrices
+//
+// It is also possible to use block-structured strictly upper matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticMatrix;
+ using blaze::StrictlyUpperMatrix;
+
+ // Definition of a 5x5 block-structured strictly upper matrix based on CompressedMatrix
+ StrictlyUpperMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > A( 5 );
+ \endcode
+
+// Also in this case the strictly upper matrix invariant is enforced, i.e. it is not possible to
+// manipulate elements in the lower part of the matrix:
+
+ \code
+ const StaticMatrix<int,3UL,3UL> B( { { 1, -4, 5 },
+ { 6, 8, -3 },
+ { 2, -1, 2 } } )
+
+ A.insert( 2, 4, B ); // Inserting the elements (2,4)
+ A(4,2)(1,1) = -5; // Invalid manipulation of lower matrix element; Results in an exception
+ \endcode
+
+// \n \section strictlyuppermatrix_performance Performance Considerations
+//
+// The \b Blaze library tries to exploit the properties of strictly upper triangular matrices
+// whenever and wherever possible. Thus using a strictly upper triangular matrix instead of
+// a general matrix can result in a considerable performance improvement. However, there are
+// also situations when using a strictly upper matrix introduces some overhead. The following
+// examples demonstrate several common situations where strictly upper matrices can positively
+// or negatively impact performance.
+//
+// \n \subsection strictlyuppermatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is strictly upper triangular, \b Blaze
+// can exploit the fact that the diagonal and the lower part of the matrix contains only default
+// elements and restrict the algorithm to the upper elements. The following example demonstrates
+// this by means of a dense matrix/dense matrix multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ StrictlyUpperMatrix< DynamicMatrix<double,rowMajor> > A;
+ StrictlyUpperMatrix< DynamicMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// In comparison to a general matrix multiplication, the performance advantage is significant,
+// especially for large and medium-sized matrices. Therefore is it highly recommended to use
+// the StrictlyUpperMatrix adaptor when a matrix is known to be strictly upper triangular. Note
+// however that the performance advantage is most pronounced for dense matrices and much less
+// so for sparse matrices.
+//
+// \n \subsection strictlyuppermatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar performance improvement can be gained when using a strictly upper triangular matrix
+// in a matrix/vector multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ StrictlyUpperMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicVector<double,columnVector> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example, \b Blaze also exploits the structure of the matrix and approx. halves the
+// runtime of the multiplication. Also in case of matrix/vector multiplications the performance
+// improvement is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection strictlyuppermatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a strictly upper triangular matrix on the right-hand side of an assignment
+// (i.e. for read access), which introduces absolutely no performance penalty, using a strictly
+// upper matrix on the left-hand side of an assignment (i.e. for write access) may introduce
+// additional overhead when it is assigned a matrix, which is not strictly upper triangular at
+// compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StrictlyUpperMatrix;
+
+ StrictlyUpperMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the upper matrix; no performance penalty
+ C = A; // Assignment of a strictly upper matrix to another strictly upper matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a strictly upper matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not strictly upper matrix to a strictly upper matrix it
+// is necessary to check whether the general matrix is strictly upper at runtime in order to
+// guarantee the strictly upper triangular property of the strictly upper matrix. In case it
+// turns out to be strictly upper triangular, it is assigned as efficiently as possible, if it
+// is not, an exception is thrown. In order to prevent this runtime overhead it is therefore
+// generally advisable to assign strictly upper matrices to other strictly upper matrices.\n
+// In this context it is especially noteworthy that the addition, subtraction, and multiplication
+// of two strictly upper triangular matrices always results in another strictly upper matrix:
+
+ \code
+ StrictlyUpperMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a strictly upper matrix; no runtime overhead
+ C = A - B; // Results in a strictly upper matrix; no runtime overhead
+ C = A * B; // Results in a strictly upper matrix; no runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class StrictlyUpperMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/strictlyuppermatrix/Dense.h b/src/cpu/blaze/math/adaptors/strictlyuppermatrix/Dense.h
new file mode 100644
index 00000000..c5ef74b2
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/strictlyuppermatrix/Dense.h
@@ -0,0 +1,2757 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/strictlyuppermatrix/Dense.h
+// \brief StrictlyUpperMatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_DENSE_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlyuppermatrix/StrictlyUpperProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/Square.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StrictlyUpperMatrix for dense matrices.
+// \ingroup strictly_upper_matrix
+//
+// This specialization of StrictlyUpperMatrix adapts the class template to the requirements of
+// dense matrices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class StrictlyUpperMatrix<MT,SO,true>
+ : public DenseMatrix< StrictlyUpperMatrix<MT,SO,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef StrictlyUpperMatrix<MT,SO,true> This; //!< Type of this StrictlyUpperMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this StrictlyUpperMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef StrictlyUpperMatrix<OT,!SO,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef StrictlyLowerMatrix<TT,!SO,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef StrictlyUpperProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain an StrictlyUpperMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other StrictlyUpperMatrix.
+ typedef StrictlyUpperMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense strictly upper matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef StrictlyUpperProxy<MT> PointerType; //!< Pointer return type.
+ typedef StrictlyUpperProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row-index of the iterator
+ , column_( column ) // The current column-index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) noexcept {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row-index of the iterator.
+ size_t column_; //!< The current column-index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StrictlyUpperMatrix();
+ template< typename A1 > explicit inline StrictlyUpperMatrix( const A1& a1 );
+ explicit inline StrictlyUpperMatrix( size_t n, const ElementType& init );
+
+ explicit inline StrictlyUpperMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline StrictlyUpperMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline StrictlyUpperMatrix( const Other (&array)[N][N] );
+
+ explicit inline StrictlyUpperMatrix( ElementType* ptr, size_t n );
+ explicit inline StrictlyUpperMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline StrictlyUpperMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline StrictlyUpperMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline StrictlyUpperMatrix( const StrictlyUpperMatrix& m );
+ inline StrictlyUpperMatrix( StrictlyUpperMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline StrictlyUpperMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline StrictlyUpperMatrix& operator=( const Other (&array)[N][N] );
+
+ inline StrictlyUpperMatrix& operator=( const ElementType& rhs );
+ inline StrictlyUpperMatrix& operator=( const StrictlyUpperMatrix& rhs );
+ inline StrictlyUpperMatrix& operator=( StrictlyUpperMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline StrictlyUpperMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, StrictlyUpperMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, StrictlyUpperMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+
+ template< typename Other > inline StrictlyUpperMatrix& scale( const Other& scalar );
+
+ inline void swap( StrictlyUpperMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ inline const MT construct( size_t n , TrueType );
+ inline const MT construct( const ElementType& value, FalseType );
+
+ template< typename MT2, bool SO2, typename T >
+ inline const MT construct( const Matrix<MT2,SO2>& m, T );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( StrictlyUpperMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for StrictlyUpperMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Single argument constructor for a strictly upper matrix.
+//
+// \param a1 The single constructor argument.
+// \exception std::invalid_argument Invalid setup of strictly upper matrix.
+//
+// This constructor constructs the strictly upper matrix based on the given argument and the type
+// of the underlying matrix \a MT:
+// - in case the given argument is a matrix, the strictly upper matrix is initialized as a copy
+// of the given matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// resizable, the given argument \a a1 specifies the number of rows and columns of the
+// strictly upper matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// a matrix with fixed size, the given argument \a a1 specifies the initial value of the
+// upper elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename A1 > // Type of the constructor argument
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( const A1& a1 )
+ : matrix_( construct( a1, typename IsResizable<MT>::Type() ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a \f$ n \times n \f$ matrix with initialized upper elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param init The initial value of the upper matrix elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( size_t n, const ElementType& init )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i )
+ matrix_(i,j) = init;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( size_t j=i+1UL; j<columns(); ++j )
+ matrix_(i,j) = init;
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of strictly upper matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the strictly
+// upper matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::StrictlyUpperMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A{ { 0, 2, 3 },
+ { 0, 0 },
+ { 0, 0, 0 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isStrictlyUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all strictly upper matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of strictly upper matrix.
+//
+// This constructor offers the option to directly initialize the elements of the strictly upper
+// matrix with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[20];
+ // ... Initialization of the dynamic array
+ blaze::StrictlyUpperMatrix< blaze::DynamicMatrix<int,rowMajor> > v( 4UL, 5UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized accoring to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a m by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also,
+// in case the given array does not represent a strictly upper triangular matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isStrictlyUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all strictly upper matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of strictly upper matrix.
+//
+// This constructor offers the option to directly initialize the elements of the strictly upper
+// matrix with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 0, 1, 2 },
+ { 0, 0 },
+ { 0, 0, 0 } };
+ blaze::StrictlyUpperMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a strictly upper triangular
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of columns of the initialization array
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isStrictlyUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a strictly upper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of strictly upper custom matrix.
+//
+// This constructor creates an unpadded strictly upper custom matrix of size \f$ n \times n \f$.
+// The construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a strictly lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded strictly upper custom matrices!
+// \note The strictly upper custom matrix does \b NOT take responsibility for the given array of
+// elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isStrictlyUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a strictly upper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of strictly upper custom matrix.
+//
+// This constructor creates a strictly upper custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a strictly lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isStrictlyUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a strictly upper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of strictly upper custom matrix.
+//
+// This constructor creates an unpadded strictly upper custom matrix of size \f$ n \times n \f$.
+// The construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a strictly lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded strictly upper custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isStrictlyUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a strictly upper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of strictly upper custom matrix.
+//
+// This constructor creates a strictly upper custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a strictly lower triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isStrictlyUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for StrictlyUpperMatrix.
+//
+// \param m The strictly upper matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( const StrictlyUpperMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for StrictlyUpperMatrix.
+//
+// \param m The strictly upper matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>::StrictlyUpperMatrix( StrictlyUpperMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::Reference
+ StrictlyUpperMatrix<MT,SO,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::ConstReference
+ StrictlyUpperMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::Reference
+ StrictlyUpperMatrix<MT,SO,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::ConstReference
+ StrictlyUpperMatrix<MT,SO,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the strictly upper matrix. Note
+// that you can NOT assume that all matrix elements lie adjacent to each other! The strictly
+// upper matrix may use techniques such as padding to improve the alignment of the data. Whereas
+// the number of elements within a row/column are given by the \c rows() and \c columns() member
+// functions, respectively, the total number of elements including padding is given by the
+// \c spacing() member function.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::ConstPointer
+ StrictlyUpperMatrix<MT,SO,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::ConstPointer
+ StrictlyUpperMatrix<MT,SO,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly upper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::Iterator
+ StrictlyUpperMatrix<MT,SO,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly upper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly upper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly upper matrix adapts a \a rowMajor dense matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor dense
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::Iterator
+ StrictlyUpperMatrix<MT,SO,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly upper matrix adapts a \a rowMajor dense matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor dense
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly upper matrix adapts a \a rowMajor dense matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor dense
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename StrictlyUpperMatrix<MT,SO,true>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all upper matrix elements.
+//
+// \param rhs Scalar value to be assigned to the upper matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>&
+ StrictlyUpperMatrix<MT,SO,true>::operator=( const ElementType& rhs )
+{
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j )
+ for( size_t i=0UL; i<j; ++i )
+ matrix_(i,j) = rhs;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=i+1UL; j<columns(); ++j )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the strictly
+// upper matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::StrictlyUpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = { { 0, 2, 3 },
+ { 0, 0 },
+ { 0, 0, 0 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>&
+ StrictlyUpperMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all strictly upper matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// This assignment operator offers the option to directly set all elements of the strictly upper
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 0, 2, 3 },
+ { },
+ { } };
+ blaze::StrictlyUpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a strictly upper triangular matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline StrictlyUpperMatrix<MT,SO,true>&
+ StrictlyUpperMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for StrictlyUpperMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>&
+ StrictlyUpperMatrix<MT,SO,true>::operator=( const StrictlyUpperMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for StrictlyUpperMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline StrictlyUpperMatrix<MT,SO,true>&
+ StrictlyUpperMatrix<MT,SO,true>::operator=( StrictlyUpperMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// strictly upper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,true>& >
+ StrictlyUpperMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// strictly upper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,true>& >
+ StrictlyUpperMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a strictly
+// upper matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is
+// not a strictly upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,true>& >
+ StrictlyUpperMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a strictly
+// upper matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is
+// not a strictly upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,true>& >
+ StrictlyUpperMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a strictly
+// upper matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is not
+// a strictly upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,true>& >
+ StrictlyUpperMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a strictly
+// upper matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is not
+// a strictly upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,true>& >
+ StrictlyUpperMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a strictly upper
+// matrix. In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline StrictlyUpperMatrix<MT,SO,true>&
+ StrictlyUpperMatrix<MT,SO,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, StrictlyUpperMatrix<MT,SO,true> >&
+ StrictlyUpperMatrix<MT,SO,true>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, StrictlyUpperMatrix<MT,SO,true> >&
+ StrictlyUpperMatrix<MT,SO,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyUpperMatrix<MT,SO,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyUpperMatrix<MT,SO,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the total
+// number of elements of a row/column. In case the strictly upper matrix adapts a \a rowMajor
+// dense matrix the function returns the spacing between two rows, in case it adapts a
+// \a columnMajor dense matrix the function returns the spacing between two columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyUpperMatrix<MT,SO,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyUpperMatrix<MT,SO,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the strictly
+// upper matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i,
+// in case it adapts a \a columnMajor dense matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyUpperMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the strictly upper matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyUpperMatrix<MT,SO,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the strictly upper matrix adapts a \a rowMajor dense matrix the function returns the
+// number of non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix
+// the function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t StrictlyUpperMatrix<MT,SO,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyUpperMatrix<MT,SO,true>::reset()
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j )
+ for( size_t i=0UL; i<j; ++i )
+ clear( matrix_(i,j) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=i+1UL; j<columns(); ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyUpperMatrix<MT,SO,true>::reset( size_t i )
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=0UL; j<i; ++j )
+ clear( matrix_(j,i) );
+ }
+ else {
+ for( size_t j=i+1UL; j<columns(); ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the strictly upper matrix.
+//
+// \return void
+//
+// This function clears the matrix and returns it to its default state. The function has the same
+// effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable matrix
+// (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set to 0,
+// whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will be
+// reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyUpperMatrix<MT,SO,true>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the strictly upper matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the strictly upper matrix adapts a resizable matrix, this function resizes the matrix
+// using the given size to \f$ n \times n \f$. During this operation, new dynamic memory may
+// be allocated in case the capacity of the matrix is too small. Note that this function may
+// invalidate all existing views (submatrices, rows, columns, ...) on the matrix if it is used to
+// shrink the matrix. Additionally, the resize operation potentially changes all matrix elements.
+// In order to preserve the old matrix values, the \a preserve flag can be set to \a true. Also
+// note that in case the size of the matrix is increased, only the new elements in the lower part
+// of the matrix are default initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 0 & 1 & 4 \\
+ 0 & 0 & 1 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & x \\
+ 0 & 1 & 4 & x \\
+ 0 & 0 & 1 & x \\
+ 0 & 0 & 0 & 1 \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void StrictlyUpperMatrix<MT,SO,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize )
+ {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, oldsize, 0UL, increment, n ).reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyUpperMatrix<MT,SO,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the strictly upper matrix.
+// \return void
+//
+// This function increases the capacity of the strictly upper matrix to at least \a elements
+// elements. The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyUpperMatrix<MT,SO,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the scalar value
+inline StrictlyUpperMatrix<MT,SO,true>&
+ StrictlyUpperMatrix<MT,SO,true>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyUpperMatrix<MT,SO,true>::swap( StrictlyUpperMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a strictly upper triangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a strictly upper
+// triangular matrix with fixed-size adapted matrix of type \a MT. Note that this function
+// can only be called in case the adapted dense matrix is a fixed-size matrix (as for instance
+// StaticMatrix). The attempt to call this function in case the adapted matrix is resizable
+// matrix will result in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t StrictlyUpperMatrix<MT,SO,true>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a strictly upper triangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a strictly upper
+// triangular matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t StrictlyUpperMatrix<MT,SO,true>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n - 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the strictly upper matrix are intact.
+//
+// \return \a true in case the strictly upper matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the strictly upper matrix are intact, i.e. if
+// its state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool StrictlyUpperMatrix<MT,SO,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isStrictlyUpper( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool StrictlyUpperMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool StrictlyUpperMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool StrictlyUpperMatrix<MT,SO,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool StrictlyUpperMatrix<MT,SO,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the strictly upper matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename StrictlyUpperMatrix<MT,SO,true>::SIMDType
+ StrictlyUpperMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the strictly upper
+// matrix. The row index must be smaller than the number of rows and the column index must be
+// smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename StrictlyUpperMatrix<MT,SO,true>::SIMDType
+ StrictlyUpperMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the strictly upper
+// matrix. The row index must be smaller than the number of rows and the column index must be
+// smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename StrictlyUpperMatrix<MT,SO,true>::SIMDType
+ StrictlyUpperMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a resizable matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT StrictlyUpperMatrix<MT,SO,true>::construct( size_t n, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ return MT( n, n, ElementType() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a fixed-size matrix with homogeneously initialized upper elements.
+//
+// \param init The initial value of the upper matrix elements.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT StrictlyUpperMatrix<MT,SO,true>::construct( const ElementType& init, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SQUARE( MT );
+
+ MT tmp;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i )
+ tmp(i,j) = init;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( size_t j=i+1UL; j<columns(); ++j )
+ tmp(i,j) = init;
+ }
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a matrix as a copy from another matrix.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of strictly upper matrix.
+// \return The newly constructed matrix.
+//
+// In case the given matrix is not a strictly upper matrix, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT StrictlyUpperMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ const MT tmp( ~m );
+
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( tmp ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/strictlyuppermatrix/Sparse.h b/src/cpu/blaze/math/adaptors/strictlyuppermatrix/Sparse.h
new file mode 100644
index 00000000..7f79423b
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/strictlyuppermatrix/Sparse.h
@@ -0,0 +1,2111 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/strictlyuppermatrix/Sparse.h
+// \brief StrictlyUpperMatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_SPARSE_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/strictlyuppermatrix/StrictlyUpperProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StrictlyUpperMatrix for sparse matrices.
+// \ingroup strictly_upper_matrix
+//
+// This specialization of StrictlyUpperMatrix adapts the class template to the requirements of sparse
+// matrices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class StrictlyUpperMatrix<MT,SO,false>
+ : public SparseMatrix< StrictlyUpperMatrix<MT,SO,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef StrictlyUpperMatrix<MT,SO,false> This; //!< Type of this StrictlyUpperMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this StrictlyUpperMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef StrictlyUpperMatrix<OT,!SO,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef StrictlyLowerMatrix<TT,!SO,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef StrictlyUpperProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain an StrictlyUpperMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other StrictlyUpperMatrix.
+ typedef StrictlyUpperMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StrictlyUpperMatrix();
+ explicit inline StrictlyUpperMatrix( size_t n );
+ explicit inline StrictlyUpperMatrix( size_t n, size_t nonzeros );
+ explicit inline StrictlyUpperMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline StrictlyUpperMatrix( const StrictlyUpperMatrix& m );
+ inline StrictlyUpperMatrix( StrictlyUpperMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline StrictlyUpperMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline StrictlyUpperMatrix& operator=( const StrictlyUpperMatrix& rhs );
+ inline StrictlyUpperMatrix& operator=( StrictlyUpperMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline StrictlyUpperMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, StrictlyUpperMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, StrictlyUpperMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+
+ template< typename Other > inline StrictlyUpperMatrix& scale( const Other& scalar );
+ template< typename Other > inline StrictlyUpperMatrix& scaleDiagonal( Other scale );
+
+ inline void swap( StrictlyUpperMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void resetLower();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( StrictlyUpperMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for StrictlyUpperMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyUpperMatrix<MT,SO,false>::StrictlyUpperMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized as identity matrix and has no additional free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyUpperMatrix<MT,SO,false>::StrictlyUpperMatrix( size_t n )
+ : matrix_( n, n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized as identity matrix and will have at least the capacity for
+// \a nonzeros non-zero elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyUpperMatrix<MT,SO,false>::StrictlyUpperMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, max( nonzeros, n ) ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+// \exception std::invalid_argument Invalid capacity specification.
+//
+// The matrix is initialized as identity matrix and will have the specified capacity in each
+// row/column. Note that since the matrix is initialized as \f$ n \times n \f$ identity matrix
+// the given vector must have at least \a n elements, all of which must not be 0. If the number
+// of non-zero elements of any row/column is specified as 0, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyUpperMatrix<MT,SO,false>::StrictlyUpperMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for StrictlyUpperMatrix.
+//
+// \param m The strictly upper matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyUpperMatrix<MT,SO,false>::StrictlyUpperMatrix( const StrictlyUpperMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for StrictlyUpperMatrix.
+//
+// \param m The strictly upper matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyUpperMatrix<MT,SO,false>::StrictlyUpperMatrix( StrictlyUpperMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of strictly upper matrix.
+//
+// This constructor initializes the strictly upper matrix as a copy of the given matrix. In
+// case the given matrix is not a strictly upper matrix, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline StrictlyUpperMatrix<MT,SO,false>::StrictlyUpperMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( ~m ) // The adapted sparse matrix
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( matrix_ ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" );
+ }
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Reference
+ StrictlyUpperMatrix<MT,SO,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstReference
+ StrictlyUpperMatrix<MT,SO,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Reference
+ StrictlyUpperMatrix<MT,SO,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstReference
+ StrictlyUpperMatrix<MT,SO,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::begin( size_t i )
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,false>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the strictly upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// to the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,false>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly upper matrix adapts a \a rowMajor sparse matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor sparse
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::end( size_t i )
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly upper matrix adapts a \a rowMajor sparse matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor sparse
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,false>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the strictly upper matrix adapts a \a rowMajor sparse matrix the function returns an
+// iterator just past the last element of row \a i, in case it adapts a \a columnMajor sparse
+// matrix the function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,false>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for StrictlyUpperMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyUpperMatrix<MT,SO,false>&
+ StrictlyUpperMatrix<MT,SO,false>::operator=( const StrictlyUpperMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for StrictlyUpperMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline StrictlyUpperMatrix<MT,SO,false>&
+ StrictlyUpperMatrix<MT,SO,false>::operator=( StrictlyUpperMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// strictly upper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,false>& >
+ StrictlyUpperMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// strictly upper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,false>& >
+ StrictlyUpperMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a strictly
+// upper matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is
+// not a strictly upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,false>& >
+ StrictlyUpperMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be a strictly
+// upper matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is
+// not a strictly upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,false>& >
+ StrictlyUpperMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a strictly
+// upper matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is not
+// a strictly upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,false>& >
+ StrictlyUpperMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to strictly upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be a strictly
+// upper matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is not
+// a strictly upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, StrictlyUpperMatrix<MT,SO,false>& >
+ StrictlyUpperMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUniTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a strictly upper
+// matrix. In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline StrictlyUpperMatrix<MT,SO,false>&
+ StrictlyUpperMatrix<MT,SO,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, StrictlyUpperMatrix<MT,SO,false> >&
+ StrictlyUpperMatrix<MT,SO,false>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, StrictlyUpperMatrix<MT,SO,false> >&
+ StrictlyUpperMatrix<MT,SO,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyUpperMatrix<MT,SO,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyUpperMatrix<MT,SO,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyUpperMatrix<MT,SO,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the strictly
+// upper matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i,
+// in case it adapts a \a columnMajor sparse matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyUpperMatrix<MT,SO,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the strictly upper matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyUpperMatrix<MT,SO,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the strictly upper matrix adapts a \a rowMajor sparse matrix the function returns
+// the number of non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse
+// matrix the function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t StrictlyUpperMatrix<MT,SO,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::reset()
+{
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j ) {
+ matrix_.erase( j, matrix_.begin(j), matrix_.lowerBound(j,j) );
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ matrix_.erase( i, matrix_.lowerBound(i,i+1UL), matrix_.end(i) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::reset( size_t i )
+{
+ if( SO ) {
+ matrix_.erase( i, matrix_.begin(i), matrix_.lowerBound(i,i) );
+ }
+ else {
+ matrix_.erase( i, matrix_.lowerBound(i,i+1UL), matrix_.end(i) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the strictly upper matrix.
+//
+// \return void
+//
+// This function clears the strictly upper matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the strictly upper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to diagonal or lower matrix element.
+//
+// This function sets the value of an element of the strictly upper matrix. In case the strictly
+// upper matrix already contains an element with row index \a i and column index \a j its value
+// is modified, else a new element with the given \a value is inserted. The attempt to set an
+// element on the diagonal or in the lower part of the matrix (i.e. below the diagonal) will
+// result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ if( i >= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or lower matrix element" );
+ }
+
+ return matrix_.set( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the strictly upper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+// \exception std::invalid_argument Invalid access to diagonal or lower matrix element.
+//
+// This function inserts a new element into the strictly upper matrix. However, duplicate elements
+// are not allowed. In case the matrix already contains an element with row index \a i and column
+// index \a j, a \a std::invalid_argument exception is thrown. Also, the attempt to insert an
+// element on the diagonal or in the lower part of the matrix (i.e. below the diagonal) will
+// result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ if( i >= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or lower matrix element" );
+ }
+
+ return matrix_.insert( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the strictly upper matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the strictly upper matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::erase( size_t i, size_t j )
+{
+ matrix_.erase( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the strictly upper matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the strictly upper matrix. In case the strictly upper
+// matrix adapts a \a rowMajor sparse matrix the function erases an element from row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function erases an element from column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::erase( size_t i, Iterator pos )
+{
+ return matrix_.erase( i, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the strictly upper matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the strictly upper matrix. In case the matrix
+// adapts a \a rowMajor sparse matrix the function erases a range of elements from row \a i, in
+// case it adapts a \a columnMajor matrix the function erases a range of elements from column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ return matrix_.erase( i, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the strictly upper matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void StrictlyUpperMatrix<MT,SO,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square strictly upper matrix detected" );
+
+ matrix_.resize( n, n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the strictly upper matrix.
+//
+// \param nonzeros The new minimum capacity of the strictly upper matrix.
+// \return void
+//
+// This function increases the capacity of the strictly upper matrix to at least \a nonzeros
+// elements. The current values of the matrix elements and the individual capacities of the
+// matrix rows are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the strictly upper matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the strictly upper matrix to at
+// least \a nonzeros elements. The current values of the strictly upper matrix and all other
+// individual row/column capacities are preserved. In case the strictly upper matrix adapts a
+// \a rowMajor sparse matrix the function reserves capacity for row \a i. In case it adapts a
+// \a columnMajor the function reserves capacity for column \a i. The index has to be in the
+// range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the strictly upper matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline StrictlyUpperMatrix<MT,SO,false>&
+ StrictlyUpperMatrix<MT,SO,false>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the upper matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the upper matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline StrictlyUpperMatrix<MT,SO,false>&
+ StrictlyUpperMatrix<MT,SO,false>::scaleDiagonal( Other scalar )
+{
+ matrix_.scaleDiagonal( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::swap( StrictlyUpperMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a strictly upper triangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a strictly upper
+// triangular matrix with fixed-size adapted matrix of type \a MT. Note that this function can
+// only be called in case the adapted dense matrix is a fixed-size matrix. The attempt to call
+// this function in case the adapted matrix is resizable matrix will result in a compile time
+// error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t StrictlyUpperMatrix<MT,SO,false>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a strictly upper triangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a strictly upper
+// triangular matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t StrictlyUpperMatrix<MT,SO,false>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n - 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the complete lower part of the matrix to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::resetLower()
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ matrix_.erase( j, matrix_.upperBound( j, j ), matrix_.end( j ) );
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i )
+ matrix_.erase( i, matrix_.begin( i ), matrix_.lowerBound( i, i ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the strictly
+// upper matrix. It specifically searches for the element with row index \a i and column index
+// \a j. In case the element is found, the function returns an row/column iterator to the
+// element. Otherwise an iterator just past the last non-zero element of row \a i or column
+// \a j (the end() iterator) is returned. Note that the returned uniupper matrix iterator is
+// subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::find( size_t i, size_t j )
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the strictly
+// upper matrix. It specifically searches for the element with row index \a i and column index
+// \a j. In case the element is found, the function returns an row/column iterator to the
+// element. Otherwise an iterator just past the last non-zero element of row \a i or column
+// \a j (the end() iterator) is returned. Note that the returned uniupper matrix iterator is
+// subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,false>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned strictly upper
+// matrix iterator is subject to invalidation due to inserting operations via the function
+// call operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::lowerBound( size_t i, size_t j )
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned strictly upper
+// matrix iterator is subject to invalidation due to inserting operations via the function
+// call operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,false>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned strictly upper
+// matrix iterator is subject to invalidation due to inserting operations via the function
+// call operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::Iterator
+ StrictlyUpperMatrix<MT,SO,false>::upperBound( size_t i, size_t j )
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned strictly upper
+// matrix iterator is subject to invalidation due to inserting operations via the function
+// call operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename StrictlyUpperMatrix<MT,SO,false>::ConstIterator
+ StrictlyUpperMatrix<MT,SO,false>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the strictly upper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to diagonal or lower matrix element.
+//
+// This function provides a very efficient way to fill a sparse matrix with elements. It appends
+// a new element to the end of the specified row/column without any additional memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (newly created) sparse matrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StrictlyUpperMatrix;
+ using blaze::rowMajor;
+
+ StrictlyUpperMatrix< CompressedMatrix<double,rowMajor> > A( 4 );
+
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 0, 1, 1.0 ); // Appending the value 1 in row 0 with column index 1
+ A.finalize( 0 ); // Finalizing row 0
+ A.append( 1, 2, 2.0 ); // Appending the value 2 in row 1 with column index 2
+ A.finalize( 1 ); // Finalizing row 1
+ A.append( 2, 3, 3.0 ); // Appending the value 3 in row 2 with column index 3
+ A.finalize( 2 ); // Finalizing row 2
+ A.finalize( 3 ); // Finalizing the empty row 3
+ \endcode
+
+// Note that although append() does not allocate new memory it still invalidates all iterators
+// returned by the end() functions! Also note that the attempt to append an element within the
+// lower part of the matrix (i.e. below the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( i >= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or lower matrix element" );
+ }
+
+ matrix_.append( i, j, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void StrictlyUpperMatrix<MT,SO,false>::finalize( size_t i )
+{
+ matrix_.finalize( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the strictly upper matrix are intact.
+//
+// \return \a true in case the strictly upper matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the strictly upper matrix are intact, i.e. if
+// its state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool StrictlyUpperMatrix<MT,SO,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isStrictlyUpper( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool StrictlyUpperMatrix<MT,SO,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool StrictlyUpperMatrix<MT,SO,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool StrictlyUpperMatrix<MT,SO,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/strictlyuppermatrix/StrictlyUpperProxy.h b/src/cpu/blaze/math/adaptors/strictlyuppermatrix/StrictlyUpperProxy.h
new file mode 100644
index 00000000..e54f307d
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/strictlyuppermatrix/StrictlyUpperProxy.h
@@ -0,0 +1,669 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/strictlyuppermatrix/StrictlyUpperProxy.h
+// \brief Header file for the StrictlyUpperProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_UPPERPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_STRICTLYUPPERMATRIX_UPPERPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/typetraits/AddConst.h>
+#include <blaze/util/typetraits/AddReference.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for strictly upper triangular matrices.
+// \ingroup strictly_upper_matrix
+//
+// The StrictlyUpperProxy provides controlled access to the elements of a non-const strictly upper
+// triangular matrix. It guarantees that the strictly upper matrix invariant is not violated, i.e.
+// that elements on the diagonal and in the lower part of the matrix remain 0. The following
+// example illustrates this by means of a \f$ 3 \times 3 \f$ dense strictly upper triangular
+// matrix:
+
+ \code
+ // Creating a 3x3 strictly upper triangular dense matrix
+ blaze::StrictlyUpperMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(0,1) = -2; // ( 0 -2 3 )
+ A(0,2) = 3; // => A = ( 0 0 5 )
+ A(1,2) = 5; // ( 0 0 0 )
+
+ A(1,1) = 4; // Invalid assignment to diagonal matrix element; results in an exception!
+ A(2,0) = 7; // Invalid assignment to lower matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class StrictlyUpperProxy : public Proxy< StrictlyUpperProxy<MT>, ElementType_<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Reference type of the underlying matrix type.
+ typedef AddConst_< Reference_<MT> > ReferenceType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+ typedef AddReference_<ReferenceType> RawReference; //!< Reference-to-non-const to the represented element.
+ typedef const RepresentedType& ConstReference; //!< Reference-to-const to the represented element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StrictlyUpperProxy( MT& matrix, size_t row, size_t column );
+ inline StrictlyUpperProxy( const StrictlyUpperProxy& uup );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline const StrictlyUpperProxy& operator= ( const StrictlyUpperProxy& uup ) const;
+
+ template< typename T >
+ inline const StrictlyUpperProxy& operator=( initializer_list<T> list ) const;
+
+ template< typename T >
+ inline const StrictlyUpperProxy& operator=( initializer_list< initializer_list<T> > list ) const;
+
+ template< typename T > inline const StrictlyUpperProxy& operator= ( const T& value ) const;
+ template< typename T > inline const StrictlyUpperProxy& operator+=( const T& value ) const;
+ template< typename T > inline const StrictlyUpperProxy& operator-=( const T& value ) const;
+ template< typename T > inline const StrictlyUpperProxy& operator*=( const T& value ) const;
+ template< typename T > inline const StrictlyUpperProxy& operator/=( const T& value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline RawReference get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator ConstReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ ReferenceType value_; //!< Reference to the accessed matrix element.
+ const bool restricted_; //!< Access flag for the accessed matrix element.
+ /*!< The flag indicates if access to the matrix element is
+ restricted. It is \a true in case the proxy represents an
+ element on the diagonal or in the lower part of the matrix. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a StrictlyUpperProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline StrictlyUpperProxy<MT>::StrictlyUpperProxy( MT& matrix, size_t row, size_t column )
+ : value_ ( matrix( row, column ) ) // Reference to the accessed matrix element
+ , restricted_( column <= row ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for StrictlyUpperProxy.
+//
+// \param uup Proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline StrictlyUpperProxy<MT>::StrictlyUpperProxy( const StrictlyUpperProxy& uup )
+ : value_ ( uup.value_ ) // Reference to the accessed matrix element
+ , restricted_( uup.restricted_ ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for StrictlyUpperProxy.
+//
+// \param uup Proxy to be copied.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline const StrictlyUpperProxy<MT>& StrictlyUpperProxy<MT>::operator=( const StrictlyUpperProxy& uup ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ = uup.value_;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyUpperProxy<MT>&
+ StrictlyUpperProxy<MT>::operator=( initializer_list<T> list ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyUpperProxy<MT>&
+ StrictlyUpperProxy<MT>::operator=( initializer_list< initializer_list<T> > list ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyUpperProxy<MT>& StrictlyUpperProxy<MT>::operator=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyUpperProxy<MT>& StrictlyUpperProxy<MT>::operator+=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyUpperProxy<MT>& StrictlyUpperProxy<MT>::operator-=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyUpperProxy<MT>& StrictlyUpperProxy<MT>::operator*=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const StrictlyUpperProxy<MT>& StrictlyUpperProxy<MT>::operator/=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename StrictlyUpperProxy<MT>::RawReference StrictlyUpperProxy<MT>::get() const noexcept
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted matrix element..
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool StrictlyUpperProxy<MT>::isRestricted() const noexcept
+{
+ return restricted_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Reference-to-const to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline StrictlyUpperProxy<MT>::operator ConstReference() const noexcept
+{
+ return static_cast<ConstReference>( value_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name StrictlyUpperProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const StrictlyUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const StrictlyUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const StrictlyUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const StrictlyUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const StrictlyUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const StrictlyUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const StrictlyUpperProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup strictly_upper_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const StrictlyUpperProxy<MT>& proxy )
+{
+ using blaze::reset;
+
+ reset( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup strictly_upper_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const StrictlyUpperProxy<MT>& proxy )
+{
+ using blaze::clear;
+
+ clear( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup strictly_upper_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const StrictlyUpperProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup strictly_upper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const StrictlyUpperProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup strictly_upper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const StrictlyUpperProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup strictly_upper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const StrictlyUpperProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup strictly_upper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const StrictlyUpperProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/BaseTemplate.h
new file mode 100644
index 00000000..99392ba6
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/BaseTemplate.h
@@ -0,0 +1,614 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the SymmetricMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsNumericMatrix.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup symmetric_matrix SymmetricMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for symmetric \f$ N \times N \f$ matrices.
+// \ingroup symmetric_matrix
+//
+// \section symmetricmatrix_general General
+//
+// The SymmetricMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \a MT and extends it
+// by enforcing the additional invariant of symmetry (i.e. the matrix is always equal to its
+// transpose \f$ A = A^T \f$). The type of the adapted matrix can be specified via the first
+// template parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF, bool NF >
+ class SymmetricMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. SymmetricMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Note that the given matrix type must be either resizable (as for instance
+// HybridMatrix or DynamicMatrix) or must be square at compile time (as for instance
+// StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+// - NF: determines how the elements of the matrix are handled internally. In order to provide
+// maximum performance and to save memory by exploiting the symmetry of the matrix, the
+// SymmetricMatrix class template implements several storage strategies. This template
+// parameter must \b NOT be defined explicitly, it is automatically derived from the first
+// template parameter. Defining the parameter explicitly may result in a compilation error!
+//
+// The following examples give an impression of several possible symmetric matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense symmetric matrix with static memory
+ blaze::SymmetricMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense symmetric matrix based on HybridMatrix
+ blaze::SymmetricMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense symmetric matrix based on DynamicMatrix
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense symmetric matrix based on CustomMatrix
+ blaze::SymmetricMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision symmetric matrix
+ blaze::SymmetricMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of a symmetric matrix is depending on the storage order of the adapted matrix
+// type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified as
+// blaze::rowMajor), the symmetric matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the symmetric matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section symmetricmatrix_vs_hermitianmatrix Symmetric Matrices vs. Hermitian Matrices
+//
+// The blaze::SymmetricMatrix adaptor and the blaze::HermitianMatrix adaptor share several traits.
+// However, there are a couple of differences, both from a mathematical point of view as well as
+// from an implementation point of view.
+//
+// From a mathematical point of view, a matrix is called symmetric when it is equal to its
+// transpose (\f$ A = A^T \f$) and it is called Hermitian when it is equal to its conjugate
+// transpose (\f$ A = \overline{A^T} \f$). For matrices of real values, however, these two
+// conditions coincide, which means that symmetric matrices of real values are also Hermitian
+// and Hermitian matrices of real values are also symmetric.
+//
+// From an implementation point of view, \b Blaze restricts Hermitian matrices to numeric data
+// types (i.e. all integral types except \a bool, floating point and complex types), whereas
+// symmetric matrices can also be block structured (i.e. can have vector or matrix elements).
+// For built-in element types, the HermitianMatrix adaptor behaves exactly like the according
+// SymmetricMatrix implementation. For complex element types, however, the Hermitian property
+// is enforced (see also \ref hermitianmatrix_hermitian).
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::HermitianMatrix;
+ using blaze::SymmetricMatrix;
+
+ // The following two matrices provide an identical experience (including performance)
+ SymmetricMatrix< DynamicMatrix<double> > A; // Both Hermitian and symmetric
+ HermitianMatrix< DynamicMatrix<double> > B; // Both Hermitian and symmetric
+
+ // The following two matrices will behave differently
+ SymmetricMatrix< DynamicMatrix< complex<double> > > C; // Only symmetric
+ HermitianMatrix< DynamicMatrix< complex<double> > > D; // Only Hermitian
+
+ // Block-structured Hermitian matrices are not allowed
+ SymmetricMatrix< DynamicMatrix< DynamicVector<double> > > E; // Block-structured symmetric matrix
+ HermitianMatrix< DynamicMatrix< DynamicVector<double> > > F; // Compilation error!
+ \endcode
+
+// \n \section symmetricmatrix_special_properties Special Properties of Symmetric Matrices
+//
+// A symmetric matrix is used exactly like a matrix of the underlying, adapted matrix type \a MT.
+// It also provides (nearly) the same interface as the underlying matrix type. However, there are
+// some important exceptions resulting from the symmetry constraint:
+//
+// -# <b>\ref symmetricmatrix_square</b>
+// -# <b>\ref symmetricmatrix_symmetry</b>
+// -# <b>\ref symmetricmatrix_initialization</b>
+//
+// \n \subsection symmetricmatrix_square Symmetric Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 symmetric dynamic matrix
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 symmetric static matrix
+ SymmetricMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ SymmetricMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection symmetricmatrix_symmetry The Symmetric Property is Always Enforced!
+//
+// This means that modifying the element \f$ a_{ij} \f$ of a symmetric matrix also modifies its
+// counterpart element \f$ a_{ji} \f$. Also, it is only possible to assign matrices that are
+// symmetric themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, row-major 3x3 symmetric compressed matrix
+ SymmetricMatrix< CompressedMatrix<double,rowMajor> > A( 3 );
+
+ // Initializing three elements via the function call operator
+ A(0,0) = 1.0; // Initialization of the diagonal element (0,0)
+ A(0,2) = 2.0; // Initialization of the elements (0,2) and (2,0)
+
+ // Inserting three more elements via the insert() function
+ A.insert( 1, 1, 3.0 ); // Inserting the diagonal element (1,1)
+ A.insert( 1, 2, 4.0 ); // Inserting the elements (1,2) and (2,1)
+
+ // Access via a non-const iterator
+ *A.begin(1UL) = 10.0; // Modifies both elements (1,0) and (0,1)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 0, 2 ); // Erasing the elements (0,2) and (2,0)
+
+ // Construction from a symmetric dense matrix
+ StaticMatrix<double,3UL,3UL> B( 3.0, 8.0, -2.0,
+ 8.0, 0.0, -1.0,
+ -2.0, -1.0, 4.0 );
+
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-symmetric dense matrix
+ StaticMatrix<double,3UL,3UL> D( 3.0, 7.0, -2.0,
+ 8.0, 0.0, -1.0,
+ -2.0, -1.0, 4.0 );
+
+ C = D; // Throws an exception; symmetric invariant would be violated!
+ \endcode
+
+// The same restriction also applies to the \c append() function for sparse matrices: Appending
+// the element \f$ a_{ij} \f$ additionally inserts the element \f$ a_{ji} \f$ into the matrix.
+// Despite the additional insertion, the \c append() function still provides the most efficient
+// way to set up a symmetric sparse matrix. In order to achieve the maximum efficiency, the
+// capacity of the individual rows/columns of the matrix should to be specifically prepared with
+// \c reserve() calls:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+
+ // Setup of the symmetric matrix
+ //
+ // ( 0 1 3 )
+ // A = ( 1 2 0 )
+ // ( 3 0 0 )
+ //
+ SymmetricMatrix< CompressedMatrix<double,rowMajor> > A( 3 );
+
+ A.reserve( 5 ); // Reserving enough space for 5 non-zero elements
+ A.reserve( 0, 2 ); // Reserving two non-zero elements in the first row
+ A.reserve( 1, 2 ); // Reserving two non-zero elements in the second row
+ A.reserve( 2, 1 ); // Reserving a single non-zero element in the third row
+ A.append( 0, 1, 1.0 ); // Appending the value 1 at position (0,1) and (1,0)
+ A.append( 1, 1, 2.0 ); // Appending the value 2 at position (1,1)
+ A.append( 2, 0, 3.0 ); // Appending the value 3 at position (2,0) and (0,2)
+ \endcode
+
+// The symmetry property is also enforced for symmetric custom matrices: In case the given array
+// of elements does not represent a symmetric matrix, a \a std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef SymmetricMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomSymmetric;
+
+ // Creating a 3x3 symmetric custom matrix from a properly initialized array
+ double array[9] = { 1.0, 2.0, 4.0,
+ 2.0, 3.0, 5.0,
+ 4.0, 5.0, 6.0 };
+ CustomSymmetric A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 symmetric custom matrix from an uninitialized array
+ CustomSymmetric B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the symmetry property is enforced for views (rows, columns, submatrices, ...) on the
+// symmetric matrix. The following example demonstrates that modifying the elements of an entire
+// row of the symmetric matrix also affects the counterpart elements in the according column of
+// the matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Setup of the symmetric matrix
+ //
+ // ( 0 1 0 2 )
+ // A = ( 1 3 4 0 )
+ // ( 0 4 0 5 )
+ // ( 2 0 5 0 )
+ //
+ SymmetricMatrix< DynamicMatrix<int> > A( 4 );
+ A(0,1) = 1;
+ A(0,3) = 2;
+ A(1,1) = 3;
+ A(1,2) = 4;
+ A(2,3) = 5;
+
+ // Setting all elements in the 1st row to 0 results in the matrix
+ //
+ // ( 0 0 0 2 )
+ // A = ( 0 0 0 0 )
+ // ( 0 0 0 5 )
+ // ( 2 0 5 0 )
+ //
+ row( A, 1 ) = 0;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to submatrices of symmetric matrices.
+// Since the modification of element \f$ a_{ij} \f$ of a symmetric matrix also modifies the
+// element \f$ a_{ji} \f$, the matrix to be assigned must be structured such that the symmetry
+// of the symmetric matrix is preserved. Otherwise a \a std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Setup of two default 4x4 symmetric matrices
+ SymmetricMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 1 2 )
+ // B = ( 3 4 )
+ // ( 5 6 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL );
+ B(0,0) = 1;
+ B(0,1) = 2;
+ B(1,0) = 3;
+ B(1,1) = 4;
+ B(2,1) = 5;
+ B(2,2) = 6;
+
+ // OK: Assigning B to a submatrix of A1 such that the symmetry can be preserved
+ //
+ // ( 0 0 1 2 )
+ // A1 = ( 0 0 3 4 )
+ // ( 1 3 5 6 )
+ // ( 2 4 6 0 )
+ //
+ submatrix( A1, 0UL, 2UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the symmetry cannot be preserved!
+ // The elements marked with X cannot be assigned unambiguously!
+ //
+ // ( 0 1 2 0 )
+ // A2 = ( 1 3 X 0 )
+ // ( 2 X 6 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection symmetricmatrix_initialization The Elements of a Dense Symmetric Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency (especially in case all default values are
+// overridden afterwards), this property is important since otherwise the symmetric property of
+// dense symmetric matrices could not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // Default initialized, 5x5 row-major symmetric dynamic matrix
+ SymmetricMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \section symmetricmatrix_arithmetic_operations Arithmetic Operations
+//
+// A SymmetricMatrix can participate in numerical operations in any way any other dense or sparse
+// matrix can participate. It can also be combined with any other dense or sparse vector or matrix.
+// The following code example gives an impression of the use of SymmetricMatrix within arithmetic
+// operations:
+
+ \code
+ using blaze::SymmetricMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ SymmetricMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ SymmetricMatrix< HybridMatrix<double,3UL,3UL,rowMajor> > E;
+ SymmetricMatrix< StaticMatrix<double,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major symmetric matrix
+ F = C - D; // Matrix subtraction and assignment to a column-major symmetric matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section symmetricmatrix_block_structured Block-Structured Symmetric Matrices
+//
+// It is also possible to use block-structured symmetric matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Definition of a 5x5 block-structured symmetric matrix based on CompressedMatrix
+ SymmetricMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > A( 5 );
+ \endcode
+
+// Also in this case, the SymmetricMatrix class template enforces the invariant of symmetry and
+// guarantees that a modifications of element \f$ a_{ij} \f$ of the adapted matrix is also
+// applied to element \f$ a_{ji} \f$:
+
+ \code
+ // Inserting the elements (2,4) and (4,2)
+ A.insert( 2, 4, StaticMatrix<int,3UL,3UL>( { { 1, -4, 5 },
+ { 6, 8, -3 },
+ { 2, -1, 2 } } ) );
+
+ // Manipulating the elements (2,4) and (4,2)
+ A(2,4)(1,1) = -5;
+ \endcode
+
+// \n \section symmetricmatrix_performance Performance Considerations
+//
+// When the symmetric property of a matrix is known beforehands using the SymmetricMatrix adaptor
+// instead of a general matrix can be a considerable performance advantage. The \b Blaze library
+// tries to exploit the properties of symmetric matrices whenever possible. However, there are
+// also situations when using a symmetric matrix introduces some overhead. The following examples
+// demonstrate several situations where symmetric matrices can positively or negatively impact
+// performance.
+//
+// \n \subsection symmetricmatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is symmetric, \b Blaze can exploit the fact
+// that \f$ A = A^T \f$ and choose the fastest and most suited combination of storage orders for the
+// multiplication. The following example demonstrates this by means of a dense matrix/sparse matrix
+// multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > A;
+ SymmetricMatrix< CompressedMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// Intuitively, the chosen combination of a row-major and a column-major matrix is the most suited
+// for maximum performance. However, \b Blaze evaluates the multiplication as
+
+ \code
+ C = A * trans( B );
+ \endcode
+
+// which significantly increases the performance since in contrast to the original formulation the
+// optimized form can be vectorized. Therefore, in the context of matrix multiplications, using the
+// SymmetricMatrix adapter is obviously an advantage.
+//
+// \n \subsection symmetricmatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar optimization is possible in case of matrix/vector multiplications:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ SymmetricMatrix< DynamicMatrix<double,rowMajor> > A;
+ CompressedVector<double,columnVector> x;
+ DynamicVector<double,columnVector> y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example it is not intuitively apparent that using a row-major matrix is not the best
+// possible choice in terms of performance since the computation cannot be vectorized. Choosing
+// a column-major matrix instead, however, would enable a vectorized computation. Therefore
+// \b Blaze exploits the fact that \c A is symmetric, selects the best suited storage order and
+// evaluates the multiplication as
+
+ \code
+ y = trans( A ) * x;
+ \endcode
+
+// which also significantly increases the performance.
+//
+// \n \subsection symmetricmatrix_views Positive Impact: Row/Column Views on Column/Row-Major Matrices
+//
+// Another example is the optimization of a row view on a column-major symmetric matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef SymmetricMatrix< DynamicMatrix<double,columnMajor> > DynamicSymmetric;
+
+ DynamicSymmetric A( 10UL );
+ Row<DynamicSymmetric> row5 = row( A, 5UL );
+ \endcode
+
+// Usually, a row view on a column-major matrix results in a considerable performance decrease in
+// comparison to a row view on a row-major matrix due to the non-contiguous storage of the matrix
+// elements. However, in case of symmetric matrices, \b Blaze instead uses the according column of
+// the matrix, which provides the same performance as if the matrix would be row-major. Note that
+// this also works for column views on row-major matrices, where \b Blaze can use the according
+// row instead of a column in order to provide maximum performance.
+//
+// \n \subsection symmetricmatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a symmetric matrix on the right-hand side of an assignment (i.e. for read
+// access), which introduces absolutely no performance penalty, using a symmetric matrix on the
+// left-hand side of an assignment (i.e. for write access) may introduce additional overhead when
+// it is assigned a general matrix, which is not symmetric at compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ SymmetricMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the symmetric matrix; no performance penalty
+ C = A; // Assignment of a symmetric matrix to another symmetric matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to a symmetric matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not symmetric matrix to a symmetric matrix it is necessary
+// to check whether the matrix is symmetric at runtime in order to guarantee the symmetry property
+// of the symmetric matrix. In case it turns out to be symmetric, it is assigned as efficiently as
+// possible, if it is not, an exception is thrown. In order to prevent this runtime overhead it is
+// therefore generally advisable to assign symmetric matrices to other symmetric matrices.\n
+// In this context it is especially noteworthy that in contrast to additions and subtractions the
+// multiplication of two symmetric matrices does not necessarily result in another symmetric matrix:
+
+ \code
+ SymmetricMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in a symmetric matrix; no runtime overhead
+ C = A - B; // Results in a symmetric matrix; no runtime overhead
+ C = A * B; // Is not guaranteed to result in a symmetric matrix; some runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value // Density flag
+ , bool NF = IsNumericMatrix<MT>::value > // Numeric flag
+class SymmetricMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNonNumeric.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNonNumeric.h
new file mode 100644
index 00000000..70adac5d
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNonNumeric.h
@@ -0,0 +1,2650 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/DenseNonNumeric.h
+// \brief SymmetricMatrix specialization for dense matrices with non-numeric element type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_DENSENONNUMERIC_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_DENSENONNUMERIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/symmetricmatrix/BaseTemplate.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsCustom.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES WITH NON-NUMERIC ELEMENT TYPE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of SymmetricMatrix for dense matrices with non-numeric element type.
+// \ingroup symmetric_matrix
+//
+// This specialization of SymmetricMatrix adapts the class template to the requirements of dense
+// matrices with non-numeric data type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class SymmetricMatrix<MT,SO,true,false>
+ : public DenseMatrix< SymmetricMatrix<MT,SO,true,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SymmetricMatrix<MT,SO,true,false> This; //!< Type of this SymmetricMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this SymmetricMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef SymmetricMatrix<OT,!SO,true,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef SymmetricMatrix<TT,!SO,true,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a SymmetricMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other SymmetricMatrix.
+ typedef SymmetricMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**MatrixIterator class definition*************************************************************
+ /*!\brief Iterator over the elements of the dense symmetric matrix.
+ */
+ template< typename MatrixType > // Type of the adapted dense matrix
+ class MatrixIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Return type for the access to the value of a dense matrix element.
+ typedef If_< IsConst<MatrixType>
+ , ConstReference_<MatrixType>
+ , Reference_<MatrixType> > Reference;
+
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef RemoveReference_<Reference> ValueType; //!< Type of the underlying elements.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef Reference ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the MatrixIterator class.
+ */
+ inline MatrixIterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the MatrixIterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline MatrixIterator( MatrixType& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row index of the iterator
+ , column_( column ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Conversion constructor*******************************************************************
+ /*!\brief Conversion constructor from different MatrixIterator instances.
+ //
+ // \param it The row iterator to be copied.
+ */
+ template< typename MatrixType2 >
+ inline MatrixIterator( const MatrixIterator<MatrixType2>& it ) noexcept
+ : matrix_( it.matrix_ ) // Reference to the adapted dense matrix
+ , row_ ( it.row_ ) // The current row index of the iterator
+ , column_( it.column_ ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline MatrixIterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline MatrixIterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline MatrixIterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const MatrixIterator operator++( int ) noexcept {
+ const MatrixIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline MatrixIterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const MatrixIterator operator--( int ) noexcept {
+ const MatrixIterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ if( ( SO && row_ < column_ ) || ( !SO && row_ > column_ ) )
+ return (*matrix_)(row_,column_);
+ else
+ return (*matrix_)(column_,row_);
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ if( ( SO && row_ < column_ ) || ( !SO && row_ > column_ ) )
+ return &(*matrix_)(row_,column_);
+ else
+ return &(*matrix_)(column_,row_);
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two MatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator==( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
+ return ( SO )?( row_ == rhs.row_ ):( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two MatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ template< typename MatrixType2 >
+ inline bool operator!=( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
+ return ( SO )?( row_ != rhs.row_ ):( column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two MatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator<( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
+ return ( SO )?( row_ < rhs.row_ ):( column_ < rhs.column_ );
+ return ( column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two MatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator>( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
+ return ( SO )?( row_ > rhs.row_ ):( column_ > rhs.column_ );
+ return ( column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two MatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator<=( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
+ return ( SO )?( row_ <= rhs.row_ ):( column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two MatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator>=( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
+ return ( SO )?( row_ >= rhs.row_ ):( column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const MatrixIterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a MatrixIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const MatrixIterator operator+( const MatrixIterator& it, size_t inc ) noexcept {
+ if( SO )
+ return MatrixIterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return MatrixIterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a MatrixIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const MatrixIterator operator+( size_t inc, const MatrixIterator& it ) noexcept {
+ if( SO )
+ return MatrixIterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return MatrixIterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a MatrixIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const MatrixIterator operator-( const MatrixIterator& it, size_t dec ) noexcept {
+ if( SO )
+ return MatrixIterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return MatrixIterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MatrixType* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row index of the iterator.
+ size_t column_; //!< The current column index of the iterator.
+ //*******************************************************************************************
+
+ //**Friend declarations**********************************************************************
+ template< typename MatrixType2 > friend class MatrixIterator;
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ typedef MatrixIterator<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef MatrixIterator<const MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable && !IsSMPAssignable<ET>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline SymmetricMatrix();
+ explicit inline SymmetricMatrix( size_t n );
+
+ explicit inline SymmetricMatrix( ElementType* ptr, size_t n );
+ explicit inline SymmetricMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline SymmetricMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline SymmetricMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline SymmetricMatrix( const SymmetricMatrix& m );
+ inline SymmetricMatrix( SymmetricMatrix&& m ) noexcept;
+
+ template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,SO>& m );
+ template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,!SO>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline SymmetricMatrix& operator=( const SymmetricMatrix& rhs );
+ inline SymmetricMatrix& operator=( SymmetricMatrix&& rhs ) noexcept;
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator+=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator-=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline SymmetricMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, SymmetricMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, SymmetricMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ inline SymmetricMatrix& transpose();
+ inline SymmetricMatrix& ctranspose();
+ template< typename Other > inline SymmetricMatrix& scale( const Other& scalar );
+ inline void swap( SymmetricMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename MT2 > inline void assign ( DenseMatrix <MT2,SO>& rhs );
+ template< typename MT2 > inline void assign ( const DenseMatrix <MT2,SO>& rhs );
+ template< typename MT2 > inline void assign ( const SparseMatrix<MT2,SO>& rhs );
+ template< typename MT2 > inline void addAssign( const DenseMatrix <MT2,SO>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,SO>& rhs );
+ template< typename MT2 > inline void subAssign( const DenseMatrix <MT2,SO>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool NF2 >
+ friend bool isDefault( const SymmetricMatrix<MT2,SO2,DF2,NF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_NUMERIC_TYPE ( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for SymmetricMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( size_t n )
+ : matrix_( n, n ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of symmetric custom matrix.
+//
+// This constructor creates an unpadded symmetric custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a symmetric matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded symmetric custom matrices!
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of symmetric custom matrix.
+//
+// This constructor creates a symmetric custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a symmetric matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of symmetric custom matrix.
+//
+// This constructor creates an unpadded symmetric custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a symmetric matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded symmetric custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of symmetric custom matrix.
+//
+// This constructor creates a symmetric custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a symmetric matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for SymmetricMatrix.
+//
+// \param m The symmetric matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( const SymmetricMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for SymmetricMatrix.
+//
+// \param m The symmetric matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( SymmetricMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices with the same storage order.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
+// given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the foreign matrix
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( const Matrix<MT2,SO>& m )
+ : matrix_() // The adapted dense matrix
+{
+ using blaze::resize;
+
+ typedef RemoveAdaptor_<ResultType_<MT2> > RT;
+ typedef If_< IsComputation<MT2>, RT, const MT2& > Tmp;
+
+ if( IsSymmetric<MT2>::value ) {
+ resize( matrix_, (~m).rows(), (~m).columns() );
+ assign( ~m );
+ }
+ else {
+ Tmp tmp( ~m );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.rows() );
+ assign( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices with opposite storage order.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
+// given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the foreign matrix
+inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( const Matrix<MT2,!SO>& m )
+ : matrix_() // The adapted dense matrix
+{
+ using blaze::resize;
+
+ typedef RemoveAdaptor_< ResultType_<MT2> > RT;
+ typedef If_< IsComputation<MT2>, RT, const MT2& > Tmp;
+
+ if( IsSymmetric<MT2>::value ) {
+ resize( matrix_, (~m).rows(), (~m).columns() );
+ assign( trans( ~m ) );
+ }
+ else {
+ Tmp tmp( ~m );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.rows() );
+ assign( trans( tmp ) );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::Reference
+ SymmetricMatrix<MT,SO,true,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ if( ( !SO && i > j ) || ( SO && i < j ) )
+ return matrix_(i,j);
+ else
+ return matrix_(j,i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::ConstReference
+ SymmetricMatrix<MT,SO,true,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ if( ( !SO && i > j ) || ( SO && i < j ) )
+ return matrix_(i,j);
+ else
+ return matrix_(j,i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::Reference
+ SymmetricMatrix<MT,SO,true,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::ConstReference
+ SymmetricMatrix<MT,SO,true,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the symmetric matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The symmetric matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function. Also note that you can NOT assume that the symmetric matrix stores all its
+// elements. It may choose to store its elements in a lower or upper triangular matrix fashion.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::ConstPointer
+ SymmetricMatrix<MT,SO,true,false>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+// Note that you can NOT assume that the symmetric matrix stores all its elements. It may choose
+// to store its elements in a lower or upper triangular matrix fashion.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::ConstPointer
+ SymmetricMatrix<MT,SO,true,false>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::Iterator
+ SymmetricMatrix<MT,SO,true,false>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::ConstIterator
+ SymmetricMatrix<MT,SO,true,false>::begin( size_t i ) const
+{
+ if( SO )
+ return ConstIterator( matrix_, 0UL, i );
+ else
+ return ConstIterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::ConstIterator
+ SymmetricMatrix<MT,SO,true,false>::cbegin( size_t i ) const
+{
+ if( SO )
+ return ConstIterator( matrix_, 0UL, i );
+ else
+ return ConstIterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::Iterator
+ SymmetricMatrix<MT,SO,true,false>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::ConstIterator
+ SymmetricMatrix<MT,SO,true,false>::end( size_t i ) const
+{
+ if( SO )
+ return ConstIterator( matrix_, rows(), i );
+ else
+ return ConstIterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,false>::ConstIterator
+ SymmetricMatrix<MT,SO,true,false>::cend( size_t i ) const
+{
+ if( SO )
+ return ConstIterator( matrix_, rows(), i );
+ else
+ return ConstIterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for SymmetricMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>&
+ SymmetricMatrix<MT,SO,true,false>::operator=( const SymmetricMatrix& rhs )
+{
+ using blaze::resize;
+
+ if( &rhs == this ) return *this;
+
+ resize( matrix_, rhs.rows(), rhs.columns() );
+ assign( rhs );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for SymmetricMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>&
+ SymmetricMatrix<MT,SO,true,false>::operator=( SymmetricMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,false>& >
+ SymmetricMatrix<MT,SO,true,false>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::resize;
+
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ if( (~rhs).isAliased( this ) ) {
+ SymmetricMatrix tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( matrix_, (~rhs).rows(), (~rhs).columns() );
+ if( IsSparseMatrix<MT2>::value )
+ reset();
+ assign( ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,false>& >
+ SymmetricMatrix<MT,SO,true,false>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::resize;
+
+ typedef If_< IsSymmetric<MT2>, CompositeType_<MT2>, ResultType_<MT2> > Tmp;
+
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ Tmp tmp( ~rhs );
+
+ if( !IsSymmetric<Tmp>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( !tmp.canAlias( this ), "Aliasing detected" );
+
+ resize( matrix_, tmp.rows(), tmp.columns() );
+ if( IsSparseMatrix<Tmp>::value )
+ reset();
+ assign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrices with opposite storage order.
+//
+// \param rhs The right-hand side matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,true,false>&
+ SymmetricMatrix<MT,SO,true,false>::operator=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,false>& >
+ SymmetricMatrix<MT,SO,true,false>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ addAssign( ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,false>& >
+ SymmetricMatrix<MT,SO,true,false>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ typedef If_< IsSymmetric<MT2>, CompositeType_<MT2>, ResultType_<MT2> > Tmp;
+
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ Tmp tmp( ~rhs );
+
+ if( !IsSymmetric<Tmp>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( !tmp.canAlias( this ), "Aliasing detected" );
+
+ addAssign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix with opposite storage order
+// (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,true,false>&
+ SymmetricMatrix<MT,SO,true,false>::operator+=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator+=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,false>& >
+ SymmetricMatrix<MT,SO,true,false>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ subAssign( ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,false>& >
+ SymmetricMatrix<MT,SO,true,false>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ typedef If_< IsSymmetric<MT2>, CompositeType_<MT2>, ResultType_<MT2> > Tmp;
+
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ Tmp tmp( ~rhs );
+
+ if( !IsSymmetric<Tmp>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( !tmp.canAlias( this ), "Aliasing detected" );
+
+ subAssign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix with opposite storage
+// order (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,true,false>&
+ SymmetricMatrix<MT,SO,true,false>::operator-=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator-=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a symmetric matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,true,false>&
+ SymmetricMatrix<MT,SO,true,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ using blaze::resize;
+
+ typedef MultTrait_< MT, ResultType_<MT2> > Tmp;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( Tmp );
+
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ Tmp tmp( (*this) * ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.columns() );
+ assign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, SymmetricMatrix<MT,SO,true,false> >&
+ SymmetricMatrix<MT,SO,true,false>::operator*=( Other rhs )
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) *= rhs;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) *= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, SymmetricMatrix<MT,SO,true,false> >&
+ SymmetricMatrix<MT,SO,true,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) /= rhs;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e.
+// the total number of elements of a row/column. In case the symmetric matrix adapts a
+// \a rowMajor dense matrix the function returns the spacing between two rows, in case
+// it adapts a \a columnMajor dense matrix the function returns the spacing between two
+// columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,false>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the symmetric
+// matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor dense matrix the function returns the capacity of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the symmetric matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,false>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ if( SO )
+ {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ if( !isDefault( matrix_(i,j) ) )
+ nonzeros += 2UL;
+ }
+ if( !isDefault( matrix_(j,j) ) )
+ ++nonzeros;
+ }
+ }
+ else
+ {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !isDefault( matrix_(i,j) ) )
+ nonzeros += 2UL;
+ }
+ if( !isDefault( matrix_(i,i) ) )
+ ++nonzeros;
+ }
+ }
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column. In
+// case the symmetric matrix adapts a \a rowMajor dense matrix the function returns the number of
+// non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix the function
+// returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,false>::nonZeros( size_t i ) const
+{
+ size_t nonzeros( 0UL );
+
+ if( SO )
+ {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !isDefault( matrix_(j,i) ) )
+ ++nonzeros;
+ }
+ for( size_t j=i; j<rows(); ++j ) {
+ if( !isDefault( matrix_(i,j) ) )
+ ++nonzeros;
+ }
+ }
+ else
+ {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !isDefault( matrix_(i,j) ) )
+ ++nonzeros;
+ }
+ for( size_t j=i; j<rows(); ++j ) {
+ if( !isDefault( matrix_(j,i) ) )
+ ++nonzeros;
+ }
+ }
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::reset()
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ clear( matrix_(i,j) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row \b and column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row \b and column to their default value.
+// The following example demonstrates this by means of a \f$ 5 \times 5 \f$ symmetric matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::StaticVector;
+ using blaze::SymmetricMatrix;
+
+ SymmetricMatrix< DynamicMatrix< StaticVector<int,1UL> > > A;
+
+ // Initializing the symmetric matrix A to
+ //
+ // ( ( ) ( 2 ) ( 5 ) ( -4 ) ( ) )
+ // ( ( 2 ) ( 1 ) ( -3 ) ( 7 ) ( ) )
+ // A = ( ( 5 ) ( -3 ) ( 8 ) ( -1 ) ( -2 ) )
+ // ( ( -4 ) ( 7 ) ( -1 ) ( ) ( -6 ) )
+ // ( ( ) ( 0 ) ( -2 ) ( -6 ) ( 1 ) )
+ // ...
+
+ // Resetting the 1st row/column results in the matrix
+ //
+ // ( ( ) ( ) ( 5 ) ( -4 ) ( ) )
+ // ( ( ) ( ) ( ) ( ) ( ) )
+ // A = ( ( 5 ) ( ) ( 8 ) ( -1 ) ( -2 ) )
+ // ( ( -4 ) ( ) ( -1 ) ( ) ( -6 ) )
+ // ( ( ) ( ) ( -2 ) ( -6 ) ( 1 ) )
+ //
+ A.reset( 1UL );
+ \endcode
+
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::reset( size_t i )
+{
+ using blaze::clear;
+
+ for( Iterator element=begin(i); element!=end(i); ++element )
+ clear( *element );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the symmetric matrix.
+//
+// \return void
+//
+// This function clears the symmetric matrix and returns it to its default state. The function has
+// the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
+// matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
+// to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
+// be reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the symmetric matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the symmetric matrix adapts a resizable matrix, this function resizes the matrix using
+// the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
+// in case the capacity of the matrix is too small. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, the resize operation potentially changes all matrix elements. In order
+// to preserve the old matrix values, the \a preserve flag can be set to \a true. In case the
+// size of the matrix is increased, new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void SymmetricMatrix<MT,SO,true,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize ) {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, 0UL, oldsize, oldsize, increment ).reset();
+ submatrix( matrix_, oldsize, 0UL, increment, n ).reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the symmetric matrix.
+// \return void
+//
+// This function increases the capacity of the symmetric matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the symmetric matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>& SymmetricMatrix<MT,SO,true,false>::transpose()
+{
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the symmetric matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,false>& SymmetricMatrix<MT,SO,true,false>::ctranspose()
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ conjugate( matrix_(i,j) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ conjugate( matrix_(i,j) );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the scalar value
+inline SymmetricMatrix<MT,SO,true,false>&
+ SymmetricMatrix<MT,SO,true,false>::scale( const Other& scalar )
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) *= scalar;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::swap( SymmetricMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the symmetric matrix are intact.
+//
+// \return \a true in case the symmetric matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the symmetric matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool SymmetricMatrix<MT,SO,true,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return isIntact( matrix_ ) &&
+ ( IsCustom<MT>::value || ( SO ? isUpper( matrix_ ) : isLower( matrix_ ) ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool SymmetricMatrix<MT,SO,true,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool SymmetricMatrix<MT,SO,true,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool SymmetricMatrix<MT,SO,true,false>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool SymmetricMatrix<MT,SO,true,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Optimized implementation of the assignment of a temporary dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::assign( DenseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) = std::move( (~rhs)(i,j) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) = std::move( (~rhs)(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::assign( const DenseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) = (~rhs)(i,j);
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) = (~rhs)(i,j);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void SymmetricMatrix<MT,SO,true,false>::assign( const SparseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> ConstIterator;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ const ConstIterator last( (~rhs).upperBound(j,j) );
+ for( ConstIterator element=(~rhs).begin(j); element!=last; ++element )
+ matrix_(element->index(),j) = element->value();
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const ConstIterator last( (~rhs).upperBound(i,i) );
+ for( ConstIterator element=(~rhs).begin(i); element!=last; ++element )
+ matrix_(i,element->index()) = element->value();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::addAssign( const DenseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) += (~rhs)(i,j);
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) += (~rhs)(i,j);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void SymmetricMatrix<MT,SO,true,false>::addAssign( const SparseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> ConstIterator;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ const ConstIterator last( (~rhs).upperBound(j,j) );
+ for( ConstIterator element=(~rhs).begin(j); element!=last; ++element )
+ matrix_(element->index(),j) += element->value();
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const ConstIterator last( (~rhs).upperBound(i,i) );
+ for( ConstIterator element=(~rhs).begin(i); element!=last; ++element )
+ matrix_(i,element->index()) += element->value();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void SymmetricMatrix<MT,SO,true,false>::subAssign( const DenseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) -= (~rhs)(i,j);
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=0UL; j<=i; ++j )
+ matrix_(i,j) -= (~rhs)(i,j);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void SymmetricMatrix<MT,SO,true,false>::subAssign( const SparseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> ConstIterator;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ const ConstIterator last( (~rhs).upperBound(j,j) );
+ for( ConstIterator element=(~rhs).begin(j); element!=last; ++element )
+ matrix_(element->index(),j) -= element->value();
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const ConstIterator last( (~rhs).upperBound(i,i) );
+ for( ConstIterator element=(~rhs).begin(i); element!=last; ++element )
+ matrix_(i,element->index()) -= element->value();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNumeric.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNumeric.h
new file mode 100644
index 00000000..228f565a
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNumeric.h
@@ -0,0 +1,2970 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/DenseNumeric.h
+// \brief SymmetricMatrix specialization for dense matrices with numeric element type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_DENSENUMERIC_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_DENSENUMERIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/symmetricmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/symmetricmatrix/NumericProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Column.h>
+#include <blaze/math/views/Row.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES WITH NUMERIC ELEMENT TYPE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of SymmetricMatrix for dense matrices with numeric element type.
+// \ingroup symmetric_matrix
+//
+// This specialization of SymmetricMatrix adapts the class template to the requirements of dense
+// matrices with numeric element type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class SymmetricMatrix<MT,SO,true,true>
+ : public DenseMatrix< SymmetricMatrix<MT,SO,true,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SymmetricMatrix<MT,SO,true,true> This; //!< Type of this SymmetricMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this SymmetricMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef SymmetricMatrix<OT,!SO,true,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef SymmetricMatrix<TT,!SO,true,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef NumericProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a SymmetricMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other SymmetricMatrix.
+ typedef SymmetricMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense symmetric matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef NumericProxy<MT> PointerType; //!< Pointer return type.
+ typedef NumericProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row index of the iterator
+ , column_( column ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) noexcept {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Store function***************************************************************************
+ /*!\brief Store of a SIMD element at the current iterator position.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs a store of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void store( const SIMDType& value ) const {
+ (*matrix_).store( row_, column_, value );
+ sync();
+ }
+ //*******************************************************************************************
+
+ //**Storea function**************************************************************************
+ /*!\brief Aligned store of a SIMD element at the current iterator position.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned store of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void storea( const SIMDType& value ) const {
+ (*matrix_).storea( row_, column_, value );
+ sync();
+ }
+ //*******************************************************************************************
+
+ //**Storeu function**************************************************************************
+ /*!\brief Unaligned store of a SIMD element at the current iterator position.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an unaligned store of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void storeu( const SIMDType& value ) const {
+ (*matrix_).storeu( row_, column_, value );
+ sync();
+ }
+ //*******************************************************************************************
+
+ //**Stream function**************************************************************************
+ /*!\brief Aligned, non-temporal store of a SIMD element at the current iterator position.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned, non-temporal store of the current SIMD element at the
+ // current iterator position. This function must \b NOT be called explicitly! It is used
+ // internally for the performance optimized evaluation of expression templates. Calling
+ // this function explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void stream( const SIMDType& value ) const {
+ (*matrix_).stream( row_, column_, value );
+ sync();
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Sync function****************************************************************************
+ /*!\brief Synchronizes several paired elements after a SIMD assignment.
+ //
+ // \return void
+ */
+ void sync() const {
+ if( SO ) {
+ const size_t kend( min( row_+SIMDSIZE, (*matrix_).rows() ) );
+ for( size_t k=row_; k<kend; ++k )
+ (*matrix_)(column_,k) = (*matrix_)(k,column_);
+ }
+ else {
+ const size_t kend( min( column_+SIMDSIZE, (*matrix_).columns() ) );
+ for( size_t k=column_; k<kend; ++k )
+ (*matrix_)(k,row_) = (*matrix_)(row_,k);
+ }
+ }
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row index of the iterator.
+ size_t column_; //!< The current column index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline SymmetricMatrix();
+ explicit inline SymmetricMatrix( size_t n );
+ explicit inline SymmetricMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline SymmetricMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline SymmetricMatrix( const Other (&array)[N][N] );
+
+ explicit inline SymmetricMatrix( ElementType* ptr, size_t n );
+ explicit inline SymmetricMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline SymmetricMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline SymmetricMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline SymmetricMatrix( const SymmetricMatrix& m );
+ inline SymmetricMatrix( SymmetricMatrix&& m ) noexcept;
+
+ template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,SO>& m );
+ template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,!SO>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline SymmetricMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline SymmetricMatrix& operator=( const Other (&array)[N][N] );
+
+ inline SymmetricMatrix& operator=( const SymmetricMatrix& rhs );
+ inline SymmetricMatrix& operator=( SymmetricMatrix&& rhs ) noexcept;
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator+=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator-=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline SymmetricMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, SymmetricMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, SymmetricMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ inline SymmetricMatrix& transpose();
+ inline SymmetricMatrix& ctranspose();
+ template< typename Other > inline SymmetricMatrix& scale( const Other& scalar );
+ inline void swap( SymmetricMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ inline void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ inline void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ inline void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ inline void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ET>::size };
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool NF2 >
+ friend bool isDefault( const SymmetricMatrix<MT2,SO2,DF2,NF2>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert2x2( SymmetricMatrix<MT2,SO2,true,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert3x3( SymmetricMatrix<MT2,SO2,true,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert4x4( SymmetricMatrix<MT2,SO2,true,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert5x5( SymmetricMatrix<MT2,SO2,true,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invert6x6( SymmetricMatrix<MT2,SO2,true,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invertByLU( SymmetricMatrix<MT2,SO2,true,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invertByLDLT( SymmetricMatrix<MT2,SO2,true,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invertByLDLH( SymmetricMatrix<MT2,SO2,true,true>& m );
+
+ template< typename MT2, bool SO2 >
+ friend void invertByLLH( SymmetricMatrix<MT2,SO2,true,true>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for SymmetricMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( size_t n )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the symmetric
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::SymmetricMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A{ { 1, 4, 5 },
+ { 4, 2, -6 },
+ { 5, -6, 3 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all symmetric matrix elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor offers the option to directly initialize the elements of the symmetric matrix
+// with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[16];
+ // ... Initialization of the dynamic array
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<int,rowMajor> > v( 4UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized accoring to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a n by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also, in
+// case the given array does not represent a symmetric matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all symmetric matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor offers the option to directly initialize the elements of the symmetric matrix
+// with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 4, 5 },
+ { 4, 2, -6 },
+ { 5, -6, 3 } };
+ blaze::SymmetricMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of symmetric custom matrix.
+//
+// This constructor creates an unpadded symmetric custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a symmetric matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded symmetric custom matrices!
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of symmetric custom matrix.
+//
+// This constructor creates a symmetric custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a symmetric matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of symmetric custom matrix.
+//
+// This constructor creates an unpadded symmetric custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a symmetric matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded symmetric custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of symmetric custom matrix.
+//
+// This constructor creates a symmetric custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a symmetric matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for SymmetricMatrix.
+//
+// \param m The symmetric matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( const SymmetricMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for SymmetricMatrix.
+//
+// \param m The symmetric matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( SymmetricMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices with the same storage order.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
+// given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the foreign matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( const Matrix<MT2,SO>& m )
+ : matrix_( ~m ) // The adapted dense matrix
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices with opposite storage order.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
+// given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the foreign matrix
+inline SymmetricMatrix<MT,SO,true,true>::SymmetricMatrix( const Matrix<MT2,!SO>& m )
+ : matrix_( trans( ~m ) ) // The adapted dense matrix
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::Reference
+ SymmetricMatrix<MT,SO,true,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::ConstReference
+ SymmetricMatrix<MT,SO,true,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::Reference
+ SymmetricMatrix<MT,SO,true,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::ConstReference
+ SymmetricMatrix<MT,SO,true,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the symmetric matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The symmetric matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function. Also note that you can NOT assume that the symmetric matrix stores all its
+// elements. It may choose to store its elements in a lower or upper triangular matrix fashion.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::ConstPointer
+ SymmetricMatrix<MT,SO,true,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+// Note that you can NOT assume that the symmetric matrix stores all its elements. It may choose
+// to store its elements in a lower or upper triangular matrix fashion.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::ConstPointer
+ SymmetricMatrix<MT,SO,true,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::Iterator
+ SymmetricMatrix<MT,SO,true,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::ConstIterator
+ SymmetricMatrix<MT,SO,true,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::ConstIterator
+ SymmetricMatrix<MT,SO,true,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::Iterator
+ SymmetricMatrix<MT,SO,true,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::ConstIterator
+ SymmetricMatrix<MT,SO,true,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,true,true>::ConstIterator
+ SymmetricMatrix<MT,SO,true,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the symmetric
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::SymmetricMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = { { 1, 4, 5 },
+ { 4, 2, -6 },
+ { 5, -6, 3 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all symmetric matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// This assignment operator offers the option to directly set all elements of the symmetric matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 4, 5 },
+ { 4, 2, -6 },
+ { 5, -6, 3 } };
+ blaze::SymmetricMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for SymmetricMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::operator=( const SymmetricMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for SymmetricMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::operator=( SymmetricMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,true>& >
+ SymmetricMatrix<MT,SO,true,true>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,true>& >
+ SymmetricMatrix<MT,SO,true,true>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ if( IsSymmetric<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrices with opposite storage order.
+//
+// \param rhs The right-hand side matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::operator=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,true>& >
+ SymmetricMatrix<MT,SO,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,true>& >
+ SymmetricMatrix<MT,SO,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ if( IsSymmetric<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix with opposite storage order
+// (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::operator+=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator+=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,true>& >
+ SymmetricMatrix<MT,SO,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,true,true>& >
+ SymmetricMatrix<MT,SO,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ if( IsSymmetric<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix with opposite storage
+// order (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::operator-=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator-=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a symmetric matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, SymmetricMatrix<MT,SO,true,true> >&
+ SymmetricMatrix<MT,SO,true,true>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, SymmetricMatrix<MT,SO,true,true> >&
+ SymmetricMatrix<MT,SO,true,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e.
+// the total number of elements of a row/column. In case the symmetric matrix adapts a
+// \a rowMajor dense matrix the function returns the spacing between two rows, in case
+// it adapts a \a columnMajor dense matrix the function returns the spacing between two
+// columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the symmetric
+// matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor dense matrix the function returns the capacity of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the symmetric matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column. In
+// case the symmetric matrix adapts a \a rowMajor dense matrix the function returns the number of
+// non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix the function
+// returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t SymmetricMatrix<MT,SO,true,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,true>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row \b and column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row \b and column to their default value.
+// The following example demonstrates this by means of a \f$ 5 \times 5 \f$ symmetric matrix:
+
+ \code
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<int> > A;
+
+ // Initializing the symmetric matrix A to
+ //
+ // ( 0 2 5 -4 0 )
+ // ( 2 1 -3 7 0 )
+ // A = ( 5 -3 8 -1 -2 )
+ // ( -4 7 -1 0 -6 )
+ // ( 0 0 -2 -6 1 )
+ // ...
+
+ // Resetting the 1st row/column results in the matrix
+ //
+ // ( 0 0 5 -4 0 )
+ // ( 0 0 0 0 0 )
+ // A = ( 5 0 8 -1 -2 )
+ // ( -4 0 -1 0 -6 )
+ // ( 0 0 -2 -6 1 )
+ //
+ A.reset( 1UL );
+ \endcode
+
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,true>::reset( size_t i )
+{
+ row ( matrix_, i ).reset();
+ column( matrix_, i ).reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the symmetric matrix.
+//
+// \return void
+//
+// This function clears the symmetric matrix and returns it to its default state. The function has
+// the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
+// matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
+// to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
+// be reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,true>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the symmetric matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the symmetric matrix adapts a resizable matrix, this function resizes the matrix using
+// the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
+// in case the capacity of the matrix is too small. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, the resize operation potentially changes all matrix elements. In order
+// to preserve the old matrix values, the \a preserve flag can be set to \a true. In case the
+// size of the matrix is increased, new elements are default initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 2 & 4 & 5 \\
+ 3 & 5 & 6 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & 0 \\
+ 2 & 4 & 5 & 0 \\
+ 3 & 5 & 6 & 0 \\
+ 0 & 0 & 0 & 0 \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void SymmetricMatrix<MT,SO,true,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize ) {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, 0UL, oldsize, oldsize, increment ).reset();
+ submatrix( matrix_, oldsize, 0UL, increment, n ).reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the symmetric matrix.
+// \return void
+//
+// This function increases the capacity of the symmetric matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the symmetric matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>& SymmetricMatrix<MT,SO,true,true>::transpose()
+{
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the symmetric matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline SymmetricMatrix<MT,SO,true,true>& SymmetricMatrix<MT,SO,true,true>::ctranspose()
+{
+ if( !IsBuiltin<ElementType>::value )
+ conjugate( matrix_ );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the scalar value
+inline SymmetricMatrix<MT,SO,true,true>&
+ SymmetricMatrix<MT,SO,true,true>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void SymmetricMatrix<MT,SO,true,true>::swap( SymmetricMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the symmetric matrix are intact.
+//
+// \return \a true in case the symmetric matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the symmetric matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool SymmetricMatrix<MT,SO,true,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isSymmetric( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool SymmetricMatrix<MT,SO,true,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool SymmetricMatrix<MT,SO,true,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool SymmetricMatrix<MT,SO,true,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool SymmetricMatrix<MT,SO,true,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the symmetric matrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than the
+// number of columns. Additionally, the column index (in case of a row-major matrix) or the row
+// index (in case of a column-major matrix) must be a multiple of the number of values inside
+// the SIMD element. This function must \b NOT be called explicitly! It is used internally for
+// the performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename SymmetricMatrix<MT,SO,true,true>::SIMDType
+ SymmetricMatrix<MT,SO,true,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the symmetric matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename SymmetricMatrix<MT,SO,true,true>::SIMDType
+ SymmetricMatrix<MT,SO,true,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the symmetric
+// matrix. The row index must be smaller than the number of rows and the column index must be
+// smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename SymmetricMatrix<MT,SO,true,true>::SIMDType
+ SymmetricMatrix<MT,SO,true,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void
+ SymmetricMatrix<MT,SO,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ matrix_.store( i, j, value );
+
+ if( SO ) {
+ const size_t kend( min( i+SIMDSIZE, rows() ) );
+ for( size_t k=i; k<kend; ++k )
+ matrix_(j,k) = matrix_(k,j);
+ }
+ else {
+ const size_t kend( min( j+SIMDSIZE, columns() ) );
+ for( size_t k=j; k<kend; ++k )
+ matrix_(k,i) = matrix_(i,k);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void
+ SymmetricMatrix<MT,SO,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ matrix_.storea( i, j, value );
+
+ if( SO ) {
+ const size_t kend( min( i+SIMDSIZE, rows() ) );
+ for( size_t k=i; k<kend; ++k )
+ matrix_(j,k) = matrix_(k,j);
+ }
+ else {
+ const size_t kend( min( j+SIMDSIZE, columns() ) );
+ for( size_t k=j; k<kend; ++k )
+ matrix_(k,i) = matrix_(i,k);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void
+ SymmetricMatrix<MT,SO,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ matrix_.storeu( i, j, value );
+
+ if( SO ) {
+ const size_t kend( min( i+SIMDSIZE, rows() ) );
+ for( size_t k=i; k<kend; ++k )
+ matrix_(j,k) = matrix_(k,j);
+ }
+ else {
+ const size_t kend( min( j+SIMDSIZE, columns() ) );
+ for( size_t k=j; k<kend; ++k )
+ matrix_(k,i) = matrix_(i,k);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index must
+// be smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void
+ SymmetricMatrix<MT,SO,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ matrix_.stream( i, j, value );
+
+ if( SO ) {
+ const size_t kend( min( i+SIMDSIZE, rows() ) );
+ for( size_t k=i; k<kend; ++k )
+ matrix_(j,k) = matrix_(k,j);
+ }
+ else {
+ const size_t kend( min( j+SIMDSIZE, columns() ) );
+ for( size_t k=j; k<kend; ++k )
+ matrix_(k,i) = matrix_(i,k);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/NonNumericProxy.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/NonNumericProxy.h
new file mode 100644
index 00000000..70cc0b26
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/NonNumericProxy.h
@@ -0,0 +1,650 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/NonNumericProxy.h
+// \brief Header file for the NonNumericProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_NONNUMERICPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_NONNUMERICPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for symmetric, square matrices with non-numeric element types.
+// \ingroup symmetric_matrix
+//
+// The NonNumericProxy provides controlled access to the elements of a non-const symmetric matrix
+// with non-numeric element type (e.g. vectors or matrices). It guarantees that a modification of
+// element \f$ a_{ij} \f$ of the accessed matrix is also applied to element \f$ a_{ji} \f$. The
+// following example illustrates this by means of a \f$ 3 \times 3 \f$ sparse symmetric matrix
+// with StaticVector elements:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticVector;
+ using blaze::SymmetricMatrix;
+
+ typedef StaticVector<int,3UL> Vector;
+
+ // Creating a 3x3 symmetric sparses matrix
+ SymmetricMatrix< CompressedMatrix< Vector > > A( 3UL );
+
+ A(0,2) = Vector( -2, 1 ); // ( ( 0 0 ) ( 0 0 ) ( -2 1 ) )
+ A(1,1) = Vector( 3, 4 ); // => A = ( ( 0 0 ) ( 3 4 ) ( 5 -1 ) )
+ A(1,2) = Vector( 5, -1 ); // ( ( -2 1 ) ( 5 -1 ) ( 0 0 ) )
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class NonNumericProxy : public Proxy< NonNumericProxy<MT>, ValueType_< ElementType_<MT> > >
+{
+ private:
+ //**Enumerations********************************************************************************
+ //! Compile time flag indicating whether the given matrix type is a row-major matrix.
+ enum : bool { rmm = IsRowMajorMatrix<MT>::value };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef ElementType_<MT> ET; //!< Element type of the adapted matrix.
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ValueType_<ET> RepresentedType; //!< Type of the represented matrix element.
+ typedef Reference_<ET> RawReference; //!< Raw reference to the represented element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline NonNumericProxy( MT& sm, size_t i, size_t j );
+ inline NonNumericProxy( const NonNumericProxy& nnp );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~NonNumericProxy();
+ //@}
+ //**********************************************************************************************
+
+ //**Operators***********************************************************************************
+ /*!\name Operators */
+ //@{
+ inline NonNumericProxy& operator= ( const NonNumericProxy& nnp );
+
+ template< typename T >
+ inline NonNumericProxy& operator=( initializer_list<T> list );
+
+ template< typename T >
+ inline NonNumericProxy& operator=( initializer_list< initializer_list<T> > list );
+
+ template< typename T > inline NonNumericProxy& operator= ( const T& value );
+ template< typename T > inline NonNumericProxy& operator+=( const T& value );
+ template< typename T > inline NonNumericProxy& operator-=( const T& value );
+ template< typename T > inline NonNumericProxy& operator*=( const T& value );
+ template< typename T > inline NonNumericProxy& operator/=( const T& value );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline RawReference get() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RawReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT& matrix_; //!< Reference to the adapted matrix.
+ size_t i_; //!< Row-index of the accessed matrix element.
+ size_t j_; //!< Column-index of the accessed matrix element.
+ //@}
+ //**********************************************************************************************
+
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_NUMERIC_TYPE ( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a NonNumericProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param i The row-index of the accessed matrix element.
+// \param j The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NonNumericProxy<MT>::NonNumericProxy( MT& matrix, size_t i, size_t j )
+ : matrix_( matrix ) // Reference to the adapted matrix
+ , i_ ( i ) // Row-index of the accessed matrix element
+ , j_ ( j ) // Column-index of the accessed matrix element
+{
+ const typename MT::Iterator pos( matrix_.find( i_, j_ ) );
+ const size_t index( rmm ? i_ : j_ );
+
+ if( pos == matrix_.end(index) )
+ {
+ const ElementType_<MT> element( ( RepresentedType() ) );
+ matrix_.insert( i_, j_, element );
+ if( i_ != j_ )
+ matrix_.insert( j_, i_, element );
+ }
+
+ BLAZE_INTERNAL_ASSERT( matrix_.find(i_,j_)->value() == matrix_.find(j_,i_)->value(), "Unbalance detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for NonNumericProxy.
+//
+// \param nnp Non-numeric access proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NonNumericProxy<MT>::NonNumericProxy( const NonNumericProxy& nnp )
+ : matrix_( nnp.matrix_ ) // Reference to the adapted matrix
+ , i_ ( nnp.i_ ) // Row-index of the accessed matrix element
+ , j_ ( nnp.j_ ) // Column-index of the accessed matrix element
+{
+ BLAZE_INTERNAL_ASSERT( matrix_.find(i_,j_) != matrix_.end( rmm ? i_ : j_ ), "Missing matrix element detected" );
+ BLAZE_INTERNAL_ASSERT( matrix_.find(j_,i_) != matrix_.end( rmm ? j_ : i_ ), "Missing matrix element detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The destructor for NonNumericProxy.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NonNumericProxy<MT>::~NonNumericProxy()
+{
+ const typename MT::Iterator pos( matrix_.find( i_, j_ ) );
+ const size_t index( rmm ? i_ : j_ );
+
+ if( pos != matrix_.end( index ) && isDefault( *pos->value() ) )
+ {
+ matrix_.erase( index, pos );
+ if( i_ != j_ )
+ matrix_.erase( ( rmm ? j_ : i_ ), matrix_.find( j_, i_ ) );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for NonNumericProxy.
+//
+// \param nnp Non-numeric access proxy to be copied.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NonNumericProxy<MT>& NonNumericProxy<MT>::operator=( const NonNumericProxy& nnp )
+{
+ get() = nnp.get();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the represented matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NonNumericProxy<MT>& NonNumericProxy<MT>::operator=( initializer_list<T> list )
+{
+ get() = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the represented matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NonNumericProxy<MT>& NonNumericProxy<MT>::operator=( initializer_list< initializer_list<T> > list )
+{
+ get() = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the represented matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NonNumericProxy<MT>& NonNumericProxy<MT>::operator=( const T& value )
+{
+ get() = value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the represented matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NonNumericProxy<MT>& NonNumericProxy<MT>::operator+=( const T& value )
+{
+ get() += value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the represented matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NonNumericProxy<MT>& NonNumericProxy<MT>::operator-=( const T& value )
+{
+ get() -= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the represented matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NonNumericProxy<MT>& NonNumericProxy<MT>::operator*=( const T& value )
+{
+ get() *= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the represented matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NonNumericProxy<MT>& NonNumericProxy<MT>::operator/=( const T& value )
+{
+ get() /= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returning a reference to the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename NonNumericProxy<MT>::RawReference NonNumericProxy<MT>::get() const noexcept
+{
+ const typename MT::Iterator pos( matrix_.find( i_, j_ ) );
+ BLAZE_INTERNAL_ASSERT( pos != matrix_.end( rmm ? i_ : j_ ), "Missing matrix element detected" );
+ return *pos->value();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the represented matrix element.
+//
+// \return Direct/raw reference to the represented matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NonNumericProxy<MT>::operator RawReference() const noexcept
+{
+ return get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name NonNumericProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const NonNumericProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const NonNumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const NonNumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const NonNumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const NonNumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const NonNumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const NonNumericProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial value.
+// In case the access proxy represents a vector- or matrix-like data structure that provides a
+// reset() function, this function resets all elements of the vector/matrix to the default initial
+// values.
+*/
+template< typename MT >
+inline void reset( const NonNumericProxy<MT>& proxy )
+{
+ using blaze::reset;
+
+ reset( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial state.
+// In case the access proxy represents a vector- or matrix-like data structure that provides a
+// clear() function, this function clears the vector/matrix to its default initial state.
+*/
+template< typename MT >
+inline void clear( const NonNumericProxy<MT>& proxy )
+{
+ using blaze::clear;
+
+ clear( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const NonNumericProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const NonNumericProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const NonNumericProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const NonNumericProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const NonNumericProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/NumericProxy.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/NumericProxy.h
new file mode 100644
index 00000000..f9ecbed3
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/NumericProxy.h
@@ -0,0 +1,780 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/NumericProxy.h
+// \brief Header file for the NumericProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_NUMERICPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_NUMERICPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for symmetric, square matrices with numeric element types.
+// \ingroup symmetric_matrix
+//
+// The NumericProxy provides controlled access to the elements of a non-const symmetric matrix
+// with numeric element type (e.g. integral values, floating point values, and complex values).
+// It guarantees that a modification of element \f$ a_{ij} \f$ of the accessed matrix is also
+// applied to element \f$ a_{ji} \f$. The following example illustrates this by means of a
+// \f$ 3 \times 3 \f$ dense symmetric matrix:
+
+ \code
+ // Creating a 3x3 symmetric dense matrix
+ blaze::SymmetricMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(0,2) = -2; // ( 0 0 -2 )
+ A(1,1) = 3; // => A = ( 0 3 5 )
+ A(1,2) = 5; // ( -2 5 0 )
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class NumericProxy : public Proxy< NumericProxy<MT> >
+{
+ private:
+ //**struct BuiltinType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct BuiltinType { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct ComplexType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct ComplexType { typedef typename T::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+ typedef Reference_<MT> Reference; //!< Reference to the represented element.
+ typedef ConstReference_<MT> ConstReference; //!< Reference-to-const to the represented element.
+ typedef NumericProxy* Pointer; //!< Pointer to the represented element.
+ typedef const NumericProxy* ConstPointer; //!< Pointer-to-const to the represented element.
+
+ //! Value type of the represented complex element.
+ typedef typename If_< IsComplex<RepresentedType>
+ , ComplexType<RepresentedType>
+ , BuiltinType<RepresentedType> >::Type ValueType;
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline NumericProxy( MT& matrix, size_t row, size_t column );
+ inline NumericProxy( const NumericProxy& np );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline NumericProxy& operator= ( const NumericProxy& sp );
+ template< typename T > inline NumericProxy& operator= ( const T& value );
+ template< typename T > inline NumericProxy& operator+=( const T& value );
+ template< typename T > inline NumericProxy& operator-=( const T& value );
+ template< typename T > inline NumericProxy& operator*=( const T& value );
+ template< typename T > inline NumericProxy& operator/=( const T& value );
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline Pointer operator->();
+ inline ConstPointer operator->() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void reset () const;
+ inline void clear () const;
+ inline void invert() const;
+
+ inline ConstReference get() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator ConstReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Complex data access functions***************************************************************
+ /*!\name Complex data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT& matrix_; //!< Reference to the adapted matrix.
+ size_t row_; //!< Row index of the accessed matrix element.
+ size_t column_; //!< Column index of the accessed matrix element.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a NumericProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NumericProxy<MT>::NumericProxy( MT& matrix, size_t row, size_t column )
+ : matrix_( matrix ) // Reference to the adapted matrix
+ , row_ ( row ) // Row index of the accessed matrix element
+ , column_( column ) // Column index of the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for NumericProxy.
+//
+// \param np Numeric proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NumericProxy<MT>::NumericProxy( const NumericProxy& np )
+ : matrix_( np.matrix_ ) // Reference to the adapted matrix
+ , row_ ( np.row_ ) // Row index of the accessed matrix element
+ , column_( np.column_ ) // Column index of the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for NumericProxy.
+//
+// \param np Numeric proxy to be copied.
+// \return Reference to the assigned proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NumericProxy<MT>& NumericProxy<MT>::operator=( const NumericProxy& np )
+{
+ matrix_(row_,column_) = np.matrix_(np.row_,np.column_);
+ matrix_(column_,row_) = np.matrix_(np.row_,np.column_);
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NumericProxy<MT>& NumericProxy<MT>::operator=( const T& value )
+{
+ matrix_(row_,column_) = value;
+ if( row_ != column_ )
+ matrix_(column_,row_) = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NumericProxy<MT>& NumericProxy<MT>::operator+=( const T& value )
+{
+ matrix_(row_,column_) += value;
+ if( row_ != column_ )
+ matrix_(column_,row_) += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NumericProxy<MT>& NumericProxy<MT>::operator-=( const T& value )
+{
+ matrix_(row_,column_) -= value;
+ if( row_ != column_ )
+ matrix_(column_,row_) -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NumericProxy<MT>& NumericProxy<MT>::operator*=( const T& value )
+{
+ matrix_(row_,column_) *= value;
+ if( row_ != column_ )
+ matrix_(column_,row_) *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline NumericProxy<MT>& NumericProxy<MT>::operator/=( const T& value )
+{
+ matrix_(row_,column_) /= value;
+ if( row_ != column_ )
+ matrix_(column_,row_) /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the represented matrix element.
+//
+// \return Pointer to the represented matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename NumericProxy<MT>::Pointer NumericProxy<MT>::operator->()
+{
+ return this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the represented matrix element.
+//
+// \return Pointer to the represented matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename NumericProxy<MT>::ConstPointer NumericProxy<MT>::operator->() const
+{
+ return this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reset the represented element to its default initial value.
+//
+// \return void
+//
+// This function resets the element represented by the proxy to its default initial value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void NumericProxy<MT>::reset() const
+{
+ using blaze::reset;
+
+ reset( matrix_(row_,column_) );
+ if( row_ != column_ )
+ reset( matrix_(column_,row_) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+//
+// \return void
+//
+// This function clears the element represented by the proxy to its default initial state.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void NumericProxy<MT>::clear() const
+{
+ using blaze::clear;
+
+ clear( matrix_(row_,column_) );
+ if( row_ != column_ )
+ clear( matrix_(column_,row_) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void NumericProxy<MT>::invert() const
+{
+ using blaze::invert;
+
+ invert( matrix_(row_,column_) );
+ if( row_ != column_ )
+ matrix_(column_,row_) = matrix_(row_,column_);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename NumericProxy<MT>::ConstReference NumericProxy<MT>::get() const noexcept
+{
+ return const_cast<const MT&>( matrix_ )(row_,column_);
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline NumericProxy<MT>::operator ConstReference() const noexcept
+{
+ return get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename NumericProxy<MT>::ValueType NumericProxy<MT>::real() const
+{
+ return matrix_(row_,column_).real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+//
+// In case the proxy represents a complex number, this function sets a new value to its real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void NumericProxy<MT>::real( ValueType value ) const
+{
+ matrix_(row_,column_).real( value );
+ if( row_ != column_ )
+ matrix_(column_,row_).real( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename NumericProxy<MT>::ValueType NumericProxy<MT>::imag() const
+{
+ return matrix_(row_,column_).imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+//
+// In case the proxy represents a complex number, this function sets a new value to its imaginary
+// part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void NumericProxy<MT>::imag( ValueType value ) const
+{
+ matrix_(row_,column_).imag( value );
+ if( row_ != column_ )
+ matrix_(column_,row_).imag( value );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name NumericProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const NumericProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const NumericProxy<MT>& proxy );
+
+template< typename MT >
+inline void invert( const NumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const NumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const NumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const NumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const NumericProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const NumericProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the numeric proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const NumericProxy<MT>& proxy )
+{
+ proxy.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the numeric proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const NumericProxy<MT>& proxy )
+{
+ proxy.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given proxy instance.
+// \return void
+*/
+template< typename MT >
+inline void invert( const NumericProxy<MT>& proxy )
+{
+ proxy.invert();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const NumericProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const NumericProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const NumericProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const NumericProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup symmetric_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const NumericProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/SharedValue.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/SharedValue.h
new file mode 100644
index 00000000..d33a9818
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/SharedValue.h
@@ -0,0 +1,314 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/SharedValue.h
+// \brief Header file for the SharedValue class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SHAREDVALUE_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SHAREDVALUE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/shared_ptr.hpp>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Value shared among several positions within a symmetric matrix.
+// \ingroup symmetric_matrix
+//
+// The SharedValue class template represents a single value of a symmetric matrix that is shared
+// among several positions within the symmetric matrix. Changes to the value of one position
+// are therefore applied to all positions sharing the same value.
+*/
+template< typename Type > // Type of the shared value
+class SharedValue
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef Type ValueType; //!< Type of the shared value.
+ typedef Type& Reference; //!< Reference to the shared value.
+ typedef const Type& ConstReference; //!< Reference-to-const to the shared value.
+ typedef Type* Pointer; //!< Pointer to the shared value.
+ typedef const Type* ConstPointer; //!< Pointer-to-const to the shared value.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline SharedValue();
+ explicit inline SharedValue( const Type& value );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline Reference operator* ();
+ inline ConstReference operator* () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline Pointer base() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ mutable boost::shared_ptr<Type> value_; //!< The shared value.
+ //@}
+ //**********************************************************************************************
+
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default constructor for a SharedValue.
+*/
+template< typename Type > // Type of the shared value
+inline SharedValue<Type>::SharedValue()
+ : value_() // The shared value
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a SharedValue.
+//
+// \param value The value to be shared.
+//
+// This constructor creates a shared value as a copy of the given value.
+*/
+template< typename Type > // Type of the shared value
+inline SharedValue<Type>::SharedValue( const Type& value )
+ : value_( new Type( value ) ) // The shared value
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the shared value.
+//
+// \return Reference to the shared value.
+*/
+template< typename Type > // Type of the shared value
+inline typename SharedValue<Type>::Reference SharedValue<Type>::operator*()
+{
+ if( !value_ )
+ value_.reset( new Type() );
+ return *value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the shared value.
+//
+// \return Reference to the shared value.
+*/
+template< typename Type > // Type of the shared value
+inline typename SharedValue<Type>::ConstReference SharedValue<Type>::operator*() const
+{
+ if( !value_ )
+ value_.reset( new Type() );
+ return *value_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Low-level access to the underlying, shared value.
+//
+// \return Pointer to the shared value.
+*/
+template< typename Type > // Type of the shared value
+inline typename SharedValue<Type>::Pointer SharedValue<Type>::base() const noexcept
+{
+ return value_.get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SharedValue operators */
+//@{
+template< typename T1, typename T2 >
+inline bool operator==( const SharedValue<T1>& lhs, const SharedValue<T2>& rhs );
+
+template< typename T1, typename T2 >
+inline bool operator!=( const SharedValue<T1>& lhs, const SharedValue<T2>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two SharedValue objects.
+// \ingroup symmetric_matrix
+//
+// \param lhs The left-hand side SharedValue object.
+// \param rhs The right-hand side SharedValue object.
+// \return \a true if both shared values refer to the same value, \a false if they don't.
+*/
+template< typename T1, typename T2 >
+inline bool operator==( const SharedValue<T1>& lhs, const SharedValue<T2>& rhs )
+{
+ return ( lhs.base() == rhs.base() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two SharedValue objects.
+// \ingroup symmetric_matrix
+//
+// \param lhs The left-hand side SharedValue object.
+// \param rhs The right-hand side SharedValue object.
+// \return \a true if both shared values refer to different values, \a false if they don't.
+*/
+template< typename T1, typename T2 >
+inline bool operator!=( const SharedValue<T1>& lhs, const SharedValue<T2>& rhs )
+{
+ return ( lhs.base() != rhs.base() );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SharedValue global functions */
+//@{
+template< typename Type >
+inline bool isDefault( const SharedValue<Type>& value );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the shared value is in default state.
+// \ingroup symmetric_matrix
+//
+// \param value The given shared value.
+// \return \a true in case the shared value is in default state, \a false otherwise.
+//
+// This function checks whether the given shared value is in default state. In case it is in
+// default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename Type >
+inline bool isDefault( const SharedValue<Type>& value )
+{
+ using blaze::isDefault;
+
+ return isDefault( *value );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNonNumeric.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNonNumeric.h
new file mode 100644
index 00000000..2f95a537
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNonNumeric.h
@@ -0,0 +1,2720 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/SparseNonNumeric.h
+// \brief SymmetricMatrix specialization for sparse matrices with non-numeric element type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SPARSENONNUMERIC_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SPARSENONNUMERIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/symmetricmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/symmetricmatrix/NonNumericProxy.h>
+#include <blaze/math/adaptors/symmetricmatrix/SharedValue.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES WITH NON-NUMERIC ELEMENT TYPE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of SymmetricMatrix for sparse matrices with non-numeric element type.
+// \ingroup symmetric_matrix
+//
+// This specialization of SymmetricMatrix adapts the class template to the requirements of sparse
+// matrices with non-numeric element type.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class SymmetricMatrix<MT,SO,false,false>
+ : public SparseMatrix< SymmetricMatrix<MT,SO,false,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+
+ //! Rebound matrix type for shared values.
+ typedef typename MT::template Rebind< SharedValue<ET> >::Other MatrixType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SymmetricMatrix<MT,SO,false,false> This; //!< Type of this SymmetricMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this SymmetricMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef SymmetricMatrix<OT,!SO,false,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef SymmetricMatrix<TT,!SO,false,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef NonNumericProxy<MatrixType> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a SymmetricMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other SymmetricMatrix.
+ typedef SymmetricMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**SharedElement class definition**************************************************************
+ /*!\brief Access proxy for a specific shared element of the sparse symmetric matrix.
+ */
+ template< typename IteratorType > // Type of the sparse matrix iterator
+ class SharedElement : private SparseElement
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef ET ValueType; //!< The value type of the value-index-pair.
+ typedef size_t IndexType; //!< The index type of the value-index-pair.
+ typedef ValueType& Reference; //!< Reference return type.
+ typedef const ValueType& ConstReference; //!< Reference-to-const return type.
+ typedef SharedElement* Pointer; //!< Pointer return type.
+ typedef const SharedElement* ConstPointer; //!< Pointer-to-const return type.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SharedElement class.
+ //
+ // \param pos Iterator to the current sparse symmetric matrix element.
+ */
+ inline SharedElement( IteratorType pos )
+ : pos_( pos ) // Iterator to the current sparse symmetric matrix element
+ {}
+ //*******************************************************************************************
+
+ //**Assignment operator**********************************************************************
+ /*!\brief Assignment to the symmetric element.
+ //
+ // \param v The new v of the symmetric element.
+ // \return Reference to the assigned symmetric element.
+ */
+ template< typename T > inline SharedElement& operator=( const T& v ) {
+ *pos_->value() = v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment to the symmetric element.
+ //
+ // \param v The right-hand side value for the addition.
+ // \return Reference to the assigned symmetric element.
+ */
+ template< typename T > inline SharedElement& operator+=( const T& v ) {
+ *pos_->value() += v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment to the symmetric element.
+ //
+ // \param v The right-hand side value for the subtraction.
+ // \return Reference to the assigned symmetric element.
+ */
+ template< typename T > inline SharedElement& operator-=( const T& v ) {
+ *pos_->value() -= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Multiplication assignment operator*******************************************************
+ /*!\brief Multiplication assignment to the symmetric element.
+ //
+ // \param v The right-hand side value for the multiplication.
+ // \return Reference to the assigned symmetric element.
+ */
+ template< typename T > inline SharedElement& operator*=( const T& v ) {
+ *pos_->value() *= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Division assignment operator*************************************************************
+ /*!\brief Division assignment to the symmetric element.
+ //
+ // \param v The right-hand side value for the division.
+ // \return Reference to the assigned symmetric element.
+ */
+ template< typename T > inline SharedElement& operator/=( const T& v ) {
+ *pos_->value() /= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the symmetric element.
+ //
+ // \return Reference to the value of the symmetric element.
+ */
+ inline Pointer operator->() {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the symmetric element.
+ //
+ // \return Reference to the value of the symmetric element.
+ */
+ inline ConstPointer operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the symmetric element.
+ //
+ // \return The current value of the symmetric element.
+ */
+ inline Reference value() {
+ return *pos_->value();
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the symmetric element.
+ //
+ // \return The current value of the symmetric element.
+ */
+ inline ConstReference value() const {
+ return *pos_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the symmetric element.
+ //
+ // \return The current index of the symmetric element.
+ */
+ inline IndexType index() const {
+ return pos_->index();
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse symmetric matrix element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**SharedIterator class definition*************************************************************
+ /*!\brief Iterator over the elements of the sparse symmetric matrix.
+ */
+ template< typename SparseElementType // Type of the underlying sparse elements.
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class SharedIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef SparseElementType ValueType; //!< Type of the underlying elements.
+ typedef SparseElementType PointerType; //!< Pointer return type.
+ typedef SparseElementType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Default constructor**********************************************************************
+ /*!\brief Default constructor for the SharedIterator class.
+ */
+ inline SharedIterator()
+ : pos_() // Iterator to the current sparse symmetric matrix element
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SharedIterator class.
+ //
+ // \param pos The initial position of the iterator.
+ */
+ inline SharedIterator( IteratorType pos )
+ : pos_( pos ) // Iterator to the current sparse symmetric matrix element
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different SharedIterator instances.
+ //
+ // \param it The matrix iterator to be copied.
+ */
+ template< typename SparseElementType2, typename IteratorType2 >
+ inline SharedIterator( const SharedIterator<SparseElementType2,IteratorType2>& it )
+ : pos_( it.pos_ ) // Iterator to the current sparse symmetric matrix element
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline SharedIterator& operator++() {
+ ++pos_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SharedIterator operator++( int ) {
+ const SharedIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Reference to the current sparse matrix element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Pointer to the current sparse matrix element.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two SharedIterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const SharedIterator& rhs ) const {
+ return pos_ == rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two SharedIterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const SharedIterator& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const SharedIterator& rhs ) const {
+ return pos_ - rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the iterator.
+ //
+ // \return The current position of the iterator.
+ */
+ inline IteratorType base() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse symmetric matrix element.
+ //*******************************************************************************************
+
+ //**Friend declarations**********************************************************************
+ template< typename SparseElementType2, typename IteratorType2 > friend class SharedIterator;
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over non-constant elements.
+ typedef SharedIterator< SharedElement< Iterator_<MatrixType> >
+ , Iterator_<MatrixType>
+ > Iterator;
+
+ //! Iterator over constant elements.
+ typedef SharedIterator< const SharedElement< ConstIterator_<MatrixType> >
+ , ConstIterator_<MatrixType>
+ > ConstIterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline SymmetricMatrix();
+ explicit inline SymmetricMatrix( size_t n );
+ explicit inline SymmetricMatrix( size_t n, size_t nonzeros );
+ explicit inline SymmetricMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline SymmetricMatrix( const SymmetricMatrix& m );
+ inline SymmetricMatrix( SymmetricMatrix&& m ) noexcept;
+
+ template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,SO>& m );
+ template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,!SO>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline SymmetricMatrix& operator=( const SymmetricMatrix& rhs );
+ inline SymmetricMatrix& operator=( SymmetricMatrix&& rhs ) noexcept;
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator+=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator-=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline SymmetricMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, SymmetricMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, SymmetricMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ inline SymmetricMatrix& transpose();
+ inline SymmetricMatrix& ctranspose();
+ template< typename Other > inline SymmetricMatrix& scale( const Other& scalar );
+ template< typename Other > inline SymmetricMatrix& scaleDiagonal( Other scale );
+ inline void swap( SymmetricMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename MT2 > void assign( DenseMatrix<MT2,SO>& rhs );
+ template< typename MT2 > void assign( const DenseMatrix<MT2,SO>& rhs );
+ template< typename MT2 > void assign( SparseMatrix<MT2,SO>& rhs );
+ template< typename MT2 > void assign( const SparseMatrix<MT2,SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MatrixType matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool NF2 >
+ friend bool isDefault( const SymmetricMatrix<MT2,SO2,DF2,NF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_NUMERIC_TYPE ( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for SymmetricMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>::SymmetricMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized to the zero matrix and has no free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>::SymmetricMatrix( size_t n )
+ : matrix_( n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized to the zero matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>::SymmetricMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+//
+// The matrix is initialized to the zero matrix and will have the specified capacity in each
+// row/column. Note that in case of a row-major matrix the given vector must have at least
+// \a m elements, in case of a column-major matrix at least \a n elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>::SymmetricMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for SymmetricMatrix.
+//
+// \param m The symmetric matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>::SymmetricMatrix( const SymmetricMatrix& m )
+ : matrix_() // The adapted sparse matrix
+{
+ using blaze::resize;
+
+ resize( matrix_, m.rows(), m.columns() );
+ assign( m );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for SymmetricMatrix.
+//
+// \param m The symmetric matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>::SymmetricMatrix( SymmetricMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices with the same storage order.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
+// given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the foreign matrix
+inline SymmetricMatrix<MT,SO,false,false>::SymmetricMatrix( const Matrix<MT2,SO>& m )
+ : matrix_() // The adapted sparse matrix
+{
+ using blaze::resize;
+
+ typedef RemoveAdaptor_< ResultType_<MT2> > RT;
+ typedef If_< IsComputation<MT2>, RT, const MT2& > Tmp;
+
+ Tmp tmp( ~m );
+
+ if( !IsSymmetric<MT2>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.columns() );
+ assign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices with opposite storage order.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
+// given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the foreign matrix
+inline SymmetricMatrix<MT,SO,false,false>::SymmetricMatrix( const Matrix<MT2,!SO>& m )
+ : matrix_() // The adapted sparse matrix
+{
+ using blaze::resize;
+
+ typedef RemoveAdaptor_< ResultType_<MT2> > RT;
+ typedef If_< IsComputation<MT2>, RT, const MT2& > Tmp;
+
+ Tmp tmp( ~m );
+
+ if( !IsSymmetric<MT2>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.columns() );
+ assign( trans( tmp ) );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// The function call operator provides access to both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$.
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Reference
+ SymmetricMatrix<MT,SO,false,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// The function call operator provides access to both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$.
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstReference
+ SymmetricMatrix<MT,SO,false,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return *matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Reference
+ SymmetricMatrix<MT,SO,false,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstReference
+ SymmetricMatrix<MT,SO,false,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::begin( size_t i )
+{
+ return Iterator( matrix_.begin(i) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstIterator
+ SymmetricMatrix<MT,SO,false,false>::begin( size_t i ) const
+{
+ return ConstIterator( matrix_.begin(i) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstIterator
+ SymmetricMatrix<MT,SO,false,false>::cbegin( size_t i ) const
+{
+ return ConstIterator( matrix_.cbegin(i) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::end( size_t i )
+{
+ return Iterator( matrix_.end(i) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstIterator
+ SymmetricMatrix<MT,SO,false,false>::end( size_t i ) const
+{
+ return ConstIterator( matrix_.end(i) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstIterator
+ SymmetricMatrix<MT,SO,false,false>::cend( size_t i ) const
+{
+ return ConstIterator( matrix_.cend(i) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for SymmetricMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::operator=( const SymmetricMatrix& rhs )
+{
+ using blaze::resize;
+
+ if( &rhs == this ) return *this;
+
+ resize( matrix_, rhs.rows(), rhs.columns() );
+ reset();
+ assign( rhs );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for SymmetricMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::operator=( SymmetricMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,false,false>& >
+ SymmetricMatrix<MT,SO,false,false>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::resize;
+
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ SymmetricMatrix tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( matrix_, (~rhs).rows(), (~rhs).columns() );
+ reset();
+ assign( ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,false,false>& >
+ SymmetricMatrix<MT,SO,false,false>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::resize;
+
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !IsSymmetric<MT2>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.columns() );
+ reset();
+ assign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrices with opposite storage order.
+//
+// \param rhs The right-hand side matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::operator=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::resize;
+
+ typedef AddTrait_< MT, ResultType_<MT2> > Tmp;
+
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ Tmp tmp( (*this) + ~rhs );
+
+ if( !IsSymmetric<Tmp>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.columns() );
+ reset();
+ assign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix with opposite storage order
+// (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::operator+=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator+=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::resize;
+
+ typedef SubTrait_< MT, ResultType_<MT2> > Tmp;
+
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ Tmp tmp( (*this) - ~rhs );
+
+ if( !IsSymmetric<Tmp>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.columns() );
+ reset();
+ assign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix with opposite storage
+// order (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::operator-=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator-=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a symmetric matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ using blaze::resize;
+
+ typedef MultTrait_< MT, ResultType_<MT2> > Tmp;
+
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ Tmp tmp( (*this) * ~rhs );
+
+ if( !IsSymmetric<Tmp>::value && !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ resize( matrix_, tmp.rows(), tmp.columns() );
+ reset();
+ assign( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, SymmetricMatrix<MT,SO,false,false> >&
+ SymmetricMatrix<MT,SO,false,false>::operator*=( Other rhs )
+{
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const Iterator_<MatrixType> last( matrix_.upperBound(i,i) );
+ for( Iterator_<MatrixType> element=matrix_.begin(i); element!=last; ++element )
+ *element->value() *= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, SymmetricMatrix<MT,SO,false,false> >&
+ SymmetricMatrix<MT,SO,false,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const Iterator_<MatrixType> last( matrix_.upperBound(i,i) );
+ for( Iterator_<MatrixType> element=matrix_.begin(i); element!=last; ++element )
+ *element->value() /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the symmetric
+// matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function returns the capacity of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the symmetric matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column. In
+// case the symmetric matrix adapts a \a rowMajor sparse matrix the function returns the number of
+// non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse matrix the function
+// returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row \b and column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row \b and column to their default value.
+// The following example demonstrates this by means of a \f$ 5 \times 5 \f$ symmetric matrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticVector;
+ using blaze::SymmetricMatrix;
+
+ SymmetricMatrix< CompressedMatrix< StaticVector<int,1UL> > > A;
+
+ // Initializing the symmetric matrix A to
+ //
+ // ( ( ) ( 2 ) ( 5 ) ( -4 ) ( ) )
+ // ( ( 2 ) ( 1 ) ( -3 ) ( 7 ) ( ) )
+ // A = ( ( 5 ) ( -3 ) ( 8 ) ( -1 ) ( -2 ) )
+ // ( ( -4 ) ( 7 ) ( -1 ) ( ) ( -6 ) )
+ // ( ( ) ( 0 ) ( -2 ) ( -6 ) ( 1 ) )
+ // ...
+
+ // Resetting the 1st row/column results in the matrix
+ //
+ // ( ( ) ( ) ( 5 ) ( -4 ) ( ) )
+ // ( ( ) ( ) ( ) ( ) ( ) )
+ // A = ( ( 5 ) ( ) ( 8 ) ( -1 ) ( -2 ) )
+ // ( ( -4 ) ( ) ( -1 ) ( ) ( -6 ) )
+ // ( ( ) ( ) ( -2 ) ( -6 ) ( 1 ) )
+ //
+ A.reset( 1UL );
+ \endcode
+
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::reset( size_t i )
+{
+ for( Iterator_<MatrixType> it=matrix_.begin(i); it!=matrix_.end(i); ++it )
+ {
+ const size_t j( it->index() );
+
+ if( i == j )
+ continue;
+
+ if( SO ) {
+ const Iterator_<MatrixType> pos( matrix_.find( i, j ) );
+ BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, pos );
+ }
+ else {
+ const Iterator_<MatrixType> pos( matrix_.find( j, i ) );
+ BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, pos );
+ }
+ }
+
+ matrix_.reset( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the symmetric matrix.
+//
+// \return void
+//
+// This function clears the symmetric matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the symmetric matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+//
+// This function sets the value of both the elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ of the
+// symmetric matrix and returns an iterator to the successfully set element \f$ a_{ij} \f$. In
+// case the symmetric matrix already contains the two elements with index \a i and \a j their
+// values are modified, else two new elements with the given \a value are inserted.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ SharedValue<ET> shared( value );
+
+ if( i != j )
+ matrix_.set( j, i, shared );
+
+ return Iterator( matrix_.set( i, j, shared ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the symmetric matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+//
+// This function inserts both the elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ into the symmetric
+// matrix and returns an iterator to the successfully inserted element \f$ a_{ij} \f$. However,
+// duplicate elements are not allowed. In case the symmetric matrix an element with row index
+// \a i and column index \a j, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ SharedValue<ET> shared( value );
+
+ if( i != j )
+ matrix_.insert( j, i, shared );
+
+ return Iterator( matrix_.insert( i, j, shared ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the symmetric matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ from the symmetric matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::erase( size_t i, size_t j )
+{
+ matrix_.erase( i, j );
+ if( i != j )
+ matrix_.erase( j, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the symmetric matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases both the specified element and its according symmetric counterpart from
+// the symmetric matrix. In case the storage order is set to \a rowMajor the given index \a i
+// refers to a row, in case the storage flag is set to \a columnMajor \a i refers to a column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::erase( size_t i, Iterator pos )
+{
+ if( pos == end( i ) )
+ return pos;
+
+ const size_t j( pos->index() );
+
+ if( i == j )
+ return Iterator( matrix_.erase( i, pos.base() ) );
+
+ if( SO ) {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( i, j ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, matrix_.find( i, j ) );
+ return Iterator( matrix_.erase( i, pos.base() ) );
+ }
+ else {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( j, i ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, matrix_.find( j, i ) );
+ return Iterator( matrix_.erase( i, pos.base() ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the symmetric matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases both the range of elements specified by the iterator pair \a first and
+// \a last and their according symmetric counterparts from the symmetric matrix. In case the
+// storage order is set to \a rowMajor the given index \a i refers to a row, in case the storage
+// flag is set to \a columnMajor \a i refers to a column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ for( Iterator it=first; it!=last; ++it )
+ {
+ const size_t j( it->index() );
+
+ if( i == j )
+ continue;
+
+ if( SO ) {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( i, j ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( i, j );
+ }
+ else {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( j, i ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, i );
+ }
+ }
+
+ return Iterator( matrix_.erase( i, first.base(), last.base() ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the symmetric matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void SymmetricMatrix<MT,SO,false,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+
+ matrix_.resize( n, n, true );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the symmetric matrix.
+//
+// \param nonzeros The new minimum capacity of the symmetric matrix.
+// \return void
+//
+// This function increases the capacity of the symmetric matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the symmetric matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the symmetric matrix to at least
+// \a nonzeros elements. The current values of the symmetric matrix and all other individual
+// row/column capacities are preserved. In case the storage order is set to \a rowMajor, the
+// function reserves capacity for row \a i. In case the storage order is set to \a columnMajor,
+// the function reserves capacity for column \a i. The index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the symmetric matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the symmetric matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>& SymmetricMatrix<MT,SO,false,false>::transpose()
+{
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the symmetric matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,false>& SymmetricMatrix<MT,SO,false,false>::ctranspose()
+{
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const Iterator_<MatrixType> last( matrix_.upperBound(i,i) );
+ for( Iterator_<MatrixType> element=matrix_.begin(i); element!=last; ++element )
+ conjugate( *element->value() );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const Iterator_<MatrixType> last( matrix_.upperBound(i,i) );
+ for( Iterator_<MatrixType> element=matrix_.begin(i); element!=last; ++element )
+ ( *element->value() ).scale( scalar );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the symmetric matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the symmetric matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline SymmetricMatrix<MT,SO,false,false>&
+ SymmetricMatrix<MT,SO,false,false>::scaleDiagonal( Other scalar )
+{
+ matrix_.scaleDiagonal( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::swap( SymmetricMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the symmetric
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned symmetric matrix iterator is subject
+// to invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::find( size_t i, size_t j )
+{
+ return Iterator( matrix_.find( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the symmetric
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned symmetric matrix iterator is subject
+// to invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstIterator
+ SymmetricMatrix<MT,SO,false,false>::find( size_t i, size_t j ) const
+{
+ return ConstIterator( matrix_.find( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned symmetric matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::lowerBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.lowerBound( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned symmetric matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstIterator
+ SymmetricMatrix<MT,SO,false,false>::lowerBound( size_t i, size_t j ) const
+{
+ return ConstIterator( matrix_.lowerBound( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned symmetric matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::Iterator
+ SymmetricMatrix<MT,SO,false,false>::upperBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.upperBound( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned symmetric matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,false>::ConstIterator
+ SymmetricMatrix<MT,SO,false,false>::upperBound( size_t i, size_t j ) const
+{
+ return ConstIterator( matrix_.upperBound( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the symmetric matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function both appends the element \f$ a_{ij} \f$ to the specified row/column and inserts
+// its according counterpart \f$ a_{ji} \f$ into the symmetric matrix. Since element \f$ a_{ij} \f$
+// is appended without any additional memory allocation, it is strictly necessary to keep the
+// following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// Although in addition to element \f$ a_{ij} \f$ a second element \f$ a_{ji} \f$ is inserted into
+// the matrix, this function still provides the most efficient way to fill a symmetric matrix with
+// values. However, in order to achieve maximum efficiency, the matrix has to be specifically
+// prepared with reserve() calls:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+
+ // Setup of the symmetric matrix
+ //
+ // ( 0 1 3 )
+ // A = ( 1 2 0 )
+ // ( 3 0 0 )
+
+ SymmetricMatrix< CompressedMatrix<double,rowMajor> > A( 3 );
+
+ A.reserve( 5 ); // Reserving enough capacity for 5 non-zero elements
+ A.reserve( 0, 2 ); // Reserving two non-zero elements in the first row
+ A.reserve( 1, 2 ); // Reserving two non-zero elements in the second row
+ A.reserve( 2, 1 ); // Reserving a single non-zero element in the third row
+ A.append( 0, 1, 1.0 ); // Appending the value 1 at position (0,1) and (1,0)
+ A.append( 1, 1, 2.0 ); // Appending the value 2 at position (1,1)
+ A.append( 2, 0, 3.0 ); // Appending the value 3 at position (2,0) and (0,2)
+ \endcode
+
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ SharedValue<ET> shared( value );
+
+ matrix_.append( i, j, shared, check );
+ if( i != j && ( !check || !isDefault( value ) ) )
+ matrix_.insert( j, i, shared );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,false>::finalize( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the symmetric matrix are intact.
+//
+// \return \a true in case the symmetric matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the symmetric matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool SymmetricMatrix<MT,SO,false,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isSymmetric( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool SymmetricMatrix<MT,SO,false,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool SymmetricMatrix<MT,SO,false,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool SymmetricMatrix<MT,SO,false,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Optimized implementation of the assignment of a temporary dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+void SymmetricMatrix<MT,SO,false,false>::assign( DenseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ std::vector<size_t> nonzeros( rows(), 0UL );
+ size_t sum( 0UL );
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ nonzeros[i] = (~rhs).nonZeros(i);
+ sum += nonzeros[i];
+ }
+
+ matrix_.reserve( sum );
+ for( size_t i=0UL; i<rows(); ++i ) {
+ matrix_.reserve( i, nonzeros[i] );
+ }
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( size_t j=i; j<columns(); ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) ) {
+ SharedValue<ET> shared;
+ *shared = std::move( (~rhs)(i,j) );
+ matrix_.append( i, j, shared, false );
+ if( i != j )
+ matrix_.append( j, i, shared, false );
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+void SymmetricMatrix<MT,SO,false,false>::assign( const DenseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ std::vector<size_t> nonzeros( rows(), 0UL );
+ size_t sum( 0UL );
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ nonzeros[i] = (~rhs).nonZeros(i);
+ sum += nonzeros[i];
+ }
+
+ matrix_.reserve( sum );
+ for( size_t i=0UL; i<rows(); ++i ) {
+ matrix_.reserve( i, nonzeros[i] );
+ }
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( size_t j=i; j<columns(); ++j ) {
+ if( !isDefault( (~rhs)(i,j) ) ) {
+ const SharedValue<ET> shared( (~rhs)(i,j) );
+ matrix_.append( i, j, shared, false );
+ if( i != j )
+ matrix_.append( j, i, shared, false );
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Optimized implementation of the assignment of a temporary sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+void SymmetricMatrix<MT,SO,false,false>::assign( SparseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ std::vector<size_t> nonzeros( rows(), 0UL );
+ size_t sum( 0UL );
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ nonzeros[i] = (~rhs).nonZeros(i);
+ sum += nonzeros[i];
+ }
+
+ matrix_.reserve( sum );
+ for( size_t i=0UL; i<rows(); ++i ) {
+ matrix_.reserve( i, nonzeros[i] );
+ }
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( Iterator_<MT2> it=(~rhs).lowerBound(i,i); it!=(~rhs).end(i); ++it ) {
+ if( !isDefault( it->value() ) ) {
+ SharedValue<ET> shared;
+ *shared = std::move( it->value() );
+ matrix_.append( i, it->index(), shared, false );
+ if( i != it->index() )
+ matrix_.append( it->index(), i, shared, false );
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+void SymmetricMatrix<MT,SO,false,false>::assign( const SparseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ std::vector<size_t> nonzeros( rows(), 0UL );
+ size_t sum( 0UL );
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ nonzeros[i] = (~rhs).nonZeros(i);
+ sum += nonzeros[i];
+ }
+
+ matrix_.reserve( sum );
+ for( size_t i=0UL; i<rows(); ++i ) {
+ matrix_.reserve( i, nonzeros[i] );
+ }
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( ConstIterator_<MT2> it=(~rhs).lowerBound(i,i); it!=(~rhs).end(i); ++it ) {
+ if( !isDefault( it->value() ) ) {
+ const SharedValue<ET> shared( it->value() );
+ matrix_.append( i, it->index(), shared, false );
+ if( i != it->index() )
+ matrix_.append( it->index(), i, shared, false );
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNumeric.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNumeric.h
new file mode 100644
index 00000000..b198c1e7
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNumeric.h
@@ -0,0 +1,2345 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/SparseNumeric.h
+// \brief SymmetricMatrix specialization for sparse matrices with numeric element type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SPARSENUMERIC_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SPARSENUMERIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/symmetricmatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/symmetricmatrix/NumericProxy.h>
+#include <blaze/math/adaptors/symmetricmatrix/SymmetricElement.h>
+#include <blaze/math/adaptors/symmetricmatrix/SymmetricValue.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES WITH NUMERIC ELEMENT TYPE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of SymmetricMatrix for sparse matrices with numeric element type.
+// \ingroup symmetric_matrix
+//
+// This specialization of SymmetricMatrix adapts the class template to the requirements of sparse
+// matrices with numeric element type.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class SymmetricMatrix<MT,SO,false,true>
+ : public SparseMatrix< SymmetricMatrix<MT,SO,false,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SymmetricMatrix<MT,SO,false,true> This; //!< Type of this SymmetricMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this SymmetricMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef SymmetricMatrix<OT,!SO,false,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef SymmetricMatrix<TT,!SO,false,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef NumericProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a SymmetricMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other SymmetricMatrix.
+ typedef SymmetricMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the elements of the sparse symmetric matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef Iterator_<MT> IteratorType; //!< Type of the underlying sparse matrix iterators.
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef SymmetricElement<MT> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Default constructor**********************************************************************
+ /*!\brief Default constructor for the Iterator class.
+ */
+ inline Iterator()
+ : pos_ () // Iterator to the current sparse symmetric matrix element
+ , matrix_( nullptr ) // The sparse matrix containing the iterator
+ , index_ ( 0UL ) // The row/column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param pos The initial position of the iterator.
+ // \param matrix The sparse matrix containing the iterator.
+ // \param index The row/column index of the iterator.
+ */
+ inline Iterator( IteratorType pos, MT& matrix, size_t index )
+ : pos_ ( pos ) // Iterator to the current sparse symmetric matrix element
+ , matrix_( &matrix ) // The sparse matrix containing the iterator
+ , index_ ( index ) // The row/column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() {
+ ++pos_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Reference to the current sparse matrix element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, matrix_, index_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Pointer to the current sparse matrix element.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, matrix_, index_ );
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const Iterator& rhs ) const {
+ return pos_ == rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const Iterator& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two matrix iterators.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return The number of elements between the two matrix iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const {
+ return pos_ - rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the matrix iterator.
+ //
+ // \return The current position of the matrix iterator.
+ */
+ inline IteratorType base() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse symmetric matrix element.
+ MT* matrix_; //!< The sparse matrix containing the iterator.
+ size_t index_; //!< The row/column index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline SymmetricMatrix();
+ explicit inline SymmetricMatrix( size_t n );
+ explicit inline SymmetricMatrix( size_t n, size_t nonzeros );
+ explicit inline SymmetricMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline SymmetricMatrix( const SymmetricMatrix& m );
+ inline SymmetricMatrix( SymmetricMatrix&& m ) noexcept;
+
+ template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,SO>& m );
+ template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,!SO>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline SymmetricMatrix& operator=( const SymmetricMatrix& rhs );
+ inline SymmetricMatrix& operator=( SymmetricMatrix&& rhs ) noexcept;
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator+=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< IsComputation<MT2>, SymmetricMatrix& > operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< IsComputation<MT2>, SymmetricMatrix& > operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2 >
+ inline SymmetricMatrix& operator-=( const Matrix<MT2,!SO>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline SymmetricMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, SymmetricMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, SymmetricMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ inline SymmetricMatrix& transpose();
+ inline SymmetricMatrix& ctranspose();
+ template< typename Other > inline SymmetricMatrix& scale( const Other& scalar );
+ template< typename Other > inline SymmetricMatrix& scaleDiagonal( Other scale );
+ inline void swap( SymmetricMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool NF2 >
+ friend bool isDefault( const SymmetricMatrix<MT2,SO2,DF2,NF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for SymmetricMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>::SymmetricMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized to the zero matrix and has no free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>::SymmetricMatrix( size_t n )
+ : matrix_( n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized to the zero matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>::SymmetricMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+//
+// The matrix is initialized to the zero matrix and will have the specified capacity in each
+// row/column. Note that in case of a row-major matrix the given vector must have at least
+// \a m elements, in case of a column-major matrix at least \a n elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>::SymmetricMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for SymmetricMatrix.
+//
+// \param m The symmetric matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>::SymmetricMatrix( const SymmetricMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for SymmetricMatrix.
+//
+// \param m The symmetric matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>::SymmetricMatrix( SymmetricMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices with the same storage order.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
+// given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the foreign matrix
+inline SymmetricMatrix<MT,SO,false,true>::SymmetricMatrix( const Matrix<MT2,SO>& m )
+ : matrix_( ~m ) // The adapted sparse matrix
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices with opposite storage order.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of symmetric matrix.
+//
+// This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
+// given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the foreign matrix
+inline SymmetricMatrix<MT,SO,false,true>::SymmetricMatrix( const Matrix<MT2,!SO>& m )
+ : matrix_( trans( ~m ) ) // The adapted sparse matrix
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// The function call operator provides access to both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$.
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Reference
+ SymmetricMatrix<MT,SO,false,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// The function call operator provides access to both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$.
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstReference
+ SymmetricMatrix<MT,SO,false,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Reference
+ SymmetricMatrix<MT,SO,false,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// The function call operator provides access to both the elements at position (i,j) and (j,i).
+// In order to preserve the symmetry of the matrix, any modification to one of the elements will
+// also be applied to the other element.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstReference
+ SymmetricMatrix<MT,SO,false,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::begin( size_t i )
+{
+ return Iterator( matrix_.begin(i), matrix_, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstIterator
+ SymmetricMatrix<MT,SO,false,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstIterator
+ SymmetricMatrix<MT,SO,false,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::end( size_t i )
+{
+ return Iterator( matrix_.end(i), matrix_, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstIterator
+ SymmetricMatrix<MT,SO,false,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the symmetric matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstIterator
+ SymmetricMatrix<MT,SO,false,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for SymmetricMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>&
+ SymmetricMatrix<MT,SO,false,true>::operator=( const SymmetricMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for SymmetricMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>&
+ SymmetricMatrix<MT,SO,false,true>::operator=( SymmetricMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,false,true>& >
+ SymmetricMatrix<MT,SO,false,true>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,false,true>& >
+ SymmetricMatrix<MT,SO,false,true>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ if( IsSymmetric<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrices with opposite storage order.
+//
+// \param rhs The right-hand side matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,true>&
+ SymmetricMatrix<MT,SO,false,true>::operator=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,false,true>& >
+ SymmetricMatrix<MT,SO,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,false,true>& >
+ SymmetricMatrix<MT,SO,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ if( IsSymmetric<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix with opposite storage order
+// (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
+// the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,true>&
+ SymmetricMatrix<MT,SO,false,true>::operator+=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator+=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,false,true>& >
+ SymmetricMatrix<MT,SO,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSymmetric<MT2>::value && !isSymmetric( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, SymmetricMatrix<MT,SO,false,true>& >
+ SymmetricMatrix<MT,SO,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ if( IsSymmetric<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix with opposite storage
+// order (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to symmetric matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
+// i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 > // Type of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,true>&
+ SymmetricMatrix<MT,SO,false,true>::operator-=( const Matrix<MT2,!SO>& rhs )
+{
+ return this->operator-=( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be a symmetric matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline SymmetricMatrix<MT,SO,false,true>&
+ SymmetricMatrix<MT,SO,false,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isSymmetric( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, SymmetricMatrix<MT,SO,false,true> >&
+ SymmetricMatrix<MT,SO,false,true>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, SymmetricMatrix<MT,SO,false,true> >&
+ SymmetricMatrix<MT,SO,false,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the symmetric
+// matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function returns the capacity of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the symmetric matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column. In
+// case the symmetric matrix adapts a \a rowMajor sparse matrix the function returns the number of
+// non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse matrix the function
+// returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t SymmetricMatrix<MT,SO,false,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row \b and column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row \b and column to their default value.
+// The following example demonstrates this by means of a \f$ 5 \times 5 \f$ symmetric matrix:
+
+ \code
+ blaze::SymmetricMatrix< blaze::CompressedMatrix<int> > A;
+
+ // Initializing the symmetric matrix A to
+ //
+ // ( 0 2 5 -4 0 )
+ // ( 2 1 -3 7 0 )
+ // A = ( 5 -3 8 -1 -2 )
+ // ( -4 7 -1 0 -6 )
+ // ( 0 0 -2 -6 1 )
+ // ...
+
+ // Resetting the 1st row/column results in the matrix
+ //
+ // ( 0 0 5 -4 0 )
+ // ( 0 0 0 0 0 )
+ // A = ( 5 0 8 -1 -2 )
+ // ( -4 0 -1 0 -6 )
+ // ( 0 0 -2 -6 1 )
+ //
+ A.reset( 1UL );
+ \endcode
+
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::reset( size_t i )
+{
+ for( Iterator_<MT> it=matrix_.begin(i); it!=matrix_.end(i); ++it )
+ {
+ const size_t j( it->index() );
+
+ if( i == j )
+ continue;
+
+ if( SO ) {
+ const Iterator_<MT> pos( matrix_.find( i, j ) );
+ BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, pos );
+ }
+ else {
+ const Iterator_<MT> pos( matrix_.find( j, i ) );
+ BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, pos );
+ }
+ }
+
+ matrix_.reset( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the symmetric matrix.
+//
+// \return void
+//
+// This function clears the symmetric matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the symmetric matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+//
+// This function sets the value of both the elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ of the
+// symmetric matrix and returns an iterator to the successfully set element \f$ a_{ij} \f$. In
+// case the symmetric matrix already contains the two elements with index \a i and \a j their
+// values are modified, else two new elements with the given \a value are inserted.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::set( size_t i, size_t j, const ElementType& value )
+{
+ if( i != j )
+ matrix_.set( j, i, value );
+ return Iterator( matrix_.set( i, j, value ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the symmetric matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+//
+// This function inserts both the elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ into the symmetric
+// matrix and returns an iterator to the successfully inserted element \f$ a_{ij} \f$. However,
+// duplicate elements are not allowed. In case the symmetric matrix an element with row index
+// \a i and column index \a j, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::insert( size_t i, size_t j, const ElementType& value )
+{
+ if( i != j )
+ matrix_.insert( j, i, value );
+ return Iterator( matrix_.insert( i, j, value ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the symmetric matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases both elements \f$ a_{ij} \f$ and \f$ a_{ji} \f$ from the symmetric matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::erase( size_t i, size_t j )
+{
+ matrix_.erase( i, j );
+ if( i != j )
+ matrix_.erase( j, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the symmetric matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases both the specified element and its according symmetric counterpart from
+// the symmetric matrix. In case the storage order is set to \a rowMajor the given index \a i
+// refers to a row, in case the storage flag is set to \a columnMajor \a i refers to a column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::erase( size_t i, Iterator pos )
+{
+ const Iterator_<MT> base( pos.base() );
+
+ if( base == matrix_.end( i ) )
+ return pos;
+
+ const size_t j( base->index() );
+
+ if( i == j ) {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( i, i ) != matrix_.end( i ), "Missing element detected" );
+ return Iterator( matrix_.erase( i, base ), matrix_, i );
+ }
+
+ if( SO ) {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( i, j ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, matrix_.find( i, j ) );
+ return Iterator( matrix_.erase( i, base ), matrix_, i );
+ }
+ else {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( j, i ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, matrix_.find( j, i ) );
+ return Iterator( matrix_.erase( i, base ), matrix_, i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the symmetric matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases both the range of elements specified by the iterator pair \a first and
+// \a last and their according symmetric counterparts from the symmetric matrix. In case the
+// storage order is set to \a rowMajor the given index \a i refers to a row, in case the storage
+// flag is set to \a columnMajor \a i refers to a column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::erase( size_t i, Iterator first, Iterator last )
+{
+ for( Iterator_<MT> it=first.base(); it!=last.base(); ++it )
+ {
+ const size_t j( it->index() );
+
+ if( i == j )
+ continue;
+
+ if( SO ) {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( i, j ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( i, j );
+ }
+ else {
+ BLAZE_INTERNAL_ASSERT( matrix_.find( j, i ) != matrix_.end( j ), "Missing element detected" );
+ matrix_.erase( j, i );
+ }
+ }
+
+ return Iterator( matrix_.erase( i, first.base(), last.base() ), matrix_, i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the symmetric matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void SymmetricMatrix<MT,SO,false,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
+
+ matrix_.resize( n, n, true );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the symmetric matrix.
+//
+// \param nonzeros The new minimum capacity of the symmetric matrix.
+// \return void
+//
+// This function increases the capacity of the symmetric matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the symmetric matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the symmetric matrix to at least
+// \a nonzeros elements. The current values of the symmetric matrix and all other individual
+// row/column capacities are preserved. In case the storage order is set to \a rowMajor, the
+// function reserves capacity for row \a i. In case the storage order is set to \a columnMajor,
+// the function reserves capacity for column \a i. The index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the symmetric matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose the symmetric matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>& SymmetricMatrix<MT,SO,false,true>::transpose()
+{
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose the symmetric matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline SymmetricMatrix<MT,SO,false,true>& SymmetricMatrix<MT,SO,false,true>::ctranspose()
+{
+ if( !IsBuiltin<ElementType>::value )
+ conjugate( matrix_ );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline SymmetricMatrix<MT,SO,false,true>&
+ SymmetricMatrix<MT,SO,false,true>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the symmetric matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the symmetric matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline SymmetricMatrix<MT,SO,false,true>&
+ SymmetricMatrix<MT,SO,false,true>::scaleDiagonal( Other scalar )
+{
+ matrix_.scaleDiagonal( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::swap( SymmetricMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the symmetric
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned symmetric matrix iterator is subject
+// to invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::find( size_t i, size_t j )
+{
+ return Iterator( matrix_.find( i, j ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the symmetric
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned symmetric matrix iterator is subject
+// to invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstIterator
+ SymmetricMatrix<MT,SO,false,true>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned symmetric matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::lowerBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.lowerBound( i, j ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned symmetric matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstIterator
+ SymmetricMatrix<MT,SO,false,true>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned symmetric matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::Iterator
+ SymmetricMatrix<MT,SO,false,true>::upperBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.upperBound( i, j ), matrix_, ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned symmetric matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename SymmetricMatrix<MT,SO,false,true>::ConstIterator
+ SymmetricMatrix<MT,SO,false,true>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the symmetric matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function both appends the element \f$ a_{ij} \f$ to the specified row/column and inserts
+// its according counterpart \f$ a_{ji} \f$ into the symmetric matrix. Since element \f$ a_{ij} \f$
+// is appended without any additional memory allocation, it is strictly necessary to keep the
+// following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// Although in addition to element \f$ a_{ij} \f$ a second element \f$ a_{ji} \f$ is inserted into
+// the matrix, this function still provides the most efficient way to fill a symmetric matrix with
+// values. However, in order to achieve maximum efficiency, the matrix has to be specifically
+// prepared with reserve() calls:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::rowMajor;
+
+ // Setup of the symmetric matrix
+ //
+ // ( 0 1 3 )
+ // A = ( 1 2 0 )
+ // ( 3 0 0 )
+
+ SymmetricMatrix< CompressedMatrix<double,rowMajor> > A( 3 );
+
+ A.reserve( 5 ); // Reserving enough capacity for 5 non-zero elements
+ A.reserve( 0, 2 ); // Reserving two non-zero elements in the first row
+ A.reserve( 1, 2 ); // Reserving two non-zero elements in the second row
+ A.reserve( 2, 1 ); // Reserving a single non-zero element in the third row
+ A.append( 0, 1, 1.0 ); // Appending the value 1 at position (0,1) and (1,0)
+ A.append( 1, 1, 2.0 ); // Appending the value 2 at position (1,1)
+ A.append( 2, 0, 3.0 ); // Appending the value 3 at position (2,0) and (0,2)
+ \endcode
+
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ matrix_.append( i, j, value, check );
+ if( i != j && ( !check || !isDefault( value ) ) )
+ matrix_.insert( j, i, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void SymmetricMatrix<MT,SO,false,true>::finalize( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the symmetric matrix are intact.
+//
+// \return \a true in case the symmetric matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the symmetric matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool SymmetricMatrix<MT,SO,false,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isSymmetric( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool SymmetricMatrix<MT,SO,false,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool SymmetricMatrix<MT,SO,false,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool SymmetricMatrix<MT,SO,false,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricElement.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricElement.h
new file mode 100644
index 00000000..507ff8bf
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricElement.h
@@ -0,0 +1,403 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/SymmetricElement.h
+// \brief Header file for the SymmetricElement class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SYMMETRICELEMENT_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SYMMETRICELEMENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/symmetricmatrix/SymmetricValue.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Representation of two synchronized elements within the sparse symmetric matrix.
+// \ingroup symmetric_matrix
+//
+// The SymmetricElement class represents two synchronized elements (i.e. two value/index pairs)
+// within a sparse symmetric matrix. It guarantees that a modification of element \f$ a_{ij} \f$
+// via iterator is also applied to element \f$ a_{ji} \f$. The following example illustrates this
+// by means of a \f$ 3 \times 3 \f$ dense Hermitian matrix:
+
+ \code
+ typedef blaze::SymmetricMatrix< blaze::CompressedMatrix<int> > Symmetric;
+
+ // Creating a 3x3 symmetric sparse matrix
+ //
+ // ( 0 0 -2 )
+ // ( 0 3 5 )
+ // ( -2 5 0 )
+ //
+ Symmetric A( 3UL );
+ A(0,2) = -2;
+ A(1,1) = 3;
+ A(1,2) = 5;
+
+ // Modification of the values at position (2,0) and (0,2)
+ //
+ // ( 0 0 4 )
+ // ( 0 3 5 )
+ // ( 4 5 0 )
+ //
+ Symmetric::Iterator it = A.begin( 2UL );
+ *it = 4;
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class SymmetricElement : private SparseElement
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> ElementType; //!< Type of the represented matrix element.
+ typedef Iterator_<MT> IteratorType; //!< Type of the underlying sparse matrix iterators.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SymmetricValue<MT> ValueType; //!< The value type of the value-index-pair.
+ typedef size_t IndexType; //!< The index type of the value-index-pair.
+ typedef SymmetricValue<MT> Reference; //!< Reference return type.
+ typedef const SymmetricValue<MT> ConstReference; //!< Reference-to-const return type.
+ typedef SymmetricElement* Pointer; //!< Pointer return type.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline SymmetricElement( IteratorType pos, MT* matrix, size_t idx );
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ template< typename T > inline SymmetricElement& operator= ( const T& v );
+ template< typename T > inline SymmetricElement& operator+=( const T& v );
+ template< typename T > inline SymmetricElement& operator-=( const T& v );
+ template< typename T > inline SymmetricElement& operator*=( const T& v );
+ template< typename T > inline SymmetricElement& operator/=( const T& v );
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline Pointer operator->() noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline Reference value() const;
+ inline IndexType index() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void sync();
+ inline bool isSynced() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse Hermitian matrix element.
+ MT* matrix_; //!< The sparse matrix containing the iterator.
+ size_t index_; //!< The row/column index of the iterator.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( ElementType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the SymmetricElement class.
+//
+// \param pos The initial position of the iterator.
+// \param matrix The sparse matrix containing the iterator.
+// \param idx The row/column index of the iterator.
+*/
+template< typename MT > // Type of the adapted matrix
+inline SymmetricElement<MT>::SymmetricElement( IteratorType pos, MT* matrix, size_t idx )
+ : pos_ ( pos ) // Iterator to the current sparse symmetric matrix element
+ , matrix_( matrix ) // The sparse matrix containing the iterator
+ , index_ ( idx ) // The row/column index of the iterator
+{
+ BLAZE_INTERNAL_ASSERT( isSynced(), "Missing matrix element detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Assignment to the symmetric element.
+//
+// \param v The new value of the symmetric element.
+// \return Reference to the assigned Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricElement<MT>& SymmetricElement<MT>::operator=( const T& v )
+{
+ *pos_ = v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the Hermitian element.
+//
+// \param v The right-hand side value for the addition.
+// \return Reference to the assigned Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricElement<MT>& SymmetricElement<MT>::operator+=( const T& v )
+{
+ *pos_ += v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the Hermitian element.
+//
+// \param v The right-hand side value for the subtraction.
+// \return Reference to the assigned Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricElement<MT>& SymmetricElement<MT>::operator-=( const T& v )
+{
+ *pos_ -= v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the Hermitian element.
+//
+// \param v The right-hand side value for the multiplication.
+// \return Reference to the assigned Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricElement<MT>& SymmetricElement<MT>::operator*=( const T& v )
+{
+ *pos_ *= v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the Hermitian element.
+//
+// \param v The right-hand side value for the division.
+// \return Reference to the assigned Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricElement<MT>& SymmetricElement<MT>::operator/=( const T& v )
+{
+ *pos_ /= v;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the Hermitian element.
+//
+// \return Reference to the value of the Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename SymmetricElement<MT>::Pointer SymmetricElement<MT>::operator->() noexcept
+{
+ return this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access to the current value of the Hermitian element.
+//
+// \return The current value of the Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename SymmetricElement<MT>::Reference SymmetricElement<MT>::value() const
+{
+ return Reference( pos_, matrix_, index_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the current index of the Hermitian element.
+//
+// \return The current index of the Hermitian element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename SymmetricElement<MT>::IndexType SymmetricElement<MT>::index() const
+{
+ return pos_->index();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Synchronization of the current sparse element to the according paired element.
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void SymmetricElement<MT>::sync()
+{
+ if( pos_->index() == index_ || isDefault( pos_->value() ) )
+ return;
+
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+
+ matrix_->set( row, column, pos_->value() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checking if the current sparse element is in sync.
+//
+// \return \a true if the current sparse element is in sync, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool SymmetricElement<MT>::isSynced() const
+{
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+
+ const IteratorType pos2( matrix_->find( row, column ) );
+ const IteratorType end( matrix_->end( pos_->index() ) );
+
+ return ( isDefault( pos_->value() ) && ( pos2 == end || isDefault( pos2->value() ) ) ) ||
+ ( pos2 != end && pos_->value() == pos2->value() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricValue.h b/src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricValue.h
new file mode 100644
index 00000000..c058594b
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricValue.h
@@ -0,0 +1,767 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/symmetricmatrix/SymmetricValue.h
+// \brief Header file for the SymmetricValue class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SYMMETRICVALUE_H_
+#define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_SYMMETRICVALUE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Representation of two synchronized values within a sparse symmetric matrix.
+// \ingroup symmetric_matrix
+//
+// The SymmetricValue class represents two synchronized values within a sparse symmetric matrix.
+// It guarantees that a modification of value \f$ a_{ij} \f$ via iterator is also applied to the
+// value \f$ a_{ji} \f$. The following example illustrates this by means of a \f$ 3 \times 3 \f$
+// sparse symmetric matrix:
+
+ \code
+ typedef blaze::SymmetricMatrix< blaze::CompressedMatrix<int> > Symmetric;
+
+ // Creating a 3x3 symmetric sparse matrix
+ //
+ // ( 0 0 -2 )
+ // ( 0 3 5 )
+ // ( -2 5 0 )
+ //
+ Symmetric A( 3UL );
+ A(0,2) = -2;
+ A(1,1) = 3;
+ A(1,2) = 5;
+
+ // Modification of the values at position (2,0) and (0,2)
+ //
+ // ( 0 0 4 )
+ // ( 0 3 5 )
+ // ( 4 5 0 )
+ //
+ Symmetric::Iterator it = A.begin( 2UL );
+ it->value() = 4;
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class SymmetricValue : public Proxy< SymmetricValue<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef typename MT::Iterator IteratorType; //!< Type of the underlying sparse matrix iterators.
+ //**********************************************************************************************
+
+ //**struct BuiltinType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct BuiltinType { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct ComplexType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct ComplexType { typedef typename T::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+
+ //! Value type of the represented complex element.
+ typedef typename If_< IsComplex<RepresentedType>
+ , ComplexType<RepresentedType>
+ , BuiltinType<RepresentedType> >::Type ValueType;
+
+ typedef ValueType value_type; //!< Value type of the represented complex element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline SymmetricValue( IteratorType pos, MT* matrix, size_t index );
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline SymmetricValue& operator= ( const SymmetricValue& sv );
+ template< typename T > inline SymmetricValue& operator= ( const T& value );
+ template< typename T > inline SymmetricValue& operator+=( const T& value );
+ template< typename T > inline SymmetricValue& operator-=( const T& value );
+ template< typename T > inline SymmetricValue& operator*=( const T& value );
+ template< typename T > inline SymmetricValue& operator/=( const T& value );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void reset () const;
+ inline void clear () const;
+ inline void invert() const;
+
+ inline RepresentedType get() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RepresentedType() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Complex data access functions***************************************************************
+ /*!\name Complex data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void sync() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse symmetric matrix element.
+ MT* matrix_; //!< The sparse matrix containing the iterator.
+ size_t index_; //!< The row/column index of the iterator.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the SymmetricValue class.
+//
+// \param pos The initial position of the iterator.
+// \param matrix The sparse matrix containing the iterator.
+// \param index The row/column index of the iterator.
+*/
+template< typename MT > // Type of the adapted matrix
+inline SymmetricValue<MT>::SymmetricValue( IteratorType pos, MT* matrix, size_t index )
+ : pos_ ( pos ) // Iterator to the current sparse symmetric matrix element
+ , matrix_( matrix ) // The sparse matrix containing the iterator
+ , index_ ( index ) // The row/column index of the iterator
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for SymmetricValue.
+//
+// \param sv The symmetric value to be copied.
+// \return Reference to the assigned symmetric value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline SymmetricValue<MT>& SymmetricValue<MT>::operator=( const SymmetricValue& sv )
+{
+ pos_->value() = sv.pos_->value();
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the symmetric value.
+//
+// \param value The new value of the symmetric value.
+// \return Reference to the assigned symmetric value.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricValue<MT>& SymmetricValue<MT>::operator=( const T& value )
+{
+ pos_->value() = value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the symmetric value.
+//
+// \param value The right-hand side value to be added to the symmetric value.
+// \return Reference to the assigned symmetric value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricValue<MT>& SymmetricValue<MT>::operator+=( const T& value )
+{
+ pos_->value() += value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the symmetric value.
+//
+// \param value The right-hand side value to be subtracted from the symmetric value.
+// \return Reference to the assigned symmetric value.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricValue<MT>& SymmetricValue<MT>::operator-=( const T& value )
+{
+ pos_->value() -= value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the symmetric value.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned symmetric value.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricValue<MT>& SymmetricValue<MT>::operator*=( const T& value )
+{
+ pos_->value() *= value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the symmetric value.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned symmetric value.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline SymmetricValue<MT>& SymmetricValue<MT>::operator/=( const T& value )
+{
+ pos_->value() /= value;
+ sync();
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reset the symmetric value to its default initial value.
+//
+// \return void
+//
+// This function resets the symmetric value to its default initial value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void SymmetricValue<MT>::reset() const
+{
+ using blaze::reset;
+
+ reset( pos_->value() );
+
+ if( pos_->index() != index_ )
+ {
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+ const IteratorType pos2( matrix_->find( row, column ) );
+
+ reset( pos2->value() );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the symmetric value.
+//
+// \return void
+//
+// This function clears the symmetric value to its default initial state.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void SymmetricValue<MT>::clear() const
+{
+ using blaze::clear;
+
+ clear( pos_->value() );
+
+ if( pos_->index() != index_ )
+ {
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+ const IteratorType pos2( matrix_->find( row, column ) );
+
+ clear( pos2->value() );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the symmetric value
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void SymmetricValue<MT>::invert() const
+{
+ using blaze::invert;
+
+ invert( pos_->value() );
+
+ if( pos_->index() != index_ )
+ {
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+ const IteratorType pos2( matrix_->find( row, column ) );
+
+ pos2->value() = pos_->value();
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the represented value.
+//
+// \return Copy of the represented value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename SymmetricValue<MT>::RepresentedType SymmetricValue<MT>::get() const noexcept
+{
+ return pos_->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Synchronization of the current sparse element to the according paired element.
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void SymmetricValue<MT>::sync() const
+{
+ if( pos_->index() == index_ || isDefault( pos_->value() ) )
+ return;
+
+ const size_t row ( ( IsRowMajorMatrix<MT>::value )?( pos_->index() ):( index_ ) );
+ const size_t column( ( IsRowMajorMatrix<MT>::value )?( index_ ):( pos_->index() ) );
+
+ matrix_->set( row, column, pos_->value() );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the represented value.
+//
+// \return Copy of the represented value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline SymmetricValue<MT>::operator RepresentedType() const noexcept
+{
+ return pos_->value();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// In case the value represents a complex number, this function returns the current value
+// of its real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename SymmetricValue<MT>::ValueType SymmetricValue<MT>::real() const
+{
+ return pos_->value().real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+//
+// In case the value represents a complex number, this function sets a new value to its
+// real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void SymmetricValue<MT>::real( ValueType value ) const
+{
+ pos_->value().real() = value;
+ sync();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// In case the value represents a complex number, this function returns the current value of its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename SymmetricValue<MT>::ValueType SymmetricValue<MT>::imag() const
+{
+ return pos_->value.imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+//
+// In case the proxy represents a complex number, this function sets a new value to its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void SymmetricValue<MT>::imag( ValueType value ) const
+{
+ pos_->value().imag( value );
+ sync();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SymmetricValue global functions */
+//@{
+template< typename MT >
+inline void reset( const SymmetricValue<MT>& value );
+
+template< typename MT >
+inline void clear( const SymmetricValue<MT>& value );
+
+template< typename MT >
+inline void invert( const SymmetricValue<MT>& value );
+
+template< typename MT >
+inline bool isDefault( const SymmetricValue<MT>& value );
+
+template< typename MT >
+inline bool isReal( const SymmetricValue<MT>& value );
+
+template< typename MT >
+inline bool isZero( const SymmetricValue<MT>& value );
+
+template< typename MT >
+inline bool isOne( const SymmetricValue<MT>& value );
+
+template< typename MT >
+inline bool isnan( const SymmetricValue<MT>& value );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the symmetric value to the default initial values.
+// \ingroup symmetric_matrix
+//
+// \param value The given symmetric value.
+// \return void
+//
+// This function resets the symmetric value to its default initial value.
+*/
+template< typename MT >
+inline void reset( const SymmetricValue<MT>& value )
+{
+ value.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the symmetric value.
+// \ingroup symmetric_matrix
+//
+// \param value The given symmetric value.
+// \return void
+//
+// This function clears the symmetric value to its default initial state.
+*/
+template< typename MT >
+inline void clear( const SymmetricValue<MT>& value )
+{
+ value.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the symmetric value.
+// \ingroup symmetric_matrix
+//
+// \param value The given symmetric value.
+// \return void
+*/
+template< typename MT >
+inline void invert( const SymmetricValue<MT>& value )
+{
+ value.invert();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the symmetric value is in default state.
+// \ingroup symmetric_matrix
+//
+// \param value The given symmetric value.
+// \return \a true in case the symmetric value is in default state, \a false otherwise.
+//
+// This function checks whether the symmetric value is in default state. In case it is in
+// default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const SymmetricValue<MT>& value )
+{
+ using blaze::isDefault;
+
+ return isDefault( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the symmetric value represents a real number.
+// \ingroup symmetric_matrix
+//
+// \param value The given symmetric value.
+// \return \a true in case the symmetric value represents a real number, \a false otherwise.
+//
+// This function checks whether the symmetric value represents the a real number. In case the
+// value is of built-in type, the function returns \a true. In case the element is of complex
+// type, the function returns \a true if the imaginary part is equal to 0. Otherwise it returns
+// \a false.
+*/
+template< typename MT >
+inline bool isReal( const SymmetricValue<MT>& value )
+{
+ using blaze::isReal;
+
+ return isReal( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the symmetric value is 0.
+// \ingroup symmetric_matrix
+//
+// \param value The given symmetric value.
+// \return \a true in case the symmetric value is 0, \a false otherwise.
+//
+// This function checks whether the symmetric value represents the numeric value 0. In case it
+// is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const SymmetricValue<MT>& value )
+{
+ using blaze::isZero;
+
+ return isZero( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the symmetric value is 1.
+// \ingroup symmetric_matrix
+//
+// \param value The given symmetric value.
+// \return \a true in case the symmetric value is 1, \a false otherwise.
+//
+// This function checks whether the symmetric value represents the numeric value 1. In case it
+// is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const SymmetricValue<MT>& value )
+{
+ using blaze::isOne;
+
+ return isOne( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the symmetric value is not a number.
+// \ingroup symmetric_matrix
+//
+// \param value The given symmetric value.
+// \return \a true in case the symmetric value is in not a number, \a false otherwise.
+//
+// This function checks whether the symmetric value is not a number (NaN). In case it is not a
+// number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const SymmetricValue<MT>& value )
+{
+ using blaze::isnan;
+
+ return isnan( value.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/unilowermatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/unilowermatrix/BaseTemplate.h
new file mode 100644
index 00000000..7f6f4e47
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/unilowermatrix/BaseTemplate.h
@@ -0,0 +1,579 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/unilowermatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the UniLowerMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup unilower_matrix UniLowerMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for lower unitriangular \f$ N \times N \f$ matrices.
+// \ingroup unilower_matrix
+//
+// \section unilowermatrix_general General
+//
+// The UniLowerMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \a MT and extends it
+// by enforcing the additional invariant that all diagonal matrix elements are 1 and all matrix
+// elements above the diagonal are 0 (lower unitriangular matrix). The type of the adapted matrix
+// can be specified via the first template parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF >
+ class UniLowerMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. UniLowerMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Also, the given matrix type must have numeric element types (i.e. all integral
+// types except \a bool, floating point and complex types). Note that the given matrix
+// type must be either resizable (as for instance HybridMatrix or DynamicMatrix) or
+// must be square at compile time (as for instance StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+// The following examples give an impression of several possible lower unitriangular matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense unilower matrix with static memory
+ blaze::UniLowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense unilower matrix based on HybridMatrix
+ blaze::UniLowerMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense unilower matrix based on DynamicMatrix
+ blaze::UniLowerMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense unilower matrix based on CustomMatrix
+ blaze::UniLowerMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision unilower matrix
+ blaze::UniLowerMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of a lower unitriangular matrix is depending on the storage order of the
+// adapted matrix type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e.
+// is specified as blaze::rowMajor), the unilower matrix will also be a row-major matrix.
+// Otherwise if the adapted matrix is column-major (i.e. is specified as blaze::columnMajor),
+// the unilower matrix will also be a column-major matrix.
+//
+//
+// \n \section unilowermatrix_special_properties Special Properties of Lower Unitriangular Matrices
+//
+// A lower unitriangular matrix is used exactly like a matrix of the underlying, adapted matrix
+// type \a MT. It also provides (nearly) the same interface as the underlying matrix type. However,
+// there are some important exceptions resulting from the lower unitriangular matrix constraint:
+//
+// -# <b>\ref unilowermatrix_square</b>
+// -# <b>\ref unilowermatrix_unilower</b>
+// -# <b>\ref unilowermatrix_initialization</b>
+// -# <b>\ref unilowermatrix_storage</b>
+// -# <b>\ref unilowermatrix_scaling</b>
+
+//
+// \n \subsection unilowermatrix_square Lower Unitriangular Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 unilower dynamic matrix
+ UniLowerMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::UniLowerMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 unilower static matrix
+ UniLowerMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ UniLowerMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+//
+// \n \subsection unilowermatrix_unilower The Lower Unitriangular Matrix Property is Always Enforced!
+//
+// The diagonal elements of a lower unitriangular matrix are fixed to 1. This property has two
+// implications. First, that means that the diagonal elements of a newly created unilower matrix
+// are pre-initialized to 1:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+ using blaze::rowMajor;
+
+ // Creating a default initialized dense unilower matrix of size 3x3
+ //
+ // ( 1 0 0 )
+ // A = ( 0 1 0 )
+ // ( 0 0 1 )
+ UniLowerMatrix< DynamicMatrix<int,rowMajor> > A( 3UL );
+
+ // Creating a default initialized sparse unilower matrix of size 3x3
+ //
+ // ( 1 0 0 )
+ // B = ( 0 1 0 )
+ // ( 0 0 1 )
+ UniLowerMatrix< CompressedMatrix<int,rowMajor> > B( 3UL );
+ \endcode
+
+// Second, this means that it is only allowed to modify elements in the lower part of the matrix,
+// but not the diagonal elements and not the elements in the upper part of the matrix. Also, it
+// is only possible to assign matrices that are lower unitriangular matrices themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::UniLowerMatrix;
+ using blaze::columnMajor;
+
+ typedef UniLowerMatrix< CompressedMatrix<double,columnMajor> > CompressedUniLower;
+
+ // Default constructed, row-major 3x3 unilower compressed matrix
+ CompressedUniLower A( 3 );
+
+ // Initializing elements via the function call operator
+ A(0,0) = 9.0; // Throws an exception; invalid modification of diagonal element
+ A(2,0) = 2.0; // Initialization of the lower element (2,0)
+ A(1,2) = 9.0; // Throws an exception; invalid modification of upper element
+
+ // Inserting elements via the insert() function
+ A.insert( 1, 0, 3.0 ); // Inserting the lower element (1,0)
+ A.insert( 1, 1, 9.0 ); // Throws an exception; invalid insertion of diagonal element
+ A.insert( 0, 2, 9.0 ); // Throws an exception; invalid insertion of upper element
+
+ // Appending an element via the append() function
+ A.reserve( 1, 3 ); // Reserving enough capacity in column 1
+ A.append( 1, 1, 9.0 ); // Throws an exception; appending a diagonal element
+ A.append( 2, 1, 4.0 ); // Appending the lower element (2,1)
+
+ // Access via a non-const iterator
+ CompressedUniLower::Iterator it = A.begin(1);
+ *it = 9.0; // Throws an exception; invalid modification of the diagonal element (1,1)
+ ++it;
+ *it = 6.0; // Modifies the lower element (2,1)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Throws an exception; invalid erasure of the diagonal element (0,0)
+ A.erase( 2, 0 ); // Erasing the lower element (2,0)
+
+ // Construction from an unilower dense matrix
+ StaticMatrix<double,3UL,3UL> B( 1.0, 0.0, 0.0,
+ 8.0, 1.0, 0.0,
+ -2.0, -1.0, 1.0 );
+
+ UniLowerMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-unilower dense matrix
+ StaticMatrix<double,3UL,3UL> D( 3.0, 0.0, -2.0,
+ 8.0, 0.0, 0.0,
+ -2.0, -1.0, 4.0 );
+
+ C = D; // Throws an exception; lower unitriangular matrix invariant would be violated!
+ \endcode
+
+// The lower unitriangular matrix property is also enforced for unilower custom matrices: In case
+// the given array of elements does not represent an unilower matrix, a \a std::invalid_argument
+// exception is thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::UniLowerMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef UniLowerMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomUniLower;
+
+ // Creating a 3x3 unilower custom matrix from a properly initialized array
+ double array[9] = { 1.0, 0.0, 0.0,
+ 2.0, 1.0, 0.0,
+ 3.0, 4.0, 1.0 };
+ CustomUniLower A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 unilower custom matrix from an uninitialized array
+ CustomUniLower B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the lower unitriangular matrix property is enforced for views (rows, columns,
+// submatrices, ...) on the unilower matrix. The following example demonstrates that modifying
+// the elements of an entire row and submatrix of an unilower matrix only affects the lower
+// matrix elements:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+
+ // Setup of the unilower matrix
+ //
+ // ( 1 0 0 0 )
+ // A = ( 2 1 0 0 )
+ // ( 0 3 1 0 )
+ // ( 4 0 5 1 )
+ //
+ UniLowerMatrix< DynamicMatrix<int> > A( 4 );
+ A(1,0) = 2;
+ A(2,1) = 3;
+ A(3,0) = 4;
+ A(3,2) = 5;
+
+ // Setting the lower elements in the 2nd row to 9 results in the matrix
+ //
+ // ( 1 0 0 0 )
+ // A = ( 2 1 0 0 )
+ // ( 9 9 1 0 )
+ // ( 4 0 5 1 )
+ //
+ row( A, 2 ) = 9;
+
+ // Setting the lower elements in the 1st and 2nd column to 7 results in
+ //
+ // ( 1 0 0 0 )
+ // A = ( 1 1 0 0 )
+ // ( 9 7 1 0 )
+ // ( 4 7 7 1 )
+ //
+ submatrix( A, 0, 1, 4, 2 ) = 7;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to rows/columns and submatrices of
+// unilower matrices. Since only lower elements may be modified the matrix to be assigned must
+// be structured such that the lower unitriangular matrix invariant of the unilower matrix is
+// preserved. Otherwise a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::UniLowerMatrix;
+ using blaze::rowVector;
+
+ // Setup of two default 4x4 unilower matrices
+ UniLowerMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of a 4-dimensional vector
+ //
+ // v = ( 1 2 3 0 )
+ //
+ DynamicVector<int,rowVector> v( 4, 0 );
+ v[0] = 3;
+ v[1] = 2;
+ v[2] = 1;
+
+ // OK: Assigning v to the 2nd row of A1 preserves the unilower matrix invariant
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 0 0 0 )
+ // ( 3 2 1 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 2 ) = v; // OK
+
+ // Error: Assigning v to the 1st row of A1 violates the unilower matrix invariant! The elements
+ // marked with X cannot be assigned and trigger an exception.
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 3 X X 0 )
+ // ( 3 2 1 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 1 ) = v; // Assignment throws an exception!
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 1 0 )
+ // B = ( 7 1 )
+ // ( 8 9 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL, 0 );
+ B(0,0) = 1;
+ B(1,0) = 7;
+ B(1,1) = 1;
+ B(2,0) = 8;
+ B(2,1) = 9;
+
+ // OK: Assigning B to a submatrix of A2 such that the unilower matrix invariant can be preserved
+ //
+ // ( 1 0 0 0 )
+ // A2 = ( 0 1 0 0 )
+ // ( 0 7 1 0 )
+ // ( 0 8 9 1 )
+ //
+ submatrix( A2, 1UL, 1UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the lower matrix invariant cannot be
+ // preserved! The elements marked with X cannot be assigned without violating the invariant!
+ //
+ // ( 1 0 0 0 )
+ // A2 = ( 0 1 X 0 )
+ // ( 0 7 X X )
+ // ( 0 8 8 X )
+ //
+ submatrix( A2, 1UL, 2UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection unilowermatrix_initialization The Upper Elements of a Dense Lower Unitriangular Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency during the creation of a dense unilower
+// matrix this initialization is important since otherwise the lower unitriangular matrix property
+// of dense unilower matrices would not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // 5x5 row-major unilower dynamic matrix with default initialized upper matrix
+ UniLowerMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \subsection unilowermatrix_storage Dense Lower Unitriangular Matrices Also Store the Upper Elements!
+//
+// It is important to note that dense lower unitriangular matrices store all elements, including
+// the elements in the upper part of the matrix, and therefore don't provide any kind of memory
+// reduction! There are two main reasons for this: First, storing also the upper elements
+// guarantees maximum performance for many algorithms that perform vectorized operations on the
+// unilower matrix, which is especially true for small dense matrices. Second, conceptually the
+// UniLowerMatrix adaptor merely restricts the interface to the matrix type \a MT and does not
+// change the data layout or the underlying matrix type.
+//
+//
+// \n \subsection unilowermatrix_scaling Lower Unitriangular Matrices Cannot Be Scaled!
+//
+// Since the diagonal elements have a fixed value of 1 it is not possible to self-scale an unilower
+// matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+
+ UniLowerMatrix< DynamicMatrix<int> > A( 4 );
+
+ A *= 2; // Compilation error; Scale operation is not available on an unilower matrix
+ A /= 2; // Compilation error; Scale operation is not available on an unilower matrix
+ A.scale( 2 ); // Compilation error; Scale function is not available on an unilower matrix
+
+ A = A * 2; // Throws an exception; Invalid assignment of non-unilower matrix
+ A = A / 2; // Throws an exception; Invalid assignment of non-unilower matrix
+ \endcode
+
+// \n \section unilowermatrix_arithmetic_operations Arithmetic Operations
+//
+// An UniLowerMatrix matrix can participate in numerical operations in any way any other dense or
+// sparse matrix can participate. It can also be combined with any other dense or sparse vector
+// or matrix. The following code example gives an impression of the use of UniLowerMatrix within
+// arithmetic operations:
+
+ \code
+ using blaze::UniLowerMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ UniLowerMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ UniLowerMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ UniLowerMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > E;
+ UniLowerMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > F;
+
+ DynamicMatrix<double,rowMajor> G( 3, 3 ); // Initialized as strictly lower matrix
+ CompressedMatrix<double,rowMajor> H( 3, 3 ); // Initialized as strictly lower matrix
+
+ E = A + B; // Matrix addition and assignment to a row-major unilower matrix
+ F = A - C; // Matrix subtraction and assignment to a column-major unilower matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ E += G; // Addition assignment (note that G is a strictly lower matrix)
+ F -= H; // Subtraction assignment (note that H is a strictly lower matrix)
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section unilowermatrix_performance Performance Considerations
+//
+// The \b Blaze library tries to exploit the properties of lower (uni)-triangular matrices whenever
+// and wherever possible. Thus using a lower (uni-)triangular matrix instead of a general matrix
+// can result in a considerable performance improvement. However, there are also situations when
+// using a (uni-)lower matrix introduces some overhead. The following examples demonstrate several
+// common situations where (uni-)lower matrices can positively or negatively impact performance.
+//
+// \n \subsection unilowermatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is lower (uni)-triangular, \b Blaze can
+// exploit the fact that the upper part of the matrix contains only default elements and restrict
+// the algorithm to the lower and diagonal elements. The following example demonstrates this by
+// means of a dense matrix/dense matrix multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ UniLowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ UniLowerMatrix< DynamicMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// In comparison to a general matrix multiplication, the performance advantage is significant,
+// especially for large matrices. Therefore is it highly recommended to use the UniLowerMatrix
+// adaptor when a matrix is known to be lower unitriangular. Note however that the performance
+// advantage is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection unilowermatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar performance improvement can be gained when using a lower (uni-)triangular matrix in
+// a matrix/vector multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::UniLowerMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ UniLowerMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicVector<double,columnVector> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example, \b Blaze also exploits the structure of the matrix and approx. halves the
+// runtime of the multiplication. Also in case of matrix/vector multiplications the performance
+// improvement is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection unilowermatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using a lower (uni-)triangular matrix on the right-hand side of an assignment
+// (i.e. for read access), which introduces absolutely no performance penalty, using a (uni-)lower
+// matrix on the left-hand side of an assignment (i.e. for write access) may introduce additional
+// overhead when it is assigned a general matrix, which is not lower (uni-)triangular at compile
+// time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniLowerMatrix;
+
+ UniLowerMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the unilower matrix; no performance penalty
+ C = A; // Assignment of an unilower matrix to another unilower matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to an unilower matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not unilower matrix to another unilower matrix it is
+// necessary to check whether the matrix is unilower at runtime in order to guarantee the lower
+// unitriangular property of the unilower matrix. In case it turns out to be lower unitriangular,
+// it is assigned as efficiently as possible, if it is not, an exception is thrown. In order to
+// prevent this runtime overhead it is therefore generally advisable to assign unilower matrices
+// to other unilower matrices.\n
+// In this context it is especially noteworthy that the multiplication of two lower unitriangular
+// matrices always results in another unilower matrix:
+
+ \code
+ UniLowerMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A * B; // Results in a lower matrix; no runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class UniLowerMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/unilowermatrix/Dense.h b/src/cpu/blaze/math/adaptors/unilowermatrix/Dense.h
new file mode 100644
index 00000000..fb2219ef
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/unilowermatrix/Dense.h
@@ -0,0 +1,2697 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/unilowermatrix/Dense.h
+// \brief UniLowerMatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_DENSE_H_
+#define _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/unilowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/unilowermatrix/UniLowerProxy.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/Square.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of UniLowerMatrix for dense matrices.
+// \ingroup unilower_matrix
+//
+// This specialization of UniLowerMatrix adapts the class template to the requirements of dense
+// matrices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class UniLowerMatrix<MT,SO,true>
+ : public DenseMatrix< UniLowerMatrix<MT,SO,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef UniLowerMatrix<MT,SO,true> This; //!< Type of this UniLowerMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this UniLowerMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef UniLowerMatrix<OT,!SO,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef UniUpperMatrix<TT,!SO,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef UniLowerProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain an UniLowerMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other UniLowerMatrix.
+ typedef UniLowerMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense unilower matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef UniLowerProxy<MT> PointerType; //!< Pointer return type.
+ typedef UniLowerProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row-index of the iterator
+ , column_( column ) // The current column-index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) noexcept {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) noexcept {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) noexcept {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row-index of the iterator.
+ size_t column_; //!< The current column-index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UniLowerMatrix();
+ template< typename A1 > explicit inline UniLowerMatrix( const A1& a1 );
+ explicit inline UniLowerMatrix( size_t n, const ElementType& init );
+
+ explicit inline UniLowerMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline UniLowerMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline UniLowerMatrix( const Other (&array)[N][N] );
+
+ explicit inline UniLowerMatrix( ElementType* ptr, size_t n );
+ explicit inline UniLowerMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline UniLowerMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline UniLowerMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline UniLowerMatrix( const UniLowerMatrix& m );
+ inline UniLowerMatrix( UniLowerMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline UniLowerMatrix& operator=( const ElementType& rhs );
+ inline UniLowerMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline UniLowerMatrix& operator=( const Other (&array)[N][N] );
+
+ inline UniLowerMatrix& operator=( const UniLowerMatrix& rhs );
+ inline UniLowerMatrix& operator=( UniLowerMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniLowerMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniLowerMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniLowerMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniLowerMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniLowerMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniLowerMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline UniLowerMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ inline void swap( UniLowerMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ inline const MT construct( size_t n , TrueType );
+ inline const MT construct( const ElementType& value, FalseType );
+
+ template< typename MT2, bool SO2, typename T >
+ inline const MT construct( const Matrix<MT2,SO2>& m, T );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( UniLowerMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for UniLowerMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ for( size_t i=0UL; i<Rows<MT>::value; ++i )
+ matrix_(i,i) = ElementType(1);
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Single argument constructor for an unilower matrix.
+//
+// \param a1 The single constructor argument.
+// \exception std::invalid_argument Invalid setup of unilower matrix.
+//
+// This constructor constructs the unilower matrix based on the given argument and the type of
+// the underlying matrix \a MT:
+// - in case the given argument is a matrix, the unilower matrix is initialized as a copy of
+// the given matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// resizable, the given argument \a a1 specifies the number of rows and columns of the
+// unilower matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// a matrix with fixed size, the given argument \a a1 specifies the initial value of the
+// lower elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename A1 > // Type of the constructor argument
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( const A1& a1 )
+ : matrix_( construct( a1, typename IsResizable<MT>::Type() ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a \f$ n \times n \f$ matrix with initialized lower elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param init The initial value of the lower matrix elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( size_t n, const ElementType& init )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ matrix_(j,j) = ElementType(1);
+ for( size_t i=j+1UL; i<rows(); ++i )
+ matrix_(i,j) = init;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j )
+ matrix_(i,j) = init;
+ matrix_(i,i) = ElementType(1);
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of unilower matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the unilower
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::UniLowerMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A{ { 1, 0, 0 },
+ { 2, 1 },
+ { 4, 5, 1 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isUniLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all unilower matrix elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of unilower matrix.
+//
+// This constructor offers the option to directly initialize the elements of the unilower matrix
+// with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[16];
+ // ... Initialization of the dynamic array
+ blaze::UniLowerMatrix< blaze::DynamicMatrix<int,rowMajor> > v( 4UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized accoring to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a n by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also, in
+// case the given array does not represent a lower unitriangular matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isUniLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all unilower matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of unilower matrix.
+//
+// This constructor offers the option to directly initialize the elements of the unilower matrix
+// with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 0, 0 },
+ { 2, 1 },
+ { 4, 5, 1 } };
+ blaze::UniLowerMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a lower unitriangular matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isUniLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a unilower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of unilower custom matrix.
+//
+// This constructor creates an unpadded unilower custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a lower unitriangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded unilower custom matrices!
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isUniLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a unilower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of unilower custom matrix.
+//
+// This constructor creates a unilower custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a lower unitriangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isUniLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a unilower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of unilower custom matrix.
+//
+// This constructor creates an unpadded unilower custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent a lower unitriangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded unilower custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isUniLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a unilower custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of unilower custom matrix.
+//
+// This constructor creates a unilower custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent a lower unitriangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isUniLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for UniLowerMatrix.
+//
+// \param m The unilower matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( const UniLowerMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for UniLowerMatrix.
+//
+// \param m The unilower matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>::UniLowerMatrix( UniLowerMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::Reference
+ UniLowerMatrix<MT,SO,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::ConstReference
+ UniLowerMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::Reference
+ UniLowerMatrix<MT,SO,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::ConstReference
+ UniLowerMatrix<MT,SO,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the unilower matrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The unilower matrix
+// may use techniques such as padding to improve the alignment of the data. Whereas the number
+// of elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::ConstPointer
+ UniLowerMatrix<MT,SO,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::ConstPointer
+ UniLowerMatrix<MT,SO,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the unilower matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::Iterator
+ UniLowerMatrix<MT,SO,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the unilower matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::ConstIterator
+ UniLowerMatrix<MT,SO,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the unilower matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::ConstIterator
+ UniLowerMatrix<MT,SO,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the unilower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::Iterator
+ UniLowerMatrix<MT,SO,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the unilower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::ConstIterator
+ UniLowerMatrix<MT,SO,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the unilower matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniLowerMatrix<MT,SO,true>::ConstIterator
+ UniLowerMatrix<MT,SO,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all lower matrix elements.
+//
+// \param rhs Scalar value to be assigned to the lower matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>&
+ UniLowerMatrix<MT,SO,true>::operator=( const ElementType& rhs )
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=j+1UL; i<rows(); ++i )
+ matrix_(i,j) = rhs;
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i )
+ for( size_t j=0UL; j<i; ++j )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the unilower
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::UniLowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = { { 1, 0, 0 },
+ { 2, 1 },
+ { 4, 5, 1 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>&
+ UniLowerMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isUniLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all unilower matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// This assignment operator offers the option to directly set all elements of the unilower matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 0, 0 },
+ { 2, 1 },
+ { 4, 5, 1 } };
+ blaze::UniLowerMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a lower unitriangular matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline UniLowerMatrix<MT,SO,true>&
+ UniLowerMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isUniLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for UniLowerMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>&
+ UniLowerMatrix<MT,SO,true>::operator=( const UniLowerMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for UniLowerMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniLowerMatrix<MT,SO,true>&
+ UniLowerMatrix<MT,SO,true>::operator=( UniLowerMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// unilower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,true>& >
+ UniLowerMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsStrictlyTriangular<MT2>::value || ( !IsUniLower<MT2>::value && !isUniLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// unilower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,true>& >
+ UniLowerMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsStrictlyTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ if( IsUniLower<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isUniLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an unilower
+// matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is not an
+// unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,true>& >
+ UniLowerMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUpper<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an unilower
+// matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is not an
+// unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,true>& >
+ UniLowerMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUpper<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// unilower matrix, i.e. the given matrix must be a strictly lower matrix. In case the
+// result is not an unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,true>& >
+ UniLowerMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUpper<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// unilower matrix, i.e. the given matrix must be a strictly lower matrix. In case the
+// result is not an unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,true>& >
+ UniLowerMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUpper<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be an unilower matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline UniLowerMatrix<MT,SO,true>&
+ UniLowerMatrix<MT,SO,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isUniLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniLowerMatrix<MT,SO,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniLowerMatrix<MT,SO,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the total
+// number of elements of a row/column. In case the unilower matrix adapts a \a rowMajor dense
+// matrix the function returns the spacing between two rows, in case it adapts a \a columnMajor
+// dense matrix the function returns the spacing between two columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniLowerMatrix<MT,SO,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniLowerMatrix<MT,SO,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the unilower
+// matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor dense matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniLowerMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the unilower matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniLowerMatrix<MT,SO,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the unilower matrix adapts a \a rowMajor dense matrix the function returns the
+// number of non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix
+// the function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniLowerMatrix<MT,SO,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniLowerMatrix<MT,SO,true>::reset()
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=j+1UL; i<rows(); ++i )
+ clear( matrix_(i,j) );
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i )
+ for( size_t j=0UL; j<i; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniLowerMatrix<MT,SO,true>::reset( size_t i )
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=i+1UL; j<rows(); ++j )
+ clear( matrix_(j,i) );
+ }
+ else {
+ for( size_t j=0UL; j<i; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the unilower matrix.
+//
+// \return void
+//
+// This function clears the unilower matrix and returns it to its default state. The function has
+// the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
+// matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
+// to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
+// be reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniLowerMatrix<MT,SO,true>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the unilower matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the unilower matrix adapts a resizable matrix, this function resizes the matrix using
+// the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
+// in case the capacity of the matrix is too small. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, the resize operation potentially changes all matrix elements. In order
+// to preserve the old matrix values, the \a preserve flag can be set to \a true. Also note that
+// in case the size of the matrix is increased, only the new elements on the diagonal and in the
+// upper part of the matrix are initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 0 & 0 \\
+ 2 & 1 & 0 \\
+ 3 & 4 & 1 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 0 & 0 & 0 \\
+ 2 & 1 & 0 & 0 \\
+ 3 & 4 & 1 & 0 \\
+ x & x & x & 1 \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void UniLowerMatrix<MT,SO,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize )
+ {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, 0UL, oldsize, n-1UL, increment ).reset();
+
+ for( size_t i=oldsize; i<n; ++i )
+ matrix_(i,i) = ElementType(1);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniLowerMatrix<MT,SO,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the unilower matrix.
+// \return void
+//
+// This function increases the capacity of the unilower matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniLowerMatrix<MT,SO,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniLowerMatrix<MT,SO,true>::swap( UniLowerMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a lower unitriangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a lower unitriangular
+// matrix with fixed-size adapted matrix of type \a MT. Note that this function can only be
+// called in case the adapted dense matrix is a fixed-size matrix (as for instance StaticMatrix).
+// The attempt to call this function in case the adapted matrix is resizable matrix will result
+// in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UniLowerMatrix<MT,SO,true>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a lower unitriangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a lower unitriangular
+// matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UniLowerMatrix<MT,SO,true>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n + 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the unilower matrix are intact.
+//
+// \return \a true in case the unilower matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the unilower matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UniLowerMatrix<MT,SO,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isUniLower( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UniLowerMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UniLowerMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UniLowerMatrix<MT,SO,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UniLowerMatrix<MT,SO,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the unilower matrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the column index (in case of a row-major matrix) or
+// the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UniLowerMatrix<MT,SO,true>::SIMDType
+ UniLowerMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the unilower matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UniLowerMatrix<MT,SO,true>::SIMDType
+ UniLowerMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the unilower matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UniLowerMatrix<MT,SO,true>::SIMDType
+ UniLowerMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a resizable matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT UniLowerMatrix<MT,SO,true>::construct( size_t n, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ MT tmp( n, n, ElementType() );
+
+ for( size_t i=0UL; i<n; ++i )
+ tmp(i,i) = ElementType(1);
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a fixed-size matrix with homogeneously initialized lower elements.
+//
+// \param init The initial value of the lower matrix elements.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT UniLowerMatrix<MT,SO,true>::construct( const ElementType& init, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SQUARE( MT );
+
+ MT tmp;
+
+ if( SO ) {
+ for( size_t j=0UL; j<tmp.columns(); ++j ) {
+ tmp(j,j) = ElementType(1);
+ for( size_t i=j+1UL; i<tmp.rows(); ++i )
+ tmp(i,j) = init;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<tmp.rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j )
+ tmp(i,j) = init;
+ tmp(i,i) = ElementType(1);
+ }
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a matrix as a copy from another matrix.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of unilower matrix.
+// \return The newly constructed matrix.
+//
+// In case the given matrix is not an unilower matrix, a \a std::invalid_argument exception is
+// thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT UniLowerMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ const MT tmp( ~m );
+
+ if( IsStrictlyTriangular<MT2>::value || ( !IsUniLower<MT2>::value && !isUniLower( tmp ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/unilowermatrix/Sparse.h b/src/cpu/blaze/math/adaptors/unilowermatrix/Sparse.h
new file mode 100644
index 00000000..dfbee4ee
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/unilowermatrix/Sparse.h
@@ -0,0 +1,2211 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/unilowermatrix/Sparse.h
+// \brief UniLowerMatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_SPARSE_H_
+#define _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/unilowermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/unilowermatrix/UniLowerElement.h>
+#include <blaze/math/adaptors/unilowermatrix/UniLowerProxy.h>
+#include <blaze/math/adaptors/unilowermatrix/UniLowerValue.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of UniLowerMatrix for sparse matrices.
+// \ingroup unilower_matrix
+//
+// This specialization of UniLowerMatrix adapts the class template to the requirements of sparse
+// matrices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class UniLowerMatrix<MT,SO,false>
+ : public SparseMatrix< UniLowerMatrix<MT,SO,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef UniLowerMatrix<MT,SO,false> This; //!< Type of this UniLowerMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this UniLowerMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef UniLowerMatrix<OT,!SO,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef UniUpperMatrix<TT,!SO,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef UniLowerProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a UniLowerMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other UniLowerMatrix.
+ typedef UniLowerMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the elements of the lower unitriangular matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef Iterator_<MT> IteratorType; //!< Type of the underlying sparse matrix iterators.
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef UniLowerElement<MT> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Default constructor**********************************************************************
+ /*!\brief Default constructor for the Iterator class.
+ */
+ inline Iterator()
+ : pos_ ( ) // Iterator to the current lower unitriangular matrix element
+ , index_ ( 0UL ) // The row/column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param pos The initial position of the iterator.
+ // \param index The row/column index of the iterator.
+ */
+ inline Iterator( IteratorType pos, size_t index )
+ : pos_ ( pos ) // Iterator to the current lower unitriangular matrix element
+ , index_( index ) // The row/column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() {
+ ++pos_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Reference to the current sparse matrix element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, pos_->index() == index_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Pointer to the current sparse matrix element.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, pos_->index() == index_ );
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const Iterator& rhs ) const {
+ return pos_ == rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const Iterator& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two matrix iterators.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return The number of elements between the two matrix iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const {
+ return pos_ - rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the matrix iterator.
+ //
+ // \return The current position of the matrix iterator.
+ */
+ inline IteratorType base() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current lower unitriangular matrix element.
+ size_t index_; //!< The row/column index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UniLowerMatrix();
+ explicit inline UniLowerMatrix( size_t n );
+ explicit inline UniLowerMatrix( size_t n, size_t nonzeros );
+ explicit inline UniLowerMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline UniLowerMatrix( const UniLowerMatrix& m );
+ inline UniLowerMatrix( UniLowerMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline UniLowerMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline UniLowerMatrix& operator=( const UniLowerMatrix& rhs );
+ inline UniLowerMatrix& operator=( UniLowerMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniLowerMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniLowerMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniLowerMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniLowerMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniLowerMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniLowerMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline UniLowerMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ inline void swap( UniLowerMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void resetUpper();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( UniLowerMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for UniLowerMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniLowerMatrix<MT,SO,false>::UniLowerMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized as identity matrix and has no additional free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniLowerMatrix<MT,SO,false>::UniLowerMatrix( size_t n )
+ : matrix_( n, n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix_.append( i, i, ElementType(1) );
+ matrix_.finalize( i );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized as identity matrix and will have at least the capacity for
+// \a nonzeros non-zero elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniLowerMatrix<MT,SO,false>::UniLowerMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, max( nonzeros, n ) ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix_.append( i, i, ElementType(1) );
+ matrix_.finalize( i );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+// \exception std::invalid_argument Invalid capacity specification.
+//
+// The matrix is initialized as identity matrix and will have the specified capacity in each
+// row/column. Note that since the matrix is initialized as \f$ n \times n \f$ identity matrix
+// the given vector must have at least \a n elements, all of which must not be 0. If the number
+// of non-zero elements of any row/column is specified as 0, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniLowerMatrix<MT,SO,false>::UniLowerMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ for( size_t i=0UL; i<n; ++i )
+ {
+ if( nonzeros[i] == 0UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid capacity specification" );
+ }
+
+ matrix_.append( i, i, ElementType(1) );
+ matrix_.finalize( i );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for UniLowerMatrix.
+//
+// \param m The unilower matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniLowerMatrix<MT,SO,false>::UniLowerMatrix( const UniLowerMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for UniLowerMatrix.
+//
+// \param m The unilower matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniLowerMatrix<MT,SO,false>::UniLowerMatrix( UniLowerMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of unilower matrix.
+//
+// This constructor initializes the unilower matrix as a copy of the given matrix. In case the
+// given matrix is not an unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline UniLowerMatrix<MT,SO,false>::UniLowerMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( ~m ) // The adapted sparse matrix
+{
+ if( !IsUniLower<MT2>::value && !isUniLower( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" );
+ }
+
+ if( !IsUniLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Reference
+ UniLowerMatrix<MT,SO,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstReference
+ UniLowerMatrix<MT,SO,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Reference
+ UniLowerMatrix<MT,SO,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the upper part of the matrix (i.e. above the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstReference
+ UniLowerMatrix<MT,SO,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the unilower matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::begin( size_t i )
+{
+ return Iterator( matrix_.begin(i), i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the unilower matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstIterator
+ UniLowerMatrix<MT,SO,false>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the unilower matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstIterator
+ UniLowerMatrix<MT,SO,false>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the unilower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::end( size_t i )
+{
+ return Iterator( matrix_.end(i), i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the unilower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstIterator
+ UniLowerMatrix<MT,SO,false>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the unilower matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstIterator
+ UniLowerMatrix<MT,SO,false>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for UniLowerMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniLowerMatrix<MT,SO,false>&
+ UniLowerMatrix<MT,SO,false>::operator=( const UniLowerMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for UniLowerMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniLowerMatrix<MT,SO,false>&
+ UniLowerMatrix<MT,SO,false>::operator=( UniLowerMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// unilower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,false>& >
+ UniLowerMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsStrictlyTriangular<MT2>::value || ( !IsUniLower<MT2>::value && !isUniLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ if( !IsUniLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
+// unilower matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,false>& >
+ UniLowerMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsStrictlyTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ if( IsUniLower<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isUniLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ if( !IsUniLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an unilower
+// matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is not an
+// unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,false>& >
+ UniLowerMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUpper<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an unilower
+// matrix, i.e. the given matrix must be a strictly lower matrix. In case the result is not an
+// unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,false>& >
+ UniLowerMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUpper<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// unilower matrix, i.e. the given matrix must be a strictly lower matrix. In case the
+// result is not an unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,false>& >
+ UniLowerMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUpper<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyLower<MT2>::value && !isStrictlyLower( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to unilower matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// unilower matrix, i.e. the given matrix must be a strictly lower matrix. In case the
+// result is not an unilower matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniLowerMatrix<MT,SO,false>& >
+ UniLowerMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsUpper<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ if( IsStrictlyLower<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ if( !IsStrictlyLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be an unilower matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline UniLowerMatrix<MT,SO,false>&
+ UniLowerMatrix<MT,SO,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isUniLower( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ if( !IsUniLower<MT2>::value )
+ resetUpper();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniLowerMatrix<MT,SO,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniLowerMatrix<MT,SO,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniLowerMatrix<MT,SO,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the unilower
+// matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniLowerMatrix<MT,SO,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the unilower matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniLowerMatrix<MT,SO,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the unilower matrix adapts a \a rowMajor sparse matrix the function returns the
+// number of non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse
+// matrix the function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniLowerMatrix<MT,SO,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::reset()
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ matrix_.erase( j, matrix_.lowerBound(j+1UL,j), matrix_.end(j) );
+ }
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i ) {
+ matrix_.erase( i, matrix_.begin(i), matrix_.lowerBound(i,i) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::reset( size_t i )
+{
+ if( SO ) {
+ matrix_.erase( i, matrix_.lowerBound(i+1UL,i), matrix_.end(i) );
+ }
+ else {
+ matrix_.erase( i, matrix_.begin(i), matrix_.lowerBound(i,i) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the unilower matrix.
+//
+// \return void
+//
+// This function clears the unilower matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the unilower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to diagonal or upper matrix element.
+//
+// This function sets the value of an element of the unilower matrix. In case the unilower matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted. The attempt to set an element on the
+// diagonal or in the upper part of the matrix (i.e. above the diagonal) will result in a
+// \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ if( i <= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or upper matrix element" );
+ }
+
+ return Iterator( matrix_.set( i, j, value ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the unilower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+// \exception std::invalid_argument Invalid access to diagonal or upper matrix element.
+//
+// This function inserts a new element into the unilower matrix. However, duplicate elements are
+// not allowed. In case the unilower matrix already contains an element with row index \a i and
+// column index \a j, a \a std::invalid_argument exception is thrown. Also, the attempt to insert
+// an element on the diagonal or in the upper part of the matrix (i.e. above the diagonal) will
+// result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ if( i <= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or upper matrix element" );
+ }
+
+ return Iterator( matrix_.insert( i, j, value ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the unilower matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function erases a non-diagonal element from the unilower matrix. The attempt to erase a
+// diagonal element will result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::erase( size_t i, size_t j )
+{
+ if( i == j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+
+ matrix_.erase( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the unilower matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function erases a non-diagonal element from the unilower matrix. In case the unilower
+// matrix adapts a \a rowMajor sparse matrix the function erases an element from row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function erases an element from column \a i.
+// The attempt to erase a diagonal element will result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::erase( size_t i, Iterator pos )
+{
+ if( pos != matrix_.end(i) && pos->index() == i ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+
+ return Iterator( matrix_.erase( i, pos.base() ), i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the unilower matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function erases a range of elements from the unilower matrix. In case the unilower matrix
+// adapts a \a rowMajor sparse matrix the function erases a range of elements from row \a i, in
+// case it adapts a \a columnMajor matrix the function erases a range of elements from column \a i.
+// The attempt to erase a diagonal element will result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ for( Iterator element=first; element!=last; ++element ) {
+ if( element->index() == i ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+ }
+
+ return Iterator( matrix_.erase( i, first.base(), last.base() ), i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the unilower matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void UniLowerMatrix<MT,SO,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square unilower matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, preserve );
+
+ if( n > oldsize ) {
+ for( size_t i=oldsize; i<n; ++i )
+ matrix_.insert( i, i, ElementType(1) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the unilower matrix.
+//
+// \param nonzeros The new minimum capacity of the unilower matrix.
+// \return void
+//
+// This function increases the capacity of the unilower matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the unilower matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the unilower matrix to at least
+// \a nonzeros elements. The current values of the unilower matrix and all other individual
+// row/column capacities are preserved. In case the unilower matrix adapts a \a rowMajor sparse
+// matrix the function reserves capacity for row \a i. In case it adapts a \a columnMajor the
+// function reserves capacity for column \a i. The index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the unilower matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::swap( UniLowerMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a lower unitriangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a lower unitriangular
+// matrix with fixed-size adapted matrix of type \a MT. Note that this function can only be
+// called in case the adapted dense matrix is a fixed-size matrix. The attempt to call this
+// function in case the adapted matrix is resizable matrix will result in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UniLowerMatrix<MT,SO,false>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for a lower unitriangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for a lower unitriangular
+// matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UniLowerMatrix<MT,SO,false>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n + 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the complete upper part of the matrix to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniLowerMatrix<MT,SO,false>::resetUpper()
+{
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j )
+ matrix_.erase( j, matrix_.begin( j ), matrix_.lowerBound( j, j ) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ matrix_.erase( i, matrix_.upperBound( i, i ), matrix_.end( i ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the unilower
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned unilower matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::find( size_t i, size_t j )
+{
+ return Iterator( matrix_.find( i, j ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the unilower
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned unilower matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstIterator
+ UniLowerMatrix<MT,SO,false>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned unilower matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::lowerBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.lowerBound( i, j ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned unilower matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstIterator
+ UniLowerMatrix<MT,SO,false>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned unilower matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::Iterator
+ UniLowerMatrix<MT,SO,false>::upperBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.upperBound( i, j ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned unilower matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniLowerMatrix<MT,SO,false>::ConstIterator
+ UniLowerMatrix<MT,SO,false>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the unilower matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to diagonal or upper matrix element.
+//
+// This function provides a very efficient way to fill a unilower sparse matrix with elements.
+// It appends a new element to the end of the specified row/column without any additional memory
+// allocation. Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (newly created) sparse matrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::UniLowerMatrix;
+ using blaze::columnMajor;
+
+ UniLowerMatrix< CompressedMatrix<double,columnMajor> > A( 4 );
+
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 1, 0, 1.0 ); // Appending the value 1 in column 0 with row index 1
+ A.finalize( 0 ); // Finalizing column 0
+ A.append( 2, 1, 2.0 ); // Appending the value 2 in column 1 with row index 2
+ A.finalize( 1 ); // Finalizing column 1
+ A.append( 3, 2, 3.0 ); // Appending the value 3 in column 2 with row index 3
+ A.finalize( 2 ); // Finalizing column 2
+ A.finalize( 3 ); // Finalizing the final column 3
+ \endcode
+
+// Note that although append() does not allocate new memory it still invalidates all iterators
+// returned by the end() functions! Also note that the attempt to append an element within the
+// upper part of the matrix (i.e. above the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( i <= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or upper matrix element" );
+ }
+
+ if( !check || !isDefault( value ) )
+ matrix_.insert( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniLowerMatrix<MT,SO,false>::finalize( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the unilower matrix are intact.
+//
+// \return \a true in case the unilower matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the unilower matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool UniLowerMatrix<MT,SO,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isUniLower( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UniLowerMatrix<MT,SO,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UniLowerMatrix<MT,SO,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool UniLowerMatrix<MT,SO,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerElement.h b/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerElement.h
new file mode 100644
index 00000000..01297ed9
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerElement.h
@@ -0,0 +1,367 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/unilowermatrix/UniLowerElement.h
+// \brief Header file for the UniLowerElement class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_UNILOWERELEMENT_H_
+#define _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_UNILOWERELEMENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/unilowermatrix/UniLowerValue.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Representation of an element within a sparse lower unitriangular matrix.
+// \ingroup unilower_matrix
+//
+// The UniLowerElement class represents an element (i.e. value/index pair) within a sparse lower
+// unitriangular matrix. It guarantees that the unilower matrix invariant is not violated, i.e.
+// that elements in the upper part of the matrix remain 0 and the diagonal elements remain 1. The
+// following example illustrates this by means of a \f$ 3 \times 3 \f$ sparse lower unitriangular
+// matrix:
+
+ \code
+ typedef blaze::UniLowerMatrix< blaze::CompressedMatrix<int> > UniLower;
+
+ // Creating a 3x3 lower unitriangular sparse matrix
+ UniLower A( 3UL );
+
+ A(1,0) = -2; // ( 1 0 0 )
+ A(2,0) = 3; // => A = ( -2 1 0 )
+ A(2,1) = 5; // ( 3 5 1 )
+
+ UniLower::Iterator it = A.begin( 1UL );
+ *it = 4; // Modification of matrix element (1,0)
+ ++it;
+ *it = 9; // Invalid assignment to diagonal matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class UniLowerElement : private SparseElement
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> ElementType; //!< Type of the represented matrix element.
+ typedef Iterator_<MT> IteratorType; //!< Type of the underlying sparse matrix iterators.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef UniLowerValue<MT> ValueType; //!< The value type of the value-index-pair.
+ typedef size_t IndexType; //!< The index type of the value-index-pair.
+ typedef UniLowerValue<MT> Reference; //!< Reference return type.
+ typedef const UniLowerValue<MT> ConstReference; //!< Reference-to-const return type.
+ typedef UniLowerElement* Pointer; //!< Pointer return type.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline UniLowerElement( IteratorType pos, bool diagonal );
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ template< typename T > inline UniLowerElement& operator= ( const T& v );
+ template< typename T > inline UniLowerElement& operator+=( const T& v );
+ template< typename T > inline UniLowerElement& operator-=( const T& v );
+ template< typename T > inline UniLowerElement& operator*=( const T& v );
+ template< typename T > inline UniLowerElement& operator/=( const T& v );
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline Pointer operator->() noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline Reference value() const;
+ inline IndexType index() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ IteratorType pos_; //!< Iterator to the current lower unitriangular matrix element.
+ bool diagonal_; //!< \a true in case the element is on the diagonal, \a false if not.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( ElementType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the UniLowerElement class.
+//
+// \param pos Iterator to the current position with the sparse lower unitriangular matrix.
+// \param diagonal \a true in case the element is on the diagonal, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniLowerElement<MT>::UniLowerElement( IteratorType pos, bool diagonal )
+ : pos_ ( pos ) // Iterator to the current lower unitriangular matrix element
+ , diagonal_( diagonal ) // true in case the element is on the diagonal, false if not
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Assignment to the unilower element.
+//
+// \param v The new value of the unilower element.
+// \return Reference to the assigned unilower element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerElement<MT>& UniLowerElement<MT>::operator=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ = v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the unilower element.
+//
+// \param v The right-hand side value for the addition.
+// \return Reference to the assigned unilower element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerElement<MT>& UniLowerElement<MT>::operator+=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ += v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the unilower element.
+//
+// \param v The right-hand side value for the subtraction.
+// \return Reference to the assigned unilower element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerElement<MT>& UniLowerElement<MT>::operator-=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ -= v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the unilower element.
+//
+// \param v The right-hand side value for the multiplication.
+// \return Reference to the assigned unilower element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerElement<MT>& UniLowerElement<MT>::operator*=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ *= v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the unilower element.
+//
+// \param v The right-hand side value for the division.
+// \return Reference to the assigned unilower element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerElement<MT>& UniLowerElement<MT>::operator/=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ /= v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the unilower element.
+//
+// \return Reference to the value of the unilower element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerElement<MT>::Pointer UniLowerElement<MT>::operator->() noexcept
+{
+ return this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access to the current value of the unilower element.
+//
+// \return The current value of the unilower element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerElement<MT>::Reference UniLowerElement<MT>::value() const
+{
+ return Reference( pos_->value(), diagonal_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the current index of the unilower element.
+//
+// \return The current index of the unilower element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerElement<MT>::IndexType UniLowerElement<MT>::index() const
+{
+ return pos_->index();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerProxy.h b/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerProxy.h
new file mode 100644
index 00000000..ffc0f129
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerProxy.h
@@ -0,0 +1,809 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/unilowermatrix/UniLowerProxy.h
+// \brief Header file for the UniLowerProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_LOWERMATRIX_UNILOWERPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_LOWERMATRIX_UNILOWERPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for lower unitriangular matrices.
+// \ingroup unilower_matrix
+//
+// The UniLowerProxy provides controlled access to the elements of a non-const lower unitriangular
+// matrix. It guarantees that the unilower matrix invariant is not violated, i.e. that elements
+// in the upper part of the matrix remain 0 and the diagonal elements remain 1. The following
+// example illustrates this by means of a \f$ 3 \times 3 \f$ dense lower unitriangular matrix:
+
+ \code
+ // Creating a 3x3 lower unitriangular dense matrix
+ blaze::UniLowerMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(1,0) = -2; // ( 1 0 0 )
+ A(2,0) = 3; // => A = ( -2 1 0 )
+ A(2,1) = 5; // ( 3 5 1 )
+
+ A(1,1) = 4; // Invalid assignment to diagonal matrix element; results in an exception!
+ A(0,2) = 7; // Invalid assignment to upper matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class UniLowerProxy : public Proxy< UniLowerProxy<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Reference type of the underlying matrix type.
+ typedef typename MT::Reference ReferenceType;
+ //**********************************************************************************************
+
+ //**struct BuiltinType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct BuiltinType { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct ComplexType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct ComplexType { typedef typename T::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of the represented matrix element.
+ typedef ElementType_<MT> RepresentedType;
+
+ //! Value type of the represented complex element.
+ typedef typename If_< IsComplex<RepresentedType>
+ , ComplexType<RepresentedType>
+ , BuiltinType<RepresentedType> >::Type ValueType;
+
+ typedef ValueType value_type; //!< Value type of the represented complex element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UniLowerProxy( MT& matrix, size_t row, size_t column );
+ inline UniLowerProxy( const UniLowerProxy& ulp );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline const UniLowerProxy& operator= ( const UniLowerProxy& ulp ) const;
+ template< typename T > inline const UniLowerProxy& operator= ( const T& value ) const;
+ template< typename T > inline const UniLowerProxy& operator+=( const T& value ) const;
+ template< typename T > inline const UniLowerProxy& operator-=( const T& value ) const;
+ template< typename T > inline const UniLowerProxy& operator*=( const T& value ) const;
+ template< typename T > inline const UniLowerProxy& operator/=( const T& value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void reset () const;
+ inline void clear () const;
+ inline void invert() const;
+
+ inline RepresentedType get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RepresentedType() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Complex data access functions***************************************************************
+ /*!\name Complex data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ ReferenceType value_; //!< Reference to the accessed matrix element.
+ size_t row_; //!< Row index of the accessed matrix element.
+ size_t column_; //!< Column index of the accessed matrix element.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for an UniLowerProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniLowerProxy<MT>::UniLowerProxy( MT& matrix, size_t row, size_t column )
+ : value_ ( matrix( row, column ) ) // Reference to the accessed matrix element
+ , row_ ( row ) // Row index of the accessed matrix element
+ , column_( column ) // Column index of the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for LowerProxy.
+//
+// \param ulp Proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniLowerProxy<MT>::UniLowerProxy( const UniLowerProxy& ulp )
+ : value_ ( ulp.value_ ) // Reference to the accessed matrix element
+ , row_ ( ulp.row_ ) // Row index of the accessed matrix element
+ , column_( ulp.column_ ) // Column index of the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for UniLowerProxy.
+//
+// \param ulp Proxy to be copied.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline const UniLowerProxy<MT>& UniLowerProxy<MT>::operator=( const UniLowerProxy& ulp ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ = ulp.value_;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniLowerProxy<MT>& UniLowerProxy<MT>::operator=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniLowerProxy<MT>& UniLowerProxy<MT>::operator+=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniLowerProxy<MT>& UniLowerProxy<MT>::operator-=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniLowerProxy<MT>& UniLowerProxy<MT>::operator*=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or upper matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the upper part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniLowerProxy<MT>& UniLowerProxy<MT>::operator/=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or upper matrix element" );
+ }
+
+ value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reset the represented element to its default initial value.
+//
+// \return void
+//
+// This function resets the element represented by the proxy to its default initial value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerProxy<MT>::reset() const
+{
+ using blaze::reset;
+
+ if( column_ < row_ )
+ reset( value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+//
+// \return void
+//
+// This function clears the element represented by the proxy to its default initial state.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerProxy<MT>::clear() const
+{
+ using blaze::clear;
+
+ if( column_ < row_ )
+ clear( value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element
+//
+// \return void
+// \exception std::invalid_argument Invalid inversion of upper matrix element.
+//
+// In case the proxy represents an upper element, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerProxy<MT>::invert() const
+{
+ using blaze::invert;
+
+ if( row_ < column_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid inversion of upper matrix element" );
+ }
+
+ if( column_ < row_ )
+ invert( value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerProxy<MT>::RepresentedType UniLowerProxy<MT>::get() const noexcept
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted matrix element..
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool UniLowerProxy<MT>::isRestricted() const noexcept
+{
+ return row_ <= column_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniLowerProxy<MT>::operator RepresentedType() const noexcept
+{
+ return get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerProxy<MT>::ValueType UniLowerProxy<MT>::real() const
+{
+ return value_.real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal or upper matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its real part.
+// In case the represented value is a diagonal element or an element in the upper part of the
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerProxy<MT>::real( ValueType value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal or upper matrix element" );
+ }
+
+ value_.real( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerProxy<MT>::ValueType UniLowerProxy<MT>::imag() const
+{
+ return value_.imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal or upper matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its imaginary
+// part. In case the represented value is a diagonal element or an element in the upper part of
+// the matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerProxy<MT>::imag( ValueType value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal or upper matrix element" );
+ }
+
+ value_.imag( value );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UniLowerProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const UniLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const UniLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline void invert( const UniLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const UniLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const UniLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const UniLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const UniLowerProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const UniLowerProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup unilower_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const UniLowerProxy<MT>& proxy )
+{
+ proxy.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup unilower_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const UniLowerProxy<MT>& proxy )
+{
+ proxy.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element.
+// \ingroup unilower_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+*/
+template< typename MT >
+inline void invert( const UniLowerProxy<MT>& proxy )
+{
+ proxy.invert();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup unilower_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const UniLowerProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup unilower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const UniLowerProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup unilower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const UniLowerProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup unilower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const UniLowerProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup unilower_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const UniLowerProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerValue.h b/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerValue.h
new file mode 100644
index 00000000..d87b106b
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerValue.h
@@ -0,0 +1,753 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/unilowermatrix/UniLowerValue.h
+// \brief Header file for the UniLowerValue class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_UNILOWERVALUE_H_
+#define _BLAZE_MATH_ADAPTORS_UNILOWERMATRIX_UNILOWERVALUE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Representation of a value within a sparse lower unitriangular matrix.
+// \ingroup unilower_matrix
+//
+// The UniLowerValue class represents a single value within a sparse lower unitriangular matrix.
+// It guarantees that the unilower matrix invariant is not violated, i.e. that elements in the
+// upper part of the matrix remain 0 and the diagonal elements remain 1. The following example
+// illustrates this by means of a \f$ 3 \times 3 \f$ sparse lower unitriangular matrix:
+
+ \code
+ typedef blaze::UniLowerMatrix< blaze::CompressedMatrix<int> > UniLower;
+
+ // Creating a 3x3 lower unitriangular sparse matrix
+ UniLower A( 3UL );
+
+ A(1,0) = -2; // ( 1 0 0 )
+ A(2,0) = 3; // => A = ( -2 1 0 )
+ A(2,1) = 5; // ( 3 5 1 )
+
+ UniLower::Iterator it = A.begin( 1UL );
+ it->value() = 4; // Modification of matrix element (1,0)
+ ++it;
+ it->value() = 9; // Invalid assignment to diagonal matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class UniLowerValue : public Proxy< UniLowerValue<MT> >
+{
+ private:
+ //**struct BuiltinType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct BuiltinType { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct ComplexType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct ComplexType { typedef typename T::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+
+ //! Value type of the represented complex element.
+ typedef typename If_< IsComplex<RepresentedType>
+ , ComplexType<RepresentedType>
+ , BuiltinType<RepresentedType> >::Type ValueType;
+
+ typedef ValueType value_type; //!< Value type of the represented complex element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline UniLowerValue( RepresentedType& value, bool diagonal );
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline UniLowerValue& operator= ( const UniLowerValue& ulv );
+ template< typename T > inline UniLowerValue& operator= ( const T& value );
+ template< typename T > inline UniLowerValue& operator+=( const T& value );
+ template< typename T > inline UniLowerValue& operator-=( const T& value );
+ template< typename T > inline UniLowerValue& operator*=( const T& value );
+ template< typename T > inline UniLowerValue& operator/=( const T& value );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void reset () const;
+ inline void clear () const;
+ inline void invert() const;
+
+ inline RepresentedType get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RepresentedType() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Complex data access functions***************************************************************
+ /*!\name Complex data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ RepresentedType* value_; //!< The represented value.
+ bool diagonal_; //!< \a true in case the element is on the diagonal, \a false if not.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the UniLowerValue class.
+//
+// \param value Reference to the represented value.
+// \param diagonal \a true in case the element is on the diagonal, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniLowerValue<MT>::UniLowerValue( RepresentedType& value, bool diagonal )
+ : value_ ( &value ) // The represented value.
+ , diagonal_( diagonal ) // true in case the element is on the diagonal, false if not
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for UniLowerValue.
+//
+// \param ulv The unilower value to be copied.
+// \return Reference to the assigned unilower value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniLowerValue<MT>& UniLowerValue<MT>::operator=( const UniLowerValue& ulv )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ = *ulv.value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the unilower value.
+//
+// \param value The new value of the unilower value.
+// \return Reference to the assigned unilower value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerValue<MT>& UniLowerValue<MT>::operator=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the unilower value.
+//
+// \param value The right-hand side value to be added to the unilower value.
+// \return Reference to the assigned unilower value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerValue<MT>& UniLowerValue<MT>::operator+=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the unilower value.
+//
+// \param value The right-hand side value to be subtracted from the unilower value.
+// \return Reference to the assigned unilower value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerValue<MT>& UniLowerValue<MT>::operator-=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the unilower value.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned unilower value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerValue<MT>& UniLowerValue<MT>::operator*=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the unilower value.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned unilower value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniLowerValue<MT>& UniLowerValue<MT>::operator/=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reset the unilower value to its default initial value.
+//
+// \return void
+//
+// This function resets the unilower value to its default initial value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerValue<MT>::reset() const
+{
+ using blaze::reset;
+
+ if( !diagonal_ )
+ reset( *value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the unilower value.
+//
+// \return void
+//
+// This function clears the unilower value to its default initial state.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerValue<MT>::clear() const
+{
+ using blaze::clear;
+
+ if( !diagonal_ )
+ clear( *value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the unilower value
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerValue<MT>::invert() const
+{
+ using blaze::invert;
+
+ if( !diagonal_ )
+ invert( *value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the represented value.
+//
+// \return Copy of the represented value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerValue<MT>::RepresentedType UniLowerValue<MT>::get() const noexcept
+{
+ return *value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the value represents a restricted matrix element..
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool UniLowerValue<MT>::isRestricted() const noexcept
+{
+ return diagonal_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the represented value.
+//
+// \return Copy of the represented value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniLowerValue<MT>::operator RepresentedType() const noexcept
+{
+ return *value_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerValue<MT>::ValueType UniLowerValue<MT>::real() const
+{
+ return value_->real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerValue<MT>::real( ValueType value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal matrix element" );
+ }
+
+ value_->real( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniLowerValue<MT>::ValueType UniLowerValue<MT>::imag() const
+{
+ return value_->imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its imaginary
+// part. In case the proxy represents a diagonal element and the given value is not zero, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniLowerValue<MT>::imag( ValueType value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal matrix element" );
+ }
+
+ value_->imag( value );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UniLowerValue global functions */
+//@{
+template< typename MT >
+inline void reset( const UniLowerValue<MT>& value );
+
+template< typename MT >
+inline void clear( const UniLowerValue<MT>& value );
+
+template< typename MT >
+inline void invert( const UniLowerValue<MT>& value );
+
+template< typename MT >
+inline bool isDefault( const UniLowerValue<MT>& value );
+
+template< typename MT >
+inline bool isReal( const UniLowerValue<MT>& value );
+
+template< typename MT >
+inline bool isZero( const UniLowerValue<MT>& value );
+
+template< typename MT >
+inline bool isOne( const UniLowerValue<MT>& value );
+
+template< typename MT >
+inline bool isnan( const UniLowerValue<MT>& value );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the unilower value to the default initial values.
+// \ingroup unilower_matrix
+//
+// \param value The given unilower value.
+// \return void
+//
+// This function resets the unilower value to its default initial value.
+*/
+template< typename MT >
+inline void reset( const UniLowerValue<MT>& value )
+{
+ value.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the unilower value.
+// \ingroup unilower_matrix
+//
+// \param value The given unilower value.
+// \return void
+//
+// This function clears the unilower value to its default initial state.
+*/
+template< typename MT >
+inline void clear( const UniLowerValue<MT>& value )
+{
+ value.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the unilower value.
+// \ingroup unilower_matrix
+//
+// \param value The given unilower value.
+// \return void
+*/
+template< typename MT >
+inline void invert( const UniLowerValue<MT>& value )
+{
+ value.invert();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the unilower value is in default state.
+// \ingroup unilower_matrix
+//
+// \param value The given unilower value.
+// \return \a true in case the unilower value is in default state, \a false otherwise.
+//
+// This function checks whether the unilower value is in default state. In case it is in
+// default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const UniLowerValue<MT>& value )
+{
+ using blaze::isDefault;
+
+ return isDefault( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the unilower value represents a real number.
+// \ingroup unilower_matrix
+//
+// \param value The given unilower value.
+// \return \a true in case the unilower value represents a real number, \a false otherwise.
+//
+// This function checks whether the unilower value represents the a real number. In case the
+// value is of built-in type, the function returns \a true. In case the element is of complex
+// type, the function returns \a true if the imaginary part is equal to 0. Otherwise it returns
+// \a false.
+*/
+template< typename MT >
+inline bool isReal( const UniLowerValue<MT>& value )
+{
+ using blaze::isReal;
+
+ return isReal( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the unilower value is 0.
+// \ingroup unilower_matrix
+//
+// \param value The given unilower value.
+// \return \a true in case the unilower value is 0, \a false otherwise.
+//
+// This function checks whether the unilower value represents the numeric value 0. In case it
+// is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const UniLowerValue<MT>& value )
+{
+ using blaze::isZero;
+
+ return isZero( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the unilower value is 1.
+// \ingroup unilower_matrix
+//
+// \param value The given unilower value.
+// \return \a true in case the unilower value is 1, \a false otherwise.
+//
+// This function checks whether the unilower value represents the numeric value 1. In case it
+// is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const UniLowerValue<MT>& value )
+{
+ using blaze::isOne;
+
+ return isOne( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the unilower value is not a number.
+// \ingroup unilower_matrix
+//
+// \param value The given unilower value.
+// \return \a true in case the unilower value is in not a number, \a false otherwise.
+//
+// This function checks whether the unilower value is not a number (NaN). In case it is not a
+// number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const UniLowerValue<MT>& value )
+{
+ using blaze::isnan;
+
+ return isnan( value.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uniuppermatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/uniuppermatrix/BaseTemplate.h
new file mode 100644
index 00000000..bf55e216
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uniuppermatrix/BaseTemplate.h
@@ -0,0 +1,578 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uniuppermatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the UniUpperMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup uniupper_matrix UniUpperMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for upper unitriangular \f$ N \times N \f$ matrices.
+// \ingroup uniupper_matrix
+//
+// \section uniuppermatrix_general General
+//
+// The UniUpperMatrix class template is an adapter for existing dense and sparse matrix types.
+// It inherits the properties and the interface of the given matrix type \a MT and extends it
+// by enforcing the additional invariant that all diagonal matrix elements are 1 and all matrix
+// elements below the diagonal are 0 (upper unitriangular matrix). The type of the adapted matrix
+// can be specified via the first template parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF >
+ class UniUpperMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. UniUpperMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Also, the given matrix type must have numeric element types (i.e. all integral
+// types except \a bool, floating point and complex types). Note that the given matrix
+// type must be either resizable (as for instance HybridMatrix or DynamicMatrix) or
+// must be square at compile time (as for instance StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+// The following examples give an impression of several possible upper unitriangular matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense uniupper matrix with static memory
+ blaze::UniUpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense uniupper matrix based on HybridMatrix
+ blaze::UniUpperMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense uniupper matrix based on DynamicMatrix
+ blaze::UniUpperMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense uniupper matrix based on CustomMatrix
+ blaze::UniUpperMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision uniupper matrix
+ blaze::UniUpperMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of an upper unitriangular matrix is depending on the storage order of the
+// adapted matrix type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e.
+// is specified as blaze::rowMajor), the uniupper matrix will also be a row-major matrix.
+// Otherwise, if the adapted matrix is column-major (i.e. is specified as blaze::columnMajor),
+// the uniupper matrix will also be a column-major matrix.
+//
+//
+// \n \section uniuppermatrix_special_properties Special Properties of Upper Unitriangular Matrices
+//
+// An upper unitriangular matrix is used exactly like a matrix of the underlying, adapted matrix
+// type \a MT. It also provides (nearly) the same interface as the underlying matrix type. However,
+// there are some important exceptions resulting from the upper unitriangular matrix constraint:
+//
+// -# <b>\ref uniuppermatrix_square</b>
+// -# <b>\ref uniuppermatrix_uniupper</b>
+// -# <b>\ref uniuppermatrix_initialization</b>
+// -# <b>\ref uniuppermatrix_storage</b>
+// -# <b>\ref uniuppermatrix_scaling</b>
+//
+// \n \subsection uniuppermatrix_square Upper Unitriangular Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 uniupper dynamic matrix
+ UniUpperMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::UniUpperMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 uniupper static matrix
+ UniUpperMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ UniUpperMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection uniuppermatrix_uniupper The Upper Unitriangular Matrix Property is Always Enforced!
+//
+// The diagonal elements of an upper unitriangular matrix are fixed to 1. This property has two
+// implications. First, that means that the diagonal elements of a newly created uniupper matrix
+// are pre-initialized to 1:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+ using blaze::rowMajor;
+
+ // Creating a default initialized dense uniupper matrix of size 3x3
+ //
+ // ( 1 0 0 )
+ // A = ( 0 1 0 )
+ // ( 0 0 1 )
+ UniUpperMatrix< DynamicMatrix<int,rowMajor> > A( 3UL );
+
+ // Creating a default initialized sparse uniupper matrix of size 3x3
+ //
+ // ( 1 0 0 )
+ // B = ( 0 1 0 )
+ // ( 0 0 1 )
+ UniUpperMatrix< CompressedMatrix<int,rowMajor> > B( 3UL );
+ \endcode
+
+// Second, this means that it is only allowed to modify elements in the upper part of the matrix,
+// but not the diagonal elements and not the elements in the lower part of the matrix. Also, it
+// is only possible to assign matrices that are upper unitriangular matrices themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::UniUpperMatrix;
+ using blaze::rowMajor;
+
+ typedef UniUpperMatrix< CompressedMatrix<double,rowMajor> > CompressedUniUpper;
+
+ // Default constructed, row-major 3x3 uniupper compressed matrix
+ CompressedUniUpper A( 3 );
+
+ // Initializing elements via the function call operator
+ A(0,0) = 9.0; // Throws an exception; invalid modification of diagonal element
+ A(0,2) = 2.0; // Initialization of the upper element (0,2)
+ A(2,1) = 9.0; // Throws an exception; invalid modification of lower element
+
+ // Inserting elements via the insert() function
+ A.insert( 0, 1, 3.0 ); // Inserting the upper element (0,1)
+ A.insert( 1, 1, 9.0 ); // Throws an exception; invalid insertion of diagonal element
+ A.insert( 2, 0, 9.0 ); // Throws an exception; invalid insertion of lower element
+
+ // Appending an element via the append() function
+ A.reserve( 1, 3 ); // Reserving enough capacity in row 1
+ A.append( 1, 2, 5.0 ); // Appending the upper element (1,2)
+ A.append( 2, 1, 9.0 ); // Throws an exception; appending an element in the lower part
+
+ // Access via a non-const iterator
+ CompressedUniUpper::Iterator it = A.begin(1);
+ *it = 9.0; // Throws an exception; invalid modification of the diagonal element (1,1)
+ ++it;
+ *it = 6.0; // Modifies the upper element (1,2)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Throws an exception; invalid erasure of the diagonal element (0,0)
+ A.erase( 0, 2 ); // Erasing the upper element (0,2)
+
+ // Construction from an uniupper dense matrix
+ StaticMatrix<double,3UL,3UL> B( { { 1.0, 8.0, -2.0 },
+ { 0.0, 1.0, -1.0 },
+ { 0.0, 0.0, 1.0 } } );
+
+ UniUpperMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-uniupper dense matrix
+ StaticMatrix<double,3UL,3UL> D( { { 3.0, 8.0, -2.0 },
+ { 0.0, 0.0, -1.0 },
+ { -2.0, 0.0, 4.0 } } );
+
+ C = D; // Throws an exception; upper unitriangular matrix invariant would be violated!
+ \endcode
+
+// The upper unitriangular matrix property is also enforced for uniupper custom matrices: In case
+// the given array of elements does not represent an uniupper matrix, a \a std::invalid_argument
+// exception is thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::UniUpperMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef UniUpperMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomUniUpper;
+
+ // Creating a 3x3 uniupper custom matrix from a properly initialized array
+ double array[9] = { 1.0, 2.0, 3.0,
+ 0.0, 1.0, 4.0,
+ 0.0, 0.0, 1.0 };
+ CustomUniUpper A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 uniupper custom matrix from an uninitialized array
+ CustomUniUpper B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the upper unitriangular matrix property is enforced for views (rows, columns,
+// submatrices, ...) on the uniupper matrix. The following example demonstrates that modifying
+// the elements of an entire row and submatrix of an uniupper matrix only affects the upper
+// matrix elements:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+
+ // Setup of the upper matrix
+ //
+ // ( 1 2 0 4 )
+ // A = ( 0 1 3 0 )
+ // ( 0 0 1 5 )
+ // ( 0 0 0 1 )
+ //
+ UniUpperMatrix< DynamicMatrix<int> > A( 4 );
+ A(0,1) = 2;
+ A(0,3) = 4;
+ A(1,2) = 3;
+ A(2,3) = 5;
+
+ // Setting the upper elements in the 1st row to 9 results in the matrix
+ //
+ // ( 1 1 0 4 )
+ // A = ( 0 1 9 9 )
+ // ( 0 0 1 5 )
+ // ( 0 0 0 1 )
+ //
+ row( A, 1 ) = 9;
+
+ // Setting the upper elements in the 1st and 2nd column to 7 results in
+ //
+ // ( 1 7 7 4 )
+ // A = ( 0 1 7 9 )
+ // ( 0 0 1 5 )
+ // ( 0 0 0 1 )
+ //
+ submatrix( A, 0, 1, 4, 2 ) = 7;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to rows/columns and submatrices of
+// uniupper matrices. Since only upper elements may be modified the matrix to be assigned must
+// be structured such that the upper unitriangular matrix invariant of the uniupper matrix is
+// preserved. Otherwise a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::UniUpperMatrix;
+ using blaze::rowVector;
+
+ // Setup of two default 4x4 upper matrices
+ UniUpperMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of a 4-dimensional vector
+ //
+ // v = ( 0 1 2 3 )
+ //
+ DynamicVector<int,rowVector> v( 4, 0 );
+ v[1] = 1;
+ v[2] = 2;
+ v[3] = 3;
+
+ // OK: Assigning v to the 1st row of A1 preserves the upper matrix invariant
+ //
+ // ( 1 0 0 0 )
+ // A1 = ( 0 1 2 3 )
+ // ( 0 0 1 0 )
+ // ( 0 0 0 1 )
+ //
+ row( A1, 1 ) = v; // OK
+
+ // Error: Assigning v to the 2nd row of A1 violates the uniupper matrix invariant! The elements
+ // marked with X cannot be assigned and trigger an exception.
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 1 2 3 )
+ // ( 0 X X 3 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 2 ) = v; // Assignment throws an exception!
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 7 8 )
+ // B = ( 1 9 )
+ // ( 0 1 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL, 0 );
+ B(0,0) = 7;
+ B(0,1) = 8;
+ B(1,0) = 1;
+ B(1,1) = 9;
+ B(2,0) = 1;
+
+ // OK: Assigning B to a submatrix of A2 such that the uniupper matrix invariant can be preserved
+ //
+ // ( 1 7 8 0 )
+ // A2 = ( 0 1 9 0 )
+ // ( 0 0 1 0 )
+ // ( 0 0 0 1 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the upper matrix invariant cannot be
+ // preserved! The elements marked with X cannot be assigned without violating the invariant!
+ //
+ // ( X 8 8 0 )
+ // A2 = ( X X 9 0 )
+ // ( 0 X 1 0 )
+ // ( 0 0 0 1 )
+ //
+ submatrix( A2, 0UL, 0UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection uniuppermatrix_initialization The Lower Elements of a Dense Upper Unitriangular Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency during the creation of a dense uniupper
+// matrix this initialization is important since otherwise the upper unitriangular matrix property
+// of dense uniupper matrices would not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // 5x5 row-major uniupper dynamic matrix with default initialized lower matrix
+ UniUpperMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \subsection uniuppermatrix_storage Dense Upper Unitriangular Matrices Also Store the Lower Elements!
+//
+// It is important to note that dense upper unitriangular matrices store all elements, including
+// the elements in the lower part of the matrix, and therefore don't provide any kind of memory
+// reduction! There are two main reasons for this: First, storing also the lower elements
+// guarantees maximum performance for many algorithms that perform vectorized operations on the
+// uniupper matrix, which is especially true for small dense matrices. Second, conceptually the
+// UniUpperMatrix adaptor merely restricts the interface to the matrix type \a MT and does not
+// change the data layout or the underlying matrix type.
+//
+//
+// \n \subsection uniuppermatrix_scaling Upper Unitriangular Matrices Cannot Be Scaled!
+//
+// Since the diagonal elements have a fixed value of 1 it is not possible to self-scale an uniupper
+// matrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+
+ UniUpperMatrix< DynamicMatrix<int> > A( 4 );
+
+ A *= 2; // Compilation error; Scale operation is not available on an uniupper matrix
+ A /= 2; // Compilation error; Scale operation is not available on an uniupper matrix
+ A.scale( 2 ); // Compilation error; Scale function is not available on an uniupper matrix
+
+ A = A * 2; // Throws an exception; Invalid assignment of non-uniupper matrix
+ A = A / 2; // Throws an exception; Invalid assignment of non-uniupper matrix
+ \endcode
+
+// \n \section uniuppermatrix_arithmetic_operations Arithmetic Operations
+//
+// An UniUpperMatrix matrix can participate in numerical operations in any way any other dense or
+// sparse matrix can participate. It can also be combined with any other dense or sparse vector
+// or matrix. The following code example gives an impression of the use of UniUpperMatrix within
+// arithmetic operations:
+
+ \code
+ using blaze::UniUpperMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ UniUpperMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ UniUpperMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ UniUpperMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > E;
+ UniUpperMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > F;
+
+ DynamicMatrix<double,rowMajor> G( 3, 3 ); // Initialized as strictly upper matrix
+ CompressedMatrix<double,rowMajor> H( 3, 3 ); // Initialized as strictly upper matrix
+
+ E = A + B; // Matrix addition and assignment to a row-major uniupper matrix
+ F = A - C; // Matrix subtraction and assignment to a column-major uniupper matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ E += G; // Addition assignment (note that G is a strictly upper matrix)
+ F -= H; // Subtraction assignment (note that H is a strictly upper matrix)
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section uniuppermatrix_performance Performance Considerations
+//
+// The \b Blaze library tries to exploit the properties of upper (uni-)triangular matrices whenever
+// and wherever possible. Thus using an upper (uni-)triangular matrix instead of a general matrix
+// can result in a considerable performance improvement. However, there are also situations when
+// using an (uni-)upper matrix introduces some overhead. The following examples demonstrate several
+// common situations where (uni-)upper matrices can positively or negatively impact performance.
+//
+// \n \subsection uniuppermatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is upper (uni-)triangular, \b Blaze can
+// exploit the fact that the lower part of the matrix contains only default elements and restrict
+// the algorithm to the upper and diagonal elements. The following example demonstrates this by
+// means of a dense matrix/dense matrix multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ UniUpperMatrix< DynamicMatrix<double,rowMajor> > A;
+ UniUpperMatrix< DynamicMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// In comparison to a general matrix multiplication, the performance advantage is significant,
+// especially for large matrices. Therefore is it highly recommended to use the UniUpperMatrix
+// adaptor when a matrix is known to be upper unitriangular. Note however that the performance
+// advantage is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection uniuppermatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar performance improvement can be gained when using an upper (uni-)triangular matrix in
+// a matrix/vector multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::UniUpperMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ UniUpperMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicVector<double,columnVector> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example, \b Blaze also exploits the structure of the matrix and approx. halves the
+// runtime of the multiplication. Also in case of matrix/vector multiplications the performance
+// improvement is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection uniuppermatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using an upper (uni-)triangular matrix on the right-hand side of an assignment
+// (i.e. for read access), which introduces absolutely no performance penalty, using an (uni-)upper
+// matrix on the left-hand side of an assignment (i.e. for write access) may introduce additional
+// overhead when it is assigned a general matrix, which is not upper (uni-)triangular at compile
+// time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UniUpperMatrix;
+
+ UniUpperMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the upper matrix; no performance penalty
+ C = A; // Assignment of an uniupper matrix to another uniupper matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to an uniupper matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not uniupper matrix to another uniupper matrix it is
+// necessary to check whether the matrix is uniupper at runtime in order to guarantee the upper
+// unitriangular property of the uniupper matrix. In case it turns out to be upper unitriangular,
+// it is assigned as efficiently as possible, if it is not, an exception is thrown. In order to
+// prevent this runtime overhead it is therefore generally advisable to assign uniupper matrices
+// to other uniupper matrices.\n
+// In this context it is especially noteworthy that the multiplication of two upper unitriangular
+// matrices always results in another uniupper matrix:
+
+ \code
+ UniUpperMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A * B; // Results in an uniupper matrix; no runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class UniUpperMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uniuppermatrix/Dense.h b/src/cpu/blaze/math/adaptors/uniuppermatrix/Dense.h
new file mode 100644
index 00000000..ebab7056
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uniuppermatrix/Dense.h
@@ -0,0 +1,2696 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uniuppermatrix/Dense.h
+// \brief UniUpperMatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_DENSE_H_
+#define _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/uniuppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/uniuppermatrix/UniUpperProxy.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/Square.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of UniUpperMatrix for dense matrices.
+// \ingroup uniupper_matrix
+//
+// This specialization of UniUpperMatrix adapts the class template to the requirements of dense
+// matrices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class UniUpperMatrix<MT,SO,true>
+ : public DenseMatrix< UniUpperMatrix<MT,SO,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef UniUpperMatrix<MT,SO,true> This; //!< Type of this UniUpperMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this UniUpperMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef UniUpperMatrix<OT,!SO,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef UniLowerMatrix<TT,!SO,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef UniUpperProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain an UniUpperMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other UniUpperMatrix.
+ typedef UniUpperMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense uniupper matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef UniUpperProxy<MT> PointerType; //!< Pointer return type.
+ typedef UniUpperProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row-index of the iterator
+ , column_( column ) // The current column-index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row-index of the iterator.
+ size_t column_; //!< The current column-index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UniUpperMatrix();
+ template< typename A1 > explicit inline UniUpperMatrix( const A1& a1 );
+ explicit inline UniUpperMatrix( size_t n, const ElementType& init );
+
+ explicit inline UniUpperMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline UniUpperMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline UniUpperMatrix( const Other (&array)[N][N] );
+
+ explicit inline UniUpperMatrix( ElementType* ptr, size_t n );
+ explicit inline UniUpperMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline UniUpperMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline UniUpperMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline UniUpperMatrix( const UniUpperMatrix& m );
+ inline UniUpperMatrix( UniUpperMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline UniUpperMatrix& operator=( const ElementType& rhs );
+ inline UniUpperMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline UniUpperMatrix& operator=( const Other (&array)[N][N] );
+
+ inline UniUpperMatrix& operator=( const UniUpperMatrix& rhs );
+ inline UniUpperMatrix& operator=( UniUpperMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniUpperMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniUpperMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniUpperMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniUpperMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniUpperMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniUpperMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline UniUpperMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ inline void swap( UniUpperMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ inline const MT construct( size_t n , TrueType );
+ inline const MT construct( const ElementType& value, FalseType );
+
+ template< typename MT2, bool SO2, typename T >
+ inline const MT construct( const Matrix<MT2,SO2>& m, T );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( UniUpperMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for UniUpperMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ for( size_t i=0UL; i<Rows<MT>::value; ++i )
+ matrix_(i,i) = ElementType(1);
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Single argument constructor for an uniupper matrix.
+//
+// \param a1 The single constructor argument.
+// \exception std::invalid_argument Invalid setup of uniupper matrix.
+//
+// This constructor constructs the uniupper matrix based on the given argument and the type of
+// the underlying matrix \a MT:
+// - in case the given argument is a matrix, the uniupper matrix is initialized as a copy of
+// the given matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// resizable, the given argument \a a1 specifies the number of rows and columns of the
+// uniupper matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// a matrix with fixed size, the given argument \a a1 specifies the initial value of the
+// upper elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename A1 > // Type of the constructor argument
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( const A1& a1 )
+ : matrix_( construct( a1, typename IsResizable<MT>::Type() ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a \f$ n \times n \f$ matrix with initialized upper elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param init The initial value of the upper matrix elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( size_t n, const ElementType& init )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i )
+ matrix_(i,j) = init;
+ matrix_(j,j) = ElementType(1);
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ matrix_(i,i) = ElementType(1);
+ for( size_t j=i+1UL; j<columns(); ++j )
+ matrix_(i,j) = init;
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of uniupper matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the uniupper
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::UniUpperMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A{ { 1, 2, 3 },
+ { 0, 1 },
+ { 0, 0, 1 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isUniUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all uniupper matrix elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of uniupper matrix.
+//
+// This constructor offers the option to directly initialize the elements of the uniupper matrix
+// with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[16];
+ // ... Initialization of the dynamic array
+ blaze::UniUpperMatrix< blaze::DynamicMatrix<int,rowMajor> > v( 4UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized accoring to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a m by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also, in
+// case the given array does not represent a upper unitriangular matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isUniUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all uniupper matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of uniupper matrix.
+//
+// This constructor offers the option to directly initialize the elements of the uniupper matrix
+// with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 0, 1 },
+ { 0, 0, 1 } };
+ blaze::UniUpperMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a upper unitriangular matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isUniUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a uniupper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of uniupper custom matrix.
+//
+// This constructor creates an unpadded uniupper custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent an upper unitriangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded uniupper custom matrices!
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isUniUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a uniupper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of uniupper custom matrix.
+//
+// This constructor creates a uniupper custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent an upper unitriangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isUniUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a uniupper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of uniupper custom matrix.
+//
+// This constructor creates an unpadded uniupper custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent an upper unitriangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded uniupper custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isUniUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a uniupper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of uniupper custom matrix.
+//
+// This constructor creates a uniupper custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent an upper unitriangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isUniUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for UniUpperMatrix.
+//
+// \param m The uniupper matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( const UniUpperMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for UniUpperMatrix.
+//
+// \param m The uniupper matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>::UniUpperMatrix( UniUpperMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::Reference
+ UniUpperMatrix<MT,SO,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::ConstReference
+ UniUpperMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::Reference
+ UniUpperMatrix<MT,SO,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::ConstReference
+ UniUpperMatrix<MT,SO,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the uniupper matrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The uniupper matrix
+// may use techniques such as padding to improve the alignment of the data. Whereas the number
+// of elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::ConstPointer
+ UniUpperMatrix<MT,SO,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::ConstPointer
+ UniUpperMatrix<MT,SO,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the uniupper matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::Iterator
+ UniUpperMatrix<MT,SO,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the uniupper matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::ConstIterator
+ UniUpperMatrix<MT,SO,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the uniupper matrix adapts a \a rowMajor dense matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::ConstIterator
+ UniUpperMatrix<MT,SO,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the uniupper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::Iterator
+ UniUpperMatrix<MT,SO,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the uniupper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::ConstIterator
+ UniUpperMatrix<MT,SO,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the uniupper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UniUpperMatrix<MT,SO,true>::ConstIterator
+ UniUpperMatrix<MT,SO,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all upper matrix elements.
+//
+// \param rhs Scalar value to be assigned to the upper matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>&
+ UniUpperMatrix<MT,SO,true>::operator=( const ElementType& rhs )
+{
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j )
+ for( size_t i=0UL; i<j; ++i )
+ matrix_(i,j) = rhs;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=i+1UL; j<columns(); ++j )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the uniupper
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::UniUpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = { { 1, 2, 3 },
+ { 0, 1 },
+ { 0, 0, 1 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>&
+ UniUpperMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isUniUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all uniupper matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// This assignment operator offers the option to directly set all elements of the uniupper matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 0, 1 },
+ { 0, 0, 1 } };
+ blaze::UniUpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a uniupper triangular matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline UniUpperMatrix<MT,SO,true>&
+ UniUpperMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isUniUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for UniUpperMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>&
+ UniUpperMatrix<MT,SO,true>::operator=( const UniUpperMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for UniUpperMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UniUpperMatrix<MT,SO,true>&
+ UniUpperMatrix<MT,SO,true>::operator=( UniUpperMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// uniupper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,true>& >
+ UniUpperMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsStrictlyTriangular<MT2>::value || ( !IsUniUpper<MT2>::value && !isUniUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// uniupper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,true>& >
+ UniUpperMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsStrictlyTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ if( IsUniUpper<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isUniUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an uniupper
+// matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is not an
+// uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,true>& >
+ UniUpperMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsLower<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an uniupper
+// matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is not an
+// uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,true>& >
+ UniUpperMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsLower<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// uniupper matrix, i.e. the given matrix must be a strictly upper matrix. In case the
+// result is not an uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,true>& >
+ UniUpperMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsLower<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// uniupper matrix, i.e. the given matrix must be a strictly upper matrix. In case the
+// result is not an uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,true>& >
+ UniUpperMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsLower<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be an uniupper matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline UniUpperMatrix<MT,SO,true>&
+ UniUpperMatrix<MT,SO,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isUniUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniUpperMatrix<MT,SO,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniUpperMatrix<MT,SO,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the total
+// number of elements of a row/column. In case the uniupper matrix adapts a \a rowMajor dense
+// matrix the function returns the spacing between two rows, in case it adapts a \a columnMajor
+// dense matrix the function returns the spacing between two columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniUpperMatrix<MT,SO,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniUpperMatrix<MT,SO,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the uniupper
+// matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor dense matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniUpperMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the uniupper matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniUpperMatrix<MT,SO,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the uniupper matrix adapts a \a rowMajor dense matrix the function returns the
+// number of non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix
+// the function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UniUpperMatrix<MT,SO,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniUpperMatrix<MT,SO,true>::reset()
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j )
+ for( size_t i=0UL; i<j; ++i )
+ clear( matrix_(i,j) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=i+1UL; j<columns(); ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniUpperMatrix<MT,SO,true>::reset( size_t i )
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=0UL; j<i; ++j )
+ clear( matrix_(j,i) );
+ }
+ else {
+ for( size_t j=i+1UL; j<columns(); ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the uniupper matrix.
+//
+// \return void
+//
+// This function clears the uniupper matrix and returns it to its default state. The function has
+// the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
+// matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
+// to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
+// be reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniUpperMatrix<MT,SO,true>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the uniupper matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the uniupper matrix adapts a resizable matrix, this function resizes the matrix using
+// the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
+// in case the capacity of the matrix is too small. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, the resize operation potentially changes all matrix elements. In order
+// to preserve the old matrix values, the \a preserve flag can be set to \a true. Also note that
+// in case the size of the matrix is increased, only the new elements in the lower part of the
+// matrix are default initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 0 & 1 & 4 \\
+ 0 & 0 & 1 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & x \\
+ 0 & 1 & 4 & x \\
+ 0 & 0 & 1 & x \\
+ 0 & 0 & 0 & 1 \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void UniUpperMatrix<MT,SO,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize )
+ {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, oldsize, 0UL, increment, n-1UL ).reset();
+
+ for( size_t i=oldsize; i<n; ++i )
+ matrix_(i,i) = ElementType(1);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniUpperMatrix<MT,SO,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the uniupper matrix.
+// \return void
+//
+// This function increases the capacity of the uniupper matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniUpperMatrix<MT,SO,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniUpperMatrix<MT,SO,true>::swap( UniUpperMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for an upper unitriangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for an upper unitriangular
+// matrix with fixed-size adapted matrix of type \a MT. Note that this function can only be
+// called in case the adapted dense matrix is a fixed-size matrix (as for instance StaticMatrix).
+// The attempt to call this function in case the adapted matrix is resizable matrix will result
+// in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UniUpperMatrix<MT,SO,true>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for an upper unitriangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for an upper unitriangular
+// matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UniUpperMatrix<MT,SO,true>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n + 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the uniupper matrix are intact.
+//
+// \return \a true in case the uniupper matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the uniupper matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UniUpperMatrix<MT,SO,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isUniUpper( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UniUpperMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UniUpperMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UniUpperMatrix<MT,SO,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UniUpperMatrix<MT,SO,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the uniupper matrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the column index (in case of a row-major matrix) or
+// the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UniUpperMatrix<MT,SO,true>::SIMDType
+ UniUpperMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the uniupper matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UniUpperMatrix<MT,SO,true>::SIMDType
+ UniUpperMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the uniupper matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UniUpperMatrix<MT,SO,true>::SIMDType
+ UniUpperMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a resizable matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT UniUpperMatrix<MT,SO,true>::construct( size_t n, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ MT tmp( n, n, ElementType() );
+
+ for( size_t i=0UL; i<n; ++i )
+ tmp(i,i) = ElementType(1);
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a fixed-size matrix with homogeneously initialized upper elements.
+//
+// \param init The initial value of the upper matrix elements.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT UniUpperMatrix<MT,SO,true>::construct( const ElementType& init, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SQUARE( MT );
+
+ MT tmp;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i )
+ tmp(i,j) = init;
+ tmp(j,j) = ElementType(1);
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ tmp(i,i) = ElementType(1);
+ for( size_t j=i+1UL; j<columns(); ++j )
+ tmp(i,j) = init;
+ }
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a matrix as a copy from another matrix.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of uniupper matrix.
+// \return The newly constructed matrix.
+//
+// In case the given matrix is not an uniupper matrix, a \a std::invalid_argument exception is
+// thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT UniUpperMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ const MT tmp( ~m );
+
+ if( IsStrictlyTriangular<MT2>::value || ( !IsUniUpper<MT2>::value && !isUniUpper( tmp ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uniuppermatrix/Sparse.h b/src/cpu/blaze/math/adaptors/uniuppermatrix/Sparse.h
new file mode 100644
index 00000000..7d402a36
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uniuppermatrix/Sparse.h
@@ -0,0 +1,2211 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uniuppermatrix/Sparse.h
+// \brief UniUpperMatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_SPARSE_H_
+#define _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/uniuppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/uniuppermatrix/UniUpperElement.h>
+#include <blaze/math/adaptors/uniuppermatrix/UniUpperProxy.h>
+#include <blaze/math/adaptors/uniuppermatrix/UniUpperValue.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of UniUpperMatrix for sparse matrices.
+// \ingroup uniupper_matrix
+//
+// This specialization of UniUpperMatrix adapts the class template to the requirements of sparse
+// matrices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class UniUpperMatrix<MT,SO,false>
+ : public SparseMatrix< UniUpperMatrix<MT,SO,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef UniUpperMatrix<MT,SO,false> This; //!< Type of this UniUpperMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this UniUpperMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef UniUpperMatrix<OT,!SO,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef UniLowerMatrix<TT,!SO,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef UniUpperProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain an UniUpperMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other UniUpperMatrix.
+ typedef UniUpperMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the elements of the upper unitriangular matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef Iterator_<MT> IteratorType; //!< Type of the underlying sparse matrix iterators.
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef UniUpperElement<MT> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Default constructor**********************************************************************
+ /*!\brief Default constructor for the Iterator class.
+ */
+ inline Iterator()
+ : pos_ ( ) // Iterator to the current upper unitriangular matrix element
+ , index_ ( 0UL ) // The row/column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param pos The initial position of the iterator.
+ // \param index The row/column index of the iterator.
+ */
+ inline Iterator( IteratorType pos, size_t index )
+ : pos_ ( pos ) // Iterator to the current upper unitriangular matrix element
+ , index_( index ) // The row/column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() {
+ ++pos_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Reference to the current sparse matrix element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, pos_->index() == index_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse matrix element.
+ //
+ // \return Pointer to the current sparse matrix element.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, pos_->index() == index_ );
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const Iterator& rhs ) const {
+ return pos_ == rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const Iterator& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two matrix iterators.
+ //
+ // \param rhs The right-hand side matrix iterator.
+ // \return The number of elements between the two matrix iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const {
+ return pos_ - rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the matrix iterator.
+ //
+ // \return The current position of the matrix iterator.
+ */
+ inline IteratorType base() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current upper unitriangular matrix element.
+ size_t index_; //!< The row/column index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UniUpperMatrix();
+ explicit inline UniUpperMatrix( size_t n );
+ explicit inline UniUpperMatrix( size_t n, size_t nonzeros );
+ explicit inline UniUpperMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline UniUpperMatrix( const UniUpperMatrix& m );
+ inline UniUpperMatrix( UniUpperMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline UniUpperMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline UniUpperMatrix& operator=( const UniUpperMatrix& rhs );
+ inline UniUpperMatrix& operator=( UniUpperMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniUpperMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniUpperMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniUpperMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniUpperMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UniUpperMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UniUpperMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline UniUpperMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ inline void swap( UniUpperMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void resetLower();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( UniUpperMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ElementType );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for UniUpperMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniUpperMatrix<MT,SO,false>::UniUpperMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized as identity matrix and has no additional free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniUpperMatrix<MT,SO,false>::UniUpperMatrix( size_t n )
+ : matrix_( n, n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix_.append( i, i, ElementType(1) );
+ matrix_.finalize( i );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized as identity matrix and will have at least the capacity for
+// \a nonzeros non-zero elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniUpperMatrix<MT,SO,false>::UniUpperMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, max( nonzeros, n ) ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ matrix_.append( i, i, ElementType(1) );
+ matrix_.finalize( i );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+// \exception std::invalid_argument Invalid capacity specification.
+//
+// The matrix is initialized as identity matrix and will have the specified capacity in each
+// row/column. Note that since the matrix is initialized as \f$ n \times n \f$ identity matrix
+// the given vector must have at least \a n elements, all of which must not be 0. If the number
+// of non-zero elements of any row/column is specified as 0, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniUpperMatrix<MT,SO,false>::UniUpperMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ for( size_t i=0UL; i<n; ++i )
+ {
+ if( nonzeros[i] == 0UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid capacity specification" );
+ }
+
+ matrix_.append( i, i, ElementType(1) );
+ matrix_.finalize( i );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for UniUpperMatrix.
+//
+// \param m The uniupper matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniUpperMatrix<MT,SO,false>::UniUpperMatrix( const UniUpperMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for UniUpperMatrix.
+//
+// \param m The uniupper matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniUpperMatrix<MT,SO,false>::UniUpperMatrix( UniUpperMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of uniupper matrix.
+//
+// This constructor initializes the uniupper matrix as a copy of the given matrix. In case the
+// given matrix is not an uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline UniUpperMatrix<MT,SO,false>::UniUpperMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( ~m ) // The adapted sparse matrix
+{
+ if( !IsUniUpper<MT2>::value && !isUniUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" );
+ }
+
+ if( !IsUniUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Reference
+ UniUpperMatrix<MT,SO,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstReference
+ UniUpperMatrix<MT,SO,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Reference
+ UniUpperMatrix<MT,SO,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt
+// to assign to an element on the diagonal or in the lower part of the matrix (i.e. below the
+// diagonal) will result in a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstReference
+ UniUpperMatrix<MT,SO,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the uniupper matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::begin( size_t i )
+{
+ return Iterator( matrix_.begin(i), i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the uniupper matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstIterator
+ UniUpperMatrix<MT,SO,false>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the uniupper matrix adapts a \a rowMajor sparse matrix the function returns an iterator to
+// the first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstIterator
+ UniUpperMatrix<MT,SO,false>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the uniupper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::end( size_t i )
+{
+ return Iterator( matrix_.end(i), i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the uniupper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstIterator
+ UniUpperMatrix<MT,SO,false>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the uniupper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstIterator
+ UniUpperMatrix<MT,SO,false>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for UniUpperMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniUpperMatrix<MT,SO,false>&
+ UniUpperMatrix<MT,SO,false>::operator=( const UniUpperMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for UniUpperMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UniUpperMatrix<MT,SO,false>&
+ UniUpperMatrix<MT,SO,false>::operator=( UniUpperMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// uniupper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,false>& >
+ UniUpperMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsStrictlyTriangular<MT2>::value || ( !IsUniUpper<MT2>::value && !isUniUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ if( !IsUniUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// uniupper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,false>& >
+ UniUpperMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsStrictlyTriangular<MT2>::value || ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ if( IsUniUpper<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isUniUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ if( !IsUniUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an uniupper
+// matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is not an
+// uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,false>& >
+ UniUpperMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsLower<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an uniupper
+// matrix, i.e. the given matrix must be a strictly upper matrix. In case the result is not an
+// uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,false>& >
+ UniUpperMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsLower<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// uniupper matrix, i.e. the given matrix must be a strictly upper matrix. In case the
+// result is not an uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,false>& >
+ UniUpperMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsLower<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsStrictlyUpper<MT2>::value && !isStrictlyUpper( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to uniupper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// uniupper matrix, i.e. the given matrix must be a strictly upper matrix. In case the
+// result is not an uniupper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UniUpperMatrix<MT,SO,false>& >
+ UniUpperMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsLower<MT2>::value || IsUniTriangular<MT2>::value ||
+ ( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ if( IsStrictlyUpper<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isStrictlyUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ if( !IsStrictlyUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be an uniupper matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline UniUpperMatrix<MT,SO,false>&
+ UniUpperMatrix<MT,SO,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isUniUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ if( !IsUniUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniUpperMatrix<MT,SO,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniUpperMatrix<MT,SO,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniUpperMatrix<MT,SO,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the uniupper
+// matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniUpperMatrix<MT,SO,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the uniupper matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniUpperMatrix<MT,SO,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the uniupper matrix adapts a \a rowMajor sparse matrix the function returns the
+// number of non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse
+// matrix the function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UniUpperMatrix<MT,SO,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::reset()
+{
+ if( SO ) {
+ for( size_t j=1UL; j<columns(); ++j ) {
+ matrix_.erase( j, matrix_.begin(j), matrix_.lowerBound(j,j) );
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ matrix_.erase( i, matrix_.lowerBound(i,i+1UL), matrix_.end(i) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::reset( size_t i )
+{
+ if( SO ) {
+ matrix_.erase( i, matrix_.begin(i), matrix_.lowerBound(i,i) );
+ }
+ else {
+ matrix_.erase( i, matrix_.lowerBound(i,i+1UL), matrix_.end(i) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the uniupper matrix.
+//
+// \return void
+//
+// This function clears the uniupper matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the uniupper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to diagonal or lower matrix element.
+//
+// This function sets the value of an element of the uniupper matrix. In case the uniupper matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted. The attempt to set an element on the
+// diagonal or in the lower part of the matrix (i.e. below the diagonal) will result in a
+// \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ if( i >= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or lower matrix element" );
+ }
+
+ return Iterator( matrix_.set( i, j, value ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the uniupper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+// \exception std::invalid_argument Invalid access to diagonal or lower matrix element.
+//
+// This function inserts a new element into the uniupper matrix. However, duplicate elements are
+// not allowed. In case the uniupper matrix already contains an element with row index \a i and
+// column index \a j, a \a std::invalid_argument exception is thrown. Also, the attempt to insert
+// an element on the diagonal or in the lower part of the matrix (i.e. below the diagonal) will
+// result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ if( i >= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or lower matrix element" );
+ }
+
+ return Iterator( matrix_.insert( i, j, value ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the uniupper matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function erases a non-diagonal element from the uniupper matrix. The attempt to erase a
+// diagonal element will result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::erase( size_t i, size_t j )
+{
+ if( i == j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+
+ matrix_.erase( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the uniupper matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function erases a non-diagonal element from the uniupper matrix. In case the uniupper
+// matrix adapts a \a rowMajor sparse matrix the function erases an element from row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function erases an element from column \a i.
+// The attempt to erase a diagonal element will result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::erase( size_t i, Iterator pos )
+{
+ if( pos != matrix_.end(i) && pos->index() == i ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+
+ return Iterator( matrix_.erase( i, pos.base() ), i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the uniupper matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+// \exception std::invalid_argument Invalid access to diagonal matrix element.
+//
+// This function erases a range of elements from the uniupper matrix. In case the uniupper matrix
+// adapts a \a rowMajor sparse matrix the function erases a range of elements from row \a i, in
+// case it adapts a \a columnMajor matrix the function erases a range of elements from column \a i.
+// The attempt to erase a diagonal element will result in a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ for( Iterator element=first; element!=last; ++element ) {
+ if( element->index() == i ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal matrix element" );
+ }
+ }
+
+ return Iterator( matrix_.erase( i, first.base(), last.base() ), i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the uniupper matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void UniUpperMatrix<MT,SO,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square uniupper matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, preserve );
+
+ if( n > oldsize ) {
+ for( size_t i=oldsize; i<n; ++i )
+ matrix_.insert( i, i, ElementType(1) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the uniupper matrix.
+//
+// \param nonzeros The new minimum capacity of the uniupper matrix.
+// \return void
+//
+// This function increases the capacity of the uniupper matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the uniupper matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the uniupper matrix to at least
+// \a nonzeros elements. The current values of the uniupper matrix and all other individual
+// row/column capacities are preserved. In case the uniupper matrix adapts a \a rowMajor sparse
+// matrix the function reserves capacity for row \a i. In case it adapts a \a columnMajor the
+// function reserves capacity for column \a i. The index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the uniupper matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::swap( UniUpperMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for an upper unitriangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for an upper unitriangular
+// matrix with fixed-size adapted matrix of type \a MT. Note that this function can only be
+// called in case the adapted dense matrix is a fixed-size matrix. The attempt to call this
+// function in case the adapted matrix is resizable matrix will result in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UniUpperMatrix<MT,SO,false>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for an upper unitriangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for an upper unitriangular
+// matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UniUpperMatrix<MT,SO,false>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n + 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the complete lower part of the matrix to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UniUpperMatrix<MT,SO,false>::resetLower()
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ matrix_.erase( j, matrix_.upperBound( j, j ), matrix_.end( j ) );
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i )
+ matrix_.erase( i, matrix_.begin( i ), matrix_.lowerBound( i, i ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the uniupper
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned uniupper matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::find( size_t i, size_t j )
+{
+ return Iterator( matrix_.find( i, j ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the uniupper
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned uniupper matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstIterator
+ UniUpperMatrix<MT,SO,false>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned uniupper matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::lowerBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.lowerBound( i, j ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned uniupper matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstIterator
+ UniUpperMatrix<MT,SO,false>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned uniupper matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::Iterator
+ UniUpperMatrix<MT,SO,false>::upperBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.upperBound( i, j ), ( SO ? j : i ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned uniupper matrix
+// iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UniUpperMatrix<MT,SO,false>::ConstIterator
+ UniUpperMatrix<MT,SO,false>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the uniupper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to diagonal or lower matrix element.
+//
+// This function provides a very efficient way to fill an uniupper sparse matrix with elements.
+// It appends a new element to the end of the specified row/column without any additional memory
+// allocation. Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (newly created) sparse matrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::UniUpperMatrix;
+ using blaze::rowMajor;
+
+ UniUpperMatrix< CompressedMatrix<double,rowMajor> > A( 4 );
+
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 0, 1, 1.0 ); // Appending the value 1 in row 0 with column index 1
+ A.finalize( 0 ); // Finalizing row 0
+ A.append( 1, 2, 2.0 ); // Appending the value 2 in row 1 with column index 2
+ A.finalize( 1 ); // Finalizing row 1
+ A.append( 2, 3, 3.0 ); // Appending the value 3 in row 2 with column index 3
+ A.finalize( 2 ); // Finalizing row 2
+ A.finalize( 3 ); // Finalizing the final row 3
+ \endcode
+
+// Note that although append() does not allocate new memory it still invalidates all iterators
+// returned by the end() functions! Also note that the attempt to append an element within the
+// lower part of the matrix (i.e. below the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( i >= j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to diagonal or lower matrix element" );
+ }
+
+ if( !check || !isDefault( value ) )
+ matrix_.insert( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UniUpperMatrix<MT,SO,false>::finalize( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the uniupper matrix are intact.
+//
+// \return \a true in case the uniupper matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the uniupper matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool UniUpperMatrix<MT,SO,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isUniUpper( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UniUpperMatrix<MT,SO,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UniUpperMatrix<MT,SO,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool UniUpperMatrix<MT,SO,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperElement.h b/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperElement.h
new file mode 100644
index 00000000..902c2cd2
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperElement.h
@@ -0,0 +1,367 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uniuppermatrix/UniUpperElement.h
+// \brief Header file for the UniUpperElement class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_UNIUPPERELEMENT_H_
+#define _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_UNIUPPERELEMENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/adaptors/uniuppermatrix/UniUpperValue.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Representation of an element within a sparse upper unitriangular matrix.
+// \ingroup uniupper_matrix
+//
+// The UniUpperElement class represents an element (i.e. value/index pair) within a sparse upper
+// unitriangular matrix. It guarantees that the uniupper matrix invariant is not violated, i.e.
+// that elements in the lower part of the matrix remain 0 and the diagonal elements remain 1. The
+// following example illustrates this by means of a \f$ 3 \times 3 \f$ sparse upper unitriangular
+// matrix:
+
+ \code
+ typedef blaze::UniUpperMatrix< blaze::CompressedMatrix<int> > UniUpper;
+
+ // Creating a 3x3 upper unitriangular sparse matrix
+ UniUpper A( 3UL );
+
+ A(0,1) = -2; // ( 1 -2 3 )
+ A(0,2) = 3; // => A = ( 0 1 5 )
+ A(1,2) = 5; // ( 0 0 1 )
+
+ UniUpper::Iterator it = A.begin( 1UL );
+ *it = 9; // Invalid assignment to diagonal matrix element; results in an exception!
+ ++it;
+ *it = 4; // Modification of matrix element (1,2)
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class UniUpperElement : private SparseElement
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> ElementType; //!< Type of the represented matrix element.
+ typedef Iterator_<MT> IteratorType; //!< Type of the underlying sparse matrix iterators.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef UniUpperValue<MT> ValueType; //!< The value type of the value-index-pair.
+ typedef size_t IndexType; //!< The index type of the value-index-pair.
+ typedef UniUpperValue<MT> Reference; //!< Reference return type.
+ typedef const UniUpperValue<MT> ConstReference; //!< Reference-to-const return type.
+ typedef UniUpperElement* Pointer; //!< Pointer return type.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline UniUpperElement( IteratorType pos, bool diagonal );
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ template< typename T > inline UniUpperElement& operator= ( const T& v );
+ template< typename T > inline UniUpperElement& operator+=( const T& v );
+ template< typename T > inline UniUpperElement& operator-=( const T& v );
+ template< typename T > inline UniUpperElement& operator*=( const T& v );
+ template< typename T > inline UniUpperElement& operator/=( const T& v );
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline Pointer operator->() noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline Reference value() const;
+ inline IndexType index() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ IteratorType pos_; //!< Iterator to the current upper unitriangular matrix element.
+ bool diagonal_; //!< \a true in case the element is on the diagonal, \a false if not.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE ( ElementType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the UniUpperElement class.
+//
+// \param pos Iterator to the current position with the sparse upper unitriangular matrix.
+// \param diagonal \a true in case the element is on the diagonal, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniUpperElement<MT>::UniUpperElement( IteratorType pos, bool diagonal )
+ : pos_ ( pos ) // Iterator to the current upper unitriangular matrix element
+ , diagonal_( diagonal ) // true in case the element is on the diagonal, false if not
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Assignment to the uniupper element.
+//
+// \param v The new value of the uniupper element.
+// \return Reference to the assigned uniupper element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperElement<MT>& UniUpperElement<MT>::operator=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ = v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the uniupper element.
+//
+// \param v The right-hand side value for the addition.
+// \return Reference to the assigned uniupper element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperElement<MT>& UniUpperElement<MT>::operator+=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ += v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the uniupper element.
+//
+// \param v The right-hand side value for the subtraction.
+// \return Reference to the assigned uniupper element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperElement<MT>& UniUpperElement<MT>::operator-=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ -= v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the uniupper element.
+//
+// \param v The right-hand side value for the multiplication.
+// \return Reference to the assigned uniupper element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperElement<MT>& UniUpperElement<MT>::operator*=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ *= v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the uniupper element.
+//
+// \param v The right-hand side value for the division.
+// \return Reference to the assigned uniupper element.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperElement<MT>& UniUpperElement<MT>::operator/=( const T& v )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *pos_ /= v;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the uniupper element.
+//
+// \return Reference to the value of the uniupper element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperElement<MT>::Pointer UniUpperElement<MT>::operator->() noexcept
+{
+ return this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access to the current value of the uniupper element.
+//
+// \return The current value of the uniupper element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperElement<MT>::Reference UniUpperElement<MT>::value() const
+{
+ return Reference( pos_->value(), diagonal_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the current index of the uniupper element.
+//
+// \return The current index of the uniupper element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperElement<MT>::IndexType UniUpperElement<MT>::index() const
+{
+ return pos_->index();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperProxy.h b/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperProxy.h
new file mode 100644
index 00000000..833268ef
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperProxy.h
@@ -0,0 +1,809 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uniuppermatrix/UniUpperProxy.h
+// \brief Header file for the UniUpperProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_UPPERPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_UPPERPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for upper unitriangular matrices.
+// \ingroup uniupper_matrix
+//
+// The UniUpperProxy provides controlled access to the elements of a non-const upper unitriangular
+// matrix. It guarantees that the uniupper matrix invariant is not violated, i.e. that elements
+// in the lower part of the matrix remain 0 and the diagonal elements remain 1. The following
+// example illustrates this by means of a \f$ 3 \times 3 \f$ dense upper unitriangular matrix:
+
+ \code
+ // Creating a 3x3 upper unitriangular dense matrix
+ blaze::UniUpperMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(0,1) = -2; // ( 1 -2 3 )
+ A(0,2) = 3; // => A = ( 0 1 5 )
+ A(1,2) = 5; // ( 0 0 1 )
+
+ A(1,1) = 4; // Invalid assignment to diagonal matrix element; results in an exception!
+ A(2,0) = 7; // Invalid assignment to lower matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class UniUpperProxy : public Proxy< UniUpperProxy<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Reference type of the underlying matrix type.
+ typedef typename MT::Reference ReferenceType;
+ //**********************************************************************************************
+
+ //**struct BuiltinType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct BuiltinType { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct ComplexType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct ComplexType { typedef typename T::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of the represented matrix element.
+ typedef ElementType_<MT> RepresentedType;
+
+ //! Value type of the represented complex element.
+ typedef typename If_< IsComplex<RepresentedType>
+ , ComplexType<RepresentedType>
+ , BuiltinType<RepresentedType> >::Type ValueType;
+
+ typedef ValueType value_type; //!< Value type of the represented complex element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UniUpperProxy( MT& matrix, size_t row, size_t column );
+ inline UniUpperProxy( const UniUpperProxy& uup );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline const UniUpperProxy& operator= ( const UniUpperProxy& uup ) const;
+ template< typename T > inline const UniUpperProxy& operator= ( const T& value ) const;
+ template< typename T > inline const UniUpperProxy& operator+=( const T& value ) const;
+ template< typename T > inline const UniUpperProxy& operator-=( const T& value ) const;
+ template< typename T > inline const UniUpperProxy& operator*=( const T& value ) const;
+ template< typename T > inline const UniUpperProxy& operator/=( const T& value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void reset () const;
+ inline void clear () const;
+ inline void invert() const;
+
+ inline RepresentedType get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RepresentedType() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Complex data access functions***************************************************************
+ /*!\name Complex data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ ReferenceType value_; //!< Reference to the accessed matrix element.
+ size_t row_; //!< Row index of the accessed matrix element.
+ size_t column_; //!< Column index of the accessed matrix element.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a UniUpperProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniUpperProxy<MT>::UniUpperProxy( MT& matrix, size_t row, size_t column )
+ : value_ ( matrix( row, column ) ) // Reference to the accessed matrix element
+ , row_ ( row ) // Row index of the accessed matrix element
+ , column_( column ) // Column index of the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for UniUpperProxy.
+//
+// \param uup Proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniUpperProxy<MT>::UniUpperProxy( const UniUpperProxy& uup )
+ : value_ ( uup.value_ ) // Reference to the accessed matrix element
+ , row_ ( uup.row_ ) // Row index of the accessed matrix element
+ , column_( uup.column_ ) // Column index of the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for UniUpperProxy.
+//
+// \param uup Proxy to be copied.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline const UniUpperProxy<MT>& UniUpperProxy<MT>::operator=( const UniUpperProxy& uup ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ = uup.value_;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniUpperProxy<MT>& UniUpperProxy<MT>::operator=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniUpperProxy<MT>& UniUpperProxy<MT>::operator+=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniUpperProxy<MT>& UniUpperProxy<MT>::operator-=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniUpperProxy<MT>& UniUpperProxy<MT>::operator*=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to diagonal or lower matrix element.
+//
+// In case the proxy represents an element on the diagonal or in the lower part of the matrix,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UniUpperProxy<MT>& UniUpperProxy<MT>::operator/=( const T& value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal or lower matrix element" );
+ }
+
+ value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reset the represented element to its default initial value.
+//
+// \return void
+//
+// This function resets the element represented by the proxy to its default initial value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperProxy<MT>::reset() const
+{
+ using blaze::reset;
+
+ if( row_ < column_ )
+ reset( value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+//
+// \return void
+//
+// This function clears the element represented by the proxy to its default initial state.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperProxy<MT>::clear() const
+{
+ using blaze::clear;
+
+ if( row_ < column_ )
+ clear( value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element
+//
+// \return void
+// \exception std::invalid_argument Invalid inversion of upper matrix element.
+//
+// In case the proxy represents a lower element, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperProxy<MT>::invert() const
+{
+ using blaze::invert;
+
+ if( column_ < row_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid inversion of lower matrix element" );
+ }
+
+ if( row_ < column_ )
+ invert( value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperProxy<MT>::RepresentedType UniUpperProxy<MT>::get() const noexcept
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted matrix element..
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool UniUpperProxy<MT>::isRestricted() const noexcept
+{
+ return column_ <= row_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniUpperProxy<MT>::operator RepresentedType() const noexcept
+{
+ return get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperProxy<MT>::ValueType UniUpperProxy<MT>::real() const
+{
+ return value_.real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal or lower matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its real part.
+// In case the represented value is a diagonal element or an element in the lower part of the
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperProxy<MT>::real( ValueType value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal or lower matrix element" );
+ }
+
+ value_.real( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperProxy<MT>::ValueType UniUpperProxy<MT>::imag() const
+{
+ return value_.imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal or lower matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its imaginary
+// part. In case the represented value is a diagonal element or an element in the lower part of
+// the matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperProxy<MT>::imag( ValueType value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal or lower matrix element" );
+ }
+
+ value_.imag( value );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UniUpperProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const UniUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const UniUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline void invert( const UniUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const UniUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const UniUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const UniUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const UniUpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const UniUpperProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup uniupper_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const UniUpperProxy<MT>& proxy )
+{
+ proxy.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup uniupper_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const UniUpperProxy<MT>& proxy )
+{
+ proxy.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element.
+// \ingroup uniupper_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+*/
+template< typename MT >
+inline void invert( const UniUpperProxy<MT>& proxy )
+{
+ proxy.invert();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup uniupper_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const UniUpperProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup uniupper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const UniUpperProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup uniupper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const UniUpperProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup uniupper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const UniUpperProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup uniupper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const UniUpperProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperValue.h b/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperValue.h
new file mode 100644
index 00000000..98d6ac88
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperValue.h
@@ -0,0 +1,753 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uniuppermatrix/UniUpperValue.h
+// \brief Header file for the UniUpperValue class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_UNIUPPERVALUE_H_
+#define _BLAZE_MATH_ADAPTORS_UNIUPPERMATRIX_UNIUPPERVALUE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Representation of a value within a sparse upper unitriangular matrix.
+// \ingroup uniupper_matrix
+//
+// The UniUpperValue class represents a single value within a sparse upper unitriangular matrix.
+// It guarantees that the uniupper matrix invariant is not violated, i.e. that elements in the
+// upper part of the matrix remain 0 and the diagonal elements remain 1. The following example
+// illustrates this by means of a \f$ 3 \times 3 \f$ sparse upper unitriangular matrix:
+
+ \code
+ typedef blaze::UniUpperMatrix< blaze::CompressedMatrix<int> > UniUpper;
+
+ // Creating a 3x3 upper unitriangular sparse matrix
+ UniUpper A( 3UL );
+
+ A(0,1) = -2; // ( 1 -2 3 )
+ A(0,2) = 3; // => A = ( 0 1 5 )
+ A(1,2) = 5; // ( 0 0 1 )
+
+ UniUpper::Iterator it = A.begin( 1UL );
+ it->value() = 9; // Invalid assignment to diagonal matrix element; results in an exception!
+ ++it;
+ it->value() = 4; // Modification of matrix element (1,2)
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class UniUpperValue : public Proxy< UniUpperValue<MT> >
+{
+ private:
+ //**struct BuiltinType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct BuiltinType { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct ComplexType**************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary struct to determine the value type of the represented complex element.
+ */
+ template< typename T >
+ struct ComplexType { typedef typename T::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+
+ //! Value type of the represented complex element.
+ typedef typename If_< IsComplex<RepresentedType>
+ , ComplexType<RepresentedType>
+ , BuiltinType<RepresentedType> >::Type ValueType;
+
+ typedef ValueType value_type; //!< Value type of the represented complex element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline UniUpperValue( RepresentedType& value, bool diagonal );
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline UniUpperValue& operator= ( const UniUpperValue& uuv );
+ template< typename T > inline UniUpperValue& operator= ( const T& value );
+ template< typename T > inline UniUpperValue& operator+=( const T& value );
+ template< typename T > inline UniUpperValue& operator-=( const T& value );
+ template< typename T > inline UniUpperValue& operator*=( const T& value );
+ template< typename T > inline UniUpperValue& operator/=( const T& value );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void reset () const;
+ inline void clear () const;
+ inline void invert() const;
+
+ inline RepresentedType get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RepresentedType() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Complex data access functions***************************************************************
+ /*!\name Complex data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ RepresentedType* value_; //!< The represented value.
+ bool diagonal_; //!< \a true in case the element is on the diagonal, \a false if not.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( RepresentedType );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the UniUpperValue class.
+//
+// \param value Reference to the represented value.
+// \param diagonal \a true in case the element is on the diagonal, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniUpperValue<MT>::UniUpperValue( RepresentedType& value, bool diagonal )
+ : value_ ( &value ) // The represented value.
+ , diagonal_( diagonal ) // true in case the element is on the diagonal, false if not
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for UniUpperValue.
+//
+// \param uuv The uniupper value to be copied.
+// \return Reference to the assigned uniupper value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniUpperValue<MT>& UniUpperValue<MT>::operator=( const UniUpperValue& uuv )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ = *uuv.value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the uniupper value.
+//
+// \param value The new value of the uniupper value.
+// \return Reference to the assigned uniupper value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperValue<MT>& UniUpperValue<MT>::operator=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the uniupper value.
+//
+// \param value The right-hand side value to be added to the uniupper value.
+// \return Reference to the assigned uniupper value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperValue<MT>& UniUpperValue<MT>::operator+=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the uniupper value.
+//
+// \param value The right-hand side value to be subtracted from the uniupper value.
+// \return Reference to the assigned uniupper value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperValue<MT>& UniUpperValue<MT>::operator-=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the uniupper value.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned uniupper value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperValue<MT>& UniUpperValue<MT>::operator*=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the uniupper value.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned uniupper value.
+// \exception std::invalid_argument Invalid assignment to diagonal matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline UniUpperValue<MT>& UniUpperValue<MT>::operator/=( const T& value )
+{
+ if( diagonal_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix element" );
+ }
+
+ *value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reset the uniupper value to its default initial value.
+//
+// \return void
+//
+// This function resets the uniupper value to its default initial value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperValue<MT>::reset() const
+{
+ using blaze::reset;
+
+ if( !diagonal_ )
+ reset( *value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the uniupper value.
+//
+// \return void
+//
+// This function clears the uniupper value to its default initial state.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperValue<MT>::clear() const
+{
+ using blaze::clear;
+
+ if( !diagonal_ )
+ clear( *value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the uniupper value
+//
+// \return void
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperValue<MT>::invert() const
+{
+ using blaze::invert;
+
+ if( !diagonal_ )
+ invert( *value_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the represented value.
+//
+// \return Copy of the represented value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperValue<MT>::RepresentedType UniUpperValue<MT>::get() const noexcept
+{
+ return *value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the value represents a restricted matrix element..
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool UniUpperValue<MT>::isRestricted() const noexcept
+{
+ return diagonal_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the represented value.
+//
+// \return Copy of the represented value.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UniUpperValue<MT>::operator RepresentedType() const noexcept
+{
+ return *value_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperValue<MT>::ValueType UniUpperValue<MT>::real() const
+{
+ return value_->real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its real part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperValue<MT>::real( ValueType value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal matrix element" );
+ }
+
+ value_->real( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// In case the proxy represents a complex number, this function returns the current value of its
+// imaginary part.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UniUpperValue<MT>::ValueType UniUpperValue<MT>::imag() const
+{
+ return value_->imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+// \exception std::invalid_argument Invalid setting for diagonal matrix element.
+//
+// In case the proxy represents a complex number, this function sets a new value to its imaginary
+// part. In case the proxy represents a diagonal element and the given value is not zero, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline void UniUpperValue<MT>::imag( ValueType value ) const
+{
+ if( isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setting for diagonal matrix element" );
+ }
+
+ value_->imag( value );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UniUpperValue global functions */
+//@{
+template< typename MT >
+inline void reset( const UniUpperValue<MT>& value );
+
+template< typename MT >
+inline void clear( const UniUpperValue<MT>& value );
+
+template< typename MT >
+inline void invert( const UniUpperValue<MT>& value );
+
+template< typename MT >
+inline bool isDefault( const UniUpperValue<MT>& value );
+
+template< typename MT >
+inline bool isReal( const UniUpperValue<MT>& value );
+
+template< typename MT >
+inline bool isZero( const UniUpperValue<MT>& value );
+
+template< typename MT >
+inline bool isOne( const UniUpperValue<MT>& value );
+
+template< typename MT >
+inline bool isnan( const UniUpperValue<MT>& value );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the uniupper value to the default initial values.
+// \ingroup uniupper_matrix
+//
+// \param value The given uniupper value.
+// \return void
+//
+// This function resets the uniupper value to its default initial value.
+*/
+template< typename MT >
+inline void reset( const UniUpperValue<MT>& value )
+{
+ value.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the uniupper value.
+// \ingroup uniupper_matrix
+//
+// \param value The given uniupper value.
+// \return void
+//
+// This function clears the uniupper value to its default initial state.
+*/
+template< typename MT >
+inline void clear( const UniUpperValue<MT>& value )
+{
+ value.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the uniupper value.
+// \ingroup uniupper_matrix
+//
+// \param value The given uniupper value.
+// \return void
+*/
+template< typename MT >
+inline void invert( const UniUpperValue<MT>& value )
+{
+ value.invert();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the uniupper value is in default state.
+// \ingroup uniupper_matrix
+//
+// \param value The given uniupper value.
+// \return \a true in case the uniupper value is in default state, \a false otherwise.
+//
+// This function checks whether the uniupper value is in default state. In case it is in
+// default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const UniUpperValue<MT>& value )
+{
+ using blaze::isDefault;
+
+ return isDefault( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the uniupper value represents a real number.
+// \ingroup uniupper_matrix
+//
+// \param value The given uniupper value.
+// \return \a true in case the uniupper value represents a real number, \a false otherwise.
+//
+// This function checks whether the uniupper value represents the a real number. In case the
+// value is of built-in type, the function returns \a true. In case the element is of complex
+// type, the function returns \a true if the imaginary part is equal to 0. Otherwise it returns
+// \a false.
+*/
+template< typename MT >
+inline bool isReal( const UniUpperValue<MT>& value )
+{
+ using blaze::isReal;
+
+ return isReal( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the uniupper value is 0.
+// \ingroup uniupper_matrix
+//
+// \param value The given uniupper value.
+// \return \a true in case the uniupper value is 0, \a false otherwise.
+//
+// This function checks whether the uniupper value represents the numeric value 0. In case it
+// is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const UniUpperValue<MT>& value )
+{
+ using blaze::isZero;
+
+ return isZero( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the uniupper value is 1.
+// \ingroup uniupper_matrix
+//
+// \param value The given uniupper value.
+// \return \a true in case the uniupper value is 1, \a false otherwise.
+//
+// This function checks whether the uniupper value represents the numeric value 1. In case it
+// is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const UniUpperValue<MT>& value )
+{
+ using blaze::isOne;
+
+ return isOne( value.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the uniupper value is not a number.
+// \ingroup uniupper_matrix
+//
+// \param value The given uniupper value.
+// \return \a true in case the uniupper value is in not a number, \a false otherwise.
+//
+// This function checks whether the uniupper value is not a number (NaN). In case it is not a
+// number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const UniUpperValue<MT>& value )
+{
+ using blaze::isnan;
+
+ return isnan( value.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uppermatrix/BaseTemplate.h b/src/cpu/blaze/math/adaptors/uppermatrix/BaseTemplate.h
new file mode 100644
index 00000000..c1856ea6
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uppermatrix/BaseTemplate.h
@@ -0,0 +1,555 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uppermatrix/BaseTemplate.h
+// \brief Header file for the implementation of the base template of the UpperMatrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UPPERMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_ADAPTORS_UPPERMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup upper_matrix UpperMatrix
+// \ingroup adaptors
+*/
+/*!\brief Matrix adapter for upper triangular \f$ N \times N \f$ matrices.
+// \ingroup upper_matrix
+//
+// \section uppermatrix_general General
+//
+// The UpperMatrix class template is an adapter for existing dense and sparse matrix types. It
+// inherits the properties and the interface of the given matrix type \a MT and extends it by
+// enforcing the additional invariant that all matrix elements below the diagonal are 0 (upper
+// triangular matrix). The type of the adapted matrix can be specified via the first template
+// parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF >
+ class UpperMatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix to be adapted. UpperMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer, non-expression dense or sparse matrix
+// type. Note that the given matrix type must be either resizable (as for instance
+// HybridMatrix or DynamicMatrix) or must be square at compile time (as for instance
+// StaticMatrix).
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+// The following examples give an impression of several possible upper matrices:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x3 row-major dense upper matrix with static memory
+ blaze::UpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+
+ // Definition of a resizable column-major dense upper matrix based on HybridMatrix
+ blaze::UpperMatrix< blaze::HybridMatrix<float,4UL,4UL,columnMajor> B;
+
+ // Definition of a resizable row-major dense upper matrix based on DynamicMatrix
+ blaze::UpperMatrix< blaze::DynamicMatrix<double,rowMajor> > C;
+
+ // Definition of a fixed-size row-major dense upper matrix based on CustomMatrix
+ blaze::UpperMatrix< blaze::CustomMatrix<double,unaligned,unpadded,rowMajor> > D;
+
+ // Definition of a compressed row-major single precision upper matrix
+ blaze::UpperMatrix< blaze::CompressedMatrix<float,rowMajor> > E;
+ \endcode
+
+// The storage order of an upper matrix is depending on the storage order of the adapted matrix
+// type \a MT. In case the adapted matrix is stored in a row-wise fashion (i.e. is specified
+// as blaze::rowMajor), the upper matrix will also be a row-major matrix. Otherwise, if the
+// adapted matrix is column-major (i.e. is specified as blaze::columnMajor), the upper matrix
+// will also be a column-major matrix.
+//
+//
+// \n \section uppermatrix_special_properties Special Properties of Upper Triangular Matrices
+//
+// An upper matrix is used exactly like a matrix of the underlying, adapted matrix type \a MT. It
+// also provides (nearly) the same interface as the underlying matrix type. However, there are
+// some important exceptions resulting from the upper matrix constraint:
+//
+// -# <b>\ref uppermatrix_square</b>
+// -# <b>\ref uppermatrix_upper</b>
+// -# <b>\ref uppermatrix_initialization</b>
+// -# <b>\ref uppermatrix_storage</b>
+//
+// \n \subsection uppermatrix_square Upper Matrices Must Always be Square!
+//
+// In case a resizable matrix is used (as for instance blaze::HybridMatrix, blaze::DynamicMatrix,
+// or blaze::CompressedMatrix), this means that the according constructors, the \c resize() and
+// the \c extend() functions only expect a single parameter, which specifies both the number of
+// rows and columns, instead of two (one for the number of rows and one for the number of columns):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UpperMatrix;
+ using blaze::rowMajor;
+
+ // Default constructed, default initialized, row-major 3x3 upper dynamic matrix
+ UpperMatrix< DynamicMatrix<double,rowMajor> > A( 3 );
+
+ // Resizing the matrix to 5x5
+ A.resize( 5 );
+
+ // Extending the number of rows and columns by 2, resulting in a 7x7 matrix
+ A.extend( 2 );
+ \endcode
+
+// In case a matrix with a fixed size is used (as for instance blaze::StaticMatrix), the number
+// of rows and number of columns must be specified equally:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::UpperMatrix;
+ using blaze::columnMajor;
+
+ // Correct setup of a fixed size column-major 3x3 upper static matrix
+ UpperMatrix< StaticMatrix<int,3UL,3UL,columnMajor> > A;
+
+ // Compilation error: the provided matrix type is not a square matrix type
+ UpperMatrix< StaticMatrix<int,3UL,4UL,columnMajor> > B;
+ \endcode
+
+// \n \subsection uppermatrix_upper The Upper Matrix Property is Always Enforced!
+//
+// This means that it is only allowed to modify elements in the upper part or the diagonal of
+// the matrix, but not the elements in the lower part of the matrix. Also, it is only possible
+// to assign matrices that are upper matrices themselves:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::StaticMatrix;
+ using blaze::UpperMatrix;
+ using blaze::rowMajor;
+
+ typedef UpperMatrix< CompressedMatrix<double,rowMajor> > CompressedUpper;
+
+ // Default constructed, row-major 3x3 upper compressed matrix
+ CompressedUpper A( 3 );
+
+ // Initializing elements via the function call operator
+ A(0,0) = 1.0; // Initialization of the diagonal element (0,0)
+ A(0,2) = 2.0; // Initialization of the upper element (0,2)
+ A(2,1) = 9.0; // Throws an exception; invalid modification of lower element
+
+ // Inserting two more elements via the insert() function
+ A.insert( 0, 1, 3.0 ); // Inserting the upper element (0,1)
+ A.insert( 1, 1, 4.0 ); // Inserting the diagonal element (1,1)
+ A.insert( 2, 0, 9.0 ); // Throws an exception; invalid insertion of lower element
+
+ // Appending an element via the append() function
+ A.reserve( 1, 3 ); // Reserving enough capacity in row 1
+ A.append( 1, 2, 5.0 ); // Appending the upper element (1,2)
+ A.append( 2, 1, 9.0 ); // Throws an exception; appending an element in the lower part
+
+ // Access via a non-const iterator
+ CompressedUpper::Iterator it = A.begin(1);
+ *it = 9.0; // Modifies the diagonal element (1,1)
+ ++it;
+ *it = 6.0; // Modifies the upper element (1,2)
+
+ // Erasing elements via the erase() function
+ A.erase( 0, 0 ); // Erasing the diagonal element (0,0)
+ A.erase( 0, 2 ); // Erasing the upper element (0,2)
+
+ // Construction from an upper dense matrix
+ StaticMatrix<double,3UL,3UL> B( { { 3.0, 8.0, -2.0 },
+ { 0.0, 0.0, -1.0 },
+ { 0.0, 0.0, 4.0 } } );
+
+ UpperMatrix< DynamicMatrix<double,rowMajor> > C( B ); // OK
+
+ // Assignment of a non-upper dense matrix
+ StaticMatrix<double,3UL,3UL> D( { { 3.0, 8.0, -2.0 },
+ { 0.0, 0.0, -1.0 },
+ { -2.0, 0.0, 4.0 } } );
+
+ C = D; // Throws an exception; upper matrix invariant would be violated!
+ \endcode
+
+// The upper matrix property is also enforced for upper custom matrices: In case the given array
+// of elements does not represent a upper matrix, a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::UpperMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ typedef UpperMatrix< CustomMatrix<double,unaligned,unpadded,rowMajor> > CustomUpper;
+
+ // Creating a 3x3 upper custom matrix from a properly initialized array
+ double array[9] = { 1.0, 2.0, 3.0,
+ 0.0, 4.0, 5.0,
+ 0.0, 0.0, 6.0 };
+ CustomUpper A( array, 3UL ); // OK
+
+ // Attempt to create a second 3x3 upper custom matrix from an uninitialized array
+ CustomUpper B( new double[9UL], 3UL, blaze::ArrayDelete() ); // Throws an exception
+ \endcode
+
+// Finally, the upper matrix property is enforced for views (rows, columns, submatrices, ...) on
+// the upper matrix. The following example demonstrates that modifying the elements of an entire
+// row and submatrix of an upper matrix only affects the upper and diagonal matrix elements:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UpperMatrix;
+
+ // Setup of the upper matrix
+ //
+ // ( 0 1 0 4 )
+ // A = ( 0 2 3 0 )
+ // ( 0 0 0 5 )
+ // ( 0 0 0 0 )
+ //
+ UpperMatrix< DynamicMatrix<int> > A( 4 );
+ A(0,1) = 1;
+ A(0,3) = 4;
+ A(1,1) = 2;
+ A(1,2) = 3;
+ A(2,3) = 5;
+
+ // Setting the upper and diagonal elements in the 1st row to 9 results in the matrix
+ //
+ // ( 0 1 0 4 )
+ // A = ( 0 9 9 9 )
+ // ( 0 0 0 5 )
+ // ( 0 0 0 0 )
+ //
+ row( A, 1 ) = 9;
+
+ // Setting the upper and diagonal elements in the 1st and 2nd column to 7 results in
+ //
+ // ( 0 7 7 4 )
+ // A = ( 0 7 7 9 )
+ // ( 0 0 7 5 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A, 0, 1, 4, 2 ) = 7;
+ \endcode
+
+// The next example demonstrates the (compound) assignment to rows/columns and submatrices of
+// upper matrices. Since only upper and diagonal elements may be modified the matrix to be
+// assigned must be structured such that the upper matrix invariant of the upper matrix is
+// preserved. Otherwise a \a std::invalid_argument exception is thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::UpperMatrix;
+ using blaze::rowVector;
+
+ // Setup of two default 4x4 upper matrices
+ UpperMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of a 4-dimensional vector
+ //
+ // v = ( 0 1 2 3 )
+ //
+ DynamicVector<int,rowVector> v( 4, 0 );
+ v[1] = 1;
+ v[2] = 2;
+ v[3] = 3;
+
+ // OK: Assigning v to the 1st row of A1 preserves the upper matrix invariant
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 1 2 3 )
+ // ( 0 0 0 0 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 1 ) = v; // OK
+
+ // Error: Assigning v to the 2nd row of A1 violates the upper matrix invariant! The element
+ // marked with X cannot be assigned and triggers an exception.
+ //
+ // ( 0 0 0 0 )
+ // A1 = ( 0 1 2 3 )
+ // ( 0 X 2 3 )
+ // ( 0 0 0 0 )
+ //
+ row( A1, 2 ) = v; // Assignment throws an exception!
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 7 8 )
+ // B = ( 0 9 )
+ // ( 0 0 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL, 0 );
+ B(0,0) = 7;
+ B(0,1) = 8;
+ B(1,1) = 9;
+
+ // OK: Assigning B to a submatrix of A2 such that the upper matrix invariant can be preserved
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( 0 7 8 0 )
+ // ( 0 0 9 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 1UL, 1UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the upper matrix invariant cannot be
+ // preserved! The elements marked with X cannot be assigned without violating the invariant!
+ //
+ // ( 0 0 0 0 )
+ // A2 = ( X 8 8 0 )
+ // ( 0 X 9 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 1UL, 0UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+
+// \n \subsection uppermatrix_initialization The Lower Elements of a Dense Upper Matrix are Always Default Initialized!
+//
+// Although this results in a small loss of efficiency during the creation of a dense upper matrix
+// this initialization is important since otherwise the upper matrix property of dense upper
+// matrices would not be guaranteed:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UpperMatrix;
+
+ // Uninitialized, 5x5 row-major dynamic matrix
+ DynamicMatrix<int,rowMajor> A( 5, 5 );
+
+ // 5x5 row-major upper dynamic matrix with default initialized lower matrix
+ UpperMatrix< DynamicMatrix<int,rowMajor> > B( 5 );
+ \endcode
+
+// \n \subsection uppermatrix_storage Dense Upper Matrices Also Store the Lower Elements!
+//
+// It is important to note that dense upper matrices store all elements, including the elements
+// in the lower part of the matrix, and therefore don't provide any kind of memory reduction!
+// There are two main reasons for this: First, storing also the lower elements guarantees maximum
+// performance for many algorithms that perform vectorized operations on the upper matrix, which
+// is especially true for small dense matrices. Second, conceptually the UpperMatrix adaptor
+// merely restricts the interface to the matrix type \a MT and does not change the data layout
+// or the underlying matrix type.
+//
+//
+// \n \section uppermatrix_arithmetic_operations Arithmetic Operations
+//
+// An UpperMatrix matrix can participate in numerical operations in any way any other dense or
+// sparse matrix can participate. It can also be combined with any other dense or sparse vector
+// or matrix. The following code example gives an impression of the use of UpperMatrix within
+// arithmetic operations:
+
+ \code
+ using blaze::UpperMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::HybridMatrix;
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 3, 3 );
+ CompressedMatrix<double,rowMajor> B( 3, 3 );
+
+ UpperMatrix< DynamicMatrix<double,rowMajor> > C( 3 );
+ UpperMatrix< CompressedMatrix<double,rowMajor> > D( 3 );
+
+ UpperMatrix< HybridMatrix<float,3UL,3UL,rowMajor> > E;
+ UpperMatrix< StaticMatrix<float,3UL,3UL,columnMajor> > F;
+
+ E = A + B; // Matrix addition and assignment to a row-major upper matrix
+ F = C - D; // Matrix subtraction and assignment to a column-major upper matrix
+ F = A * D; // Matrix multiplication between a dense and a sparse matrix
+
+ C *= 2.0; // In-place scaling of matrix C
+ E = 2.0 * B; // Scaling of matrix B
+ F = C * 2.0; // Scaling of matrix C
+
+ E += A - B; // Addition assignment
+ F -= C + D; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+
+// \n \section uppermatrix_block_structured Block-Structured Upper Matrices
+//
+// It is also possible to use block-structured upper matrices:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::StaticMatrix;
+ using blaze::UpperMatrix;
+
+ // Definition of a 5x5 block-structured upper matrix based on CompressedMatrix
+ UpperMatrix< CompressedMatrix< StaticMatrix<int,3UL,3UL> > > A( 5 );
+ \endcode
+
+// Also in this case the upper matrix invariant is enforced, i.e. it is not possible to manipulate
+// elements in the lower part of the matrix:
+
+ \code
+ const StaticMatrix<int,3UL,3UL> B( { { 1, -4, 5 },
+ { 6, 8, -3 },
+ { 2, -1, 2 } } )
+
+ A.insert( 2, 4, B ); // Inserting the elements (2,4)
+ A(4,2)(1,1) = -5; // Invalid manipulation of lower matrix element; Results in an exception
+ \endcode
+
+// \n \section uppermatrix_performance Performance Considerations
+//
+// The \b Blaze library tries to exploit the properties of upper matrices whenever and wherever
+// possible. Thus using an upper triangular matrix instead of a general matrix can result in a
+// considerable performance improvement. However, there are also situations when using an upper
+// triangular matrix introduces some overhead. The following examples demonstrate several common
+// situations where upper matrices can positively or negatively impact performance.
+//
+// \n \subsection uppermatrix_matrix_matrix_multiplication Positive Impact: Matrix/Matrix Multiplication
+//
+// When multiplying two matrices, at least one of which is upper triangular, \b Blaze can exploit
+// the fact that the lower part of the matrix contains only default elements and restrict the
+// algorithm to the upper and diagonal elements. The following example demonstrates this by means
+// of a dense matrix/dense matrix multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UpperMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ UpperMatrix< DynamicMatrix<double,rowMajor> > A;
+ UpperMatrix< DynamicMatrix<double,columnMajor> > B;
+ DynamicMatrix<double,columnMajor> C;
+
+ // ... Resizing and initialization
+
+ C = A * B;
+ \endcode
+
+// In comparison to a general matrix multiplication, the performance advantage is significant,
+// especially for large matrices. Therefore is it highly recommended to use the UpperMatrix
+// adaptor when a matrix is known to be upper triangular. Note however that the performance
+// advantage is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection uppermatrix_matrix_vector_multiplication Positive Impact: Matrix/Vector Multiplication
+//
+// A similar performance improvement can be gained when using an upper matrix in a matrix/vector
+// multiplication:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::UpperMatrix;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ UpperMatrix< DynamicMatrix<double,rowMajor> > A;
+ DynamicVector<double,columnVector> x, y;
+
+ // ... Resizing and initialization
+
+ y = A * x;
+ \endcode
+
+// In this example, \b Blaze also exploits the structure of the matrix and approx. halves the
+// runtime of the multiplication. Also in case of matrix/vector multiplications the performance
+// improvement is most pronounced for dense matrices and much less so for sparse matrices.
+//
+// \n \subsection uppermatrix_assignment Negative Impact: Assignment of a General Matrix
+//
+// In contrast to using an upper triangular matrix on the right-hand side of an assignment (i.e.
+// for read access), which introduces absolutely no performance penalty, using an upper matrix on
+// the left-hand side of an assignment (i.e. for write access) may introduce additional overhead
+// when it is assigned a general matrix, which is not upper triangular at compile time:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::UpperMatrix;
+
+ UpperMatrix< DynamicMatrix<double> > A, C;
+ DynamicMatrix<double> B;
+
+ B = A; // Only read-access to the upper matrix; no performance penalty
+ C = A; // Assignment of an upper matrix to another upper matrix; no runtime overhead
+ C = B; // Assignment of a general matrix to an upper matrix; some runtime overhead
+ \endcode
+
+// When assigning a general, potentially not upper matrix to an upper matrix it is necessary to
+// check whether the matrix is upper at runtime in order to guarantee the upper triangular property
+// of the upper matrix. In case it turns out to be upper triangular, it is assigned as efficiently
+// as possible, if it is not, an exception is thrown. In order to prevent this runtime overhead it
+// is therefore generally advisable to assign upper matrices to other upper matrices.\n
+// In this context it is especially noteworthy that the addition, subtraction, and multiplication
+// of two upper triangular matrices always results in another upper matrix:
+
+ \code
+ UpperMatrix< DynamicMatrix<double> > A, B, C;
+
+ C = A + B; // Results in an upper matrix; no runtime overhead
+ C = A - B; // Results in an upper matrix; no runtime overhead
+ C = A * B; // Results in an upper matrix; no runtime overhead
+ \endcode
+*/
+template< typename MT // Type of the adapted matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order of the adapted matrix
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class UpperMatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uppermatrix/Dense.h b/src/cpu/blaze/math/adaptors/uppermatrix/Dense.h
new file mode 100644
index 00000000..c7c7b9b0
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uppermatrix/Dense.h
@@ -0,0 +1,2739 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uppermatrix/Dense.h
+// \brief UpperMatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UPPERMATRIX_DENSE_H_
+#define _BLAZE_MATH_ADAPTORS_UPPERMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/uppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/uppermatrix/UpperProxy.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/Square.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/dense/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of UpperMatrix for dense matrices.
+// \ingroup upper_matrix
+//
+// This specialization of UpperMatrix adapts the class template to the requirements of dense
+// matrices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+class UpperMatrix<MT,SO,true>
+ : public DenseMatrix< UpperMatrix<MT,SO,true>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the dense matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef UpperMatrix<MT,SO,true> This; //!< Type of this UpperMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this UpperMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef UpperMatrix<OT,!SO,true> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef LowerMatrix<TT,!SO,true> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef SIMDType_<MT> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef UpperProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain an UpperMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other UpperMatrix.
+ typedef UpperMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Iterator class definition*******************************************************************
+ /*!\brief Iterator over the non-constant elements of the dense upper matrix.
+ */
+ class Iterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType_<MT> ValueType; //!< Type of the underlying elements.
+ typedef UpperProxy<MT> PointerType; //!< Pointer return type.
+ typedef UpperProxy<MT> ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the Iterator class.
+ */
+ inline Iterator() noexcept
+ : matrix_( nullptr ) // Reference to the adapted dense matrix
+ , row_ ( 0UL ) // The current row index of the iterator
+ , column_( 0UL ) // The current column index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Iterator class.
+ //
+ // \param matrix The adapted matrix.
+ // \param row Initial row index of the iterator.
+ // \param column Initial column index of the iterator.
+ */
+ inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // Reference to the adapted dense matrix
+ , row_ ( row ) // The current row-index of the iterator
+ , column_( column ) // The current column-index of the iterator
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline Iterator& operator+=( size_t inc ) noexcept {
+ ( SO )?( row_ += inc ):( column_ += inc );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline Iterator& operator-=( size_t dec ) noexcept {
+ ( SO )?( row_ -= dec ):( column_ -= dec );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline Iterator& operator++() noexcept {
+ ( SO )?( ++row_ ):( ++column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator++( int ) noexcept {
+ const Iterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline Iterator& operator--() noexcept {
+ ( SO )?( --row_ ):( --column_ );
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const Iterator operator--( int ) noexcept {
+ const Iterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline PointerType operator->() const {
+ return PointerType( *matrix_, row_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element at the current iterator
+ // position. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return (*matrix_).load(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return (*matrix_).loada(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element at the current iterator position.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element at the current
+ // iterator position. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ return (*matrix_).loadu(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Conversion operator**********************************************************************
+ /*!\brief Conversion to an iterator over constant elements.
+ //
+ // \return An iterator over constant elements.
+ */
+ inline operator ConstIterator() const {
+ if( SO )
+ return matrix_->begin( column_ ) + row_;
+ else
+ return matrix_->begin( row_ ) + column_;
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs == ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a Iterator and ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) != rhs );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between a ConstIterator and Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs != ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) < rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs < ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) > rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs > ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) <= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between a ConstIterator and a Iterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs <= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
+ return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between a Iterator and a ConstIterator.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
+ return ( ConstIterator( lhs ) >= rhs );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two Iterator objects.
+ //
+ // \param lhs The left-hand side iterator.
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
+ return ( lhs >= ConstIterator( rhs ) );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
+ return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a Iterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a Iterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a Iterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
+ if( SO )
+ return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
+ else
+ return Iterator( *it.matrix_, it.row_, it.column_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MT* matrix_; //!< Reference to the adapted dense matrix.
+ size_t row_; //!< The current row-index of the iterator.
+ size_t column_; //!< The current column-index of the iterator.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UpperMatrix();
+ template< typename A1 > explicit inline UpperMatrix( const A1& a1 );
+ explicit inline UpperMatrix( size_t n, const ElementType& init );
+
+ explicit inline UpperMatrix( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other >
+ explicit inline UpperMatrix( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline UpperMatrix( const Other (&array)[N][N] );
+
+ explicit inline UpperMatrix( ElementType* ptr, size_t n );
+ explicit inline UpperMatrix( ElementType* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline UpperMatrix( ElementType* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline UpperMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d );
+
+ inline UpperMatrix( const UpperMatrix& m );
+ inline UpperMatrix( UpperMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline ConstPointer data () const noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline UpperMatrix& operator=( const ElementType& rhs );
+ inline UpperMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+
+ template< typename Other, size_t N >
+ inline UpperMatrix& operator=( const Other (&array)[N][N] );
+
+ inline UpperMatrix& operator=( const UpperMatrix& rhs );
+ inline UpperMatrix& operator=( UpperMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UpperMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UpperMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UpperMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UpperMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UpperMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UpperMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline UpperMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, UpperMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, UpperMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t n, bool preserve=true );
+ inline void extend ( size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ template< typename Other > inline UpperMatrix& scale( const Other& scalar );
+ inline void swap( UpperMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ inline const MT construct( size_t n , TrueType );
+ inline const MT construct( const ElementType& value, FalseType );
+
+ template< typename MT2, bool SO2, typename T >
+ inline const MT construct( const Matrix<MT2,SO2>& m, T );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted dense matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend bool isDefault( const UpperMatrix<MT2,SO2,DF2>& m );
+
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( UpperMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for UpperMatrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>::UpperMatrix()
+ : matrix_() // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Single argument constructor for an upper matrix.
+//
+// \param a1 The single constructor argument.
+// \exception std::invalid_argument Invalid setup of upper matrix.
+//
+// This constructor constructs the upper matrix based on the given argument and the type of
+// the underlying matrix \a MT:
+// - in case the given argument is a matrix, the upper matrix is initialized as a copy of
+// the given matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// resizable, the given argument \a a1 specifies the number of rows and columns of the
+// upper matrix.
+// - in case the given argument is not a matrix and the underlying matrix of type \a MT is
+// a matrix with fixed size, the given argument \a a1 specifies the initial value of the
+// upper and diagonal elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename A1 > // Type of the constructor argument
+inline UpperMatrix<MT,SO,true>::UpperMatrix( const A1& a1 )
+ : matrix_( construct( a1, typename IsResizable<MT>::Type() ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a \f$ n \times n \f$ matrix with initialized upper and diagonal elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param init The initial value of the upper and diagonal matrix elements.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>::UpperMatrix( size_t n, const ElementType& init )
+ : matrix_( n, n, ElementType() ) // The adapted dense matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) = init;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=i; j<columns(); ++j )
+ matrix_(i,j) = init;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of upper matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the upper
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::UpperMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A{ { 1, 2, 3 },
+ { 0, 4 },
+ { 0, 0, 6 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all matrix elements are
+// initialized with the values from the given list. Missing values are initialized with default
+// values. In case the given list does not represent a diagonal matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>::UpperMatrix( initializer_list< initializer_list<ElementType> > list )
+ : matrix_( list ) // The adapted dense matrix
+{
+ if( !isUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all upper matrix elements.
+//
+// \param n The number of rows and columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid setup of upper matrix.
+//
+// This constructor offers the option to directly initialize the elements of the upper matrix
+// with a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[16];
+ // ... Initialization of the dynamic array
+ blaze::UpperMatrix< blaze::DynamicMatrix<int,rowMajor> > v( 4UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized accoring to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a n by
+// \a n elements. Providing an array with less elements results in undefined behavior! Also, in
+// case the given array does not represent a upper triangular matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the initialization array
+inline UpperMatrix<MT,SO,true>::UpperMatrix( size_t n, const Other* array )
+ : matrix_( n, n, array ) // The adapted dense matrix
+{
+ if( !isUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all upper matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the initialization.
+// \exception std::invalid_argument Invalid setup of upper matrix.
+//
+// This constructor offers the option to directly initialize the elements of the upper matrix
+// with a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 0, 4 },
+ { 0, 0, 6 } };
+ blaze::UpperMatrix< blaze::StaticMatrix<int,3,3,rowMajor> > A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the given array does not represent a lower triangular matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline UpperMatrix<MT,SO,true>::UpperMatrix( const Other (&array)[N][N] )
+ : matrix_( array ) // The adapted dense matrix
+{
+ if( !isUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for an upper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of upper custom matrix.
+//
+// This constructor creates an unpadded upper custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent an upper triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded upper custom matrices!
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>::UpperMatrix( ElementType* ptr, size_t n )
+ : matrix_( ptr, n, n ) // The adapted dense matrix
+{
+ if( !isUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for an upper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of upper custom matrix.
+//
+// This constructor creates an upper custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent an upper triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>::UpperMatrix( ElementType* ptr, size_t n, size_t nn )
+ : matrix_( ptr, n, n, nn ) // The adapted dense matrix
+{
+ if( !isUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for an upper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of upper custom matrix.
+//
+// This constructor creates an unpadded upper custom matrix of size \f$ n \times n \f$. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the values in the given array do not represent an upper triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded upper custom matrices!
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline UpperMatrix<MT,SO,true>::UpperMatrix( ElementType* ptr, size_t n, Deleter d )
+ : matrix_( ptr, n, n, d ) // The adapted dense matrix
+{
+ if( !isUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for an upper custom matrix of size \f$ n \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param n The number of rows and columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of upper custom matrix.
+//
+// This constructor creates an upper custom matrix of size \f$ n \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set;
+// - ... the values in the given array do not represent an upper triangular matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Deleter > // Type of the custom deleter
+inline UpperMatrix<MT,SO,true>::UpperMatrix( ElementType* ptr, size_t n, size_t nn, Deleter d )
+ : matrix_( ptr, n, n, nn, d ) // The adapted dense matrix
+{
+ if( !isUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for UpperMatrix.
+//
+// \param m The upper matrix to be copied.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>::UpperMatrix( const UpperMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for UpperMatrix.
+//
+// \param m The upper matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>::UpperMatrix( UpperMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::Reference
+ UpperMatrix<MT,SO,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::ConstReference
+ UpperMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::Reference
+ UpperMatrix<MT,SO,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::ConstReference
+ UpperMatrix<MT,SO,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the upper matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The upper matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::ConstPointer
+ UpperMatrix<MT,SO,true>::data() const noexcept
+{
+ return matrix_.data();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::ConstPointer
+ UpperMatrix<MT,SO,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the upper matrix adapts a \a rowMajor dense matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::Iterator
+ UpperMatrix<MT,SO,true>::begin( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, 0UL, i );
+ else
+ return Iterator( matrix_, i, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the upper matrix adapts a \a rowMajor dense matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::ConstIterator
+ UpperMatrix<MT,SO,true>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the upper matrix adapts a \a rowMajor dense matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::ConstIterator
+ UpperMatrix<MT,SO,true>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the upper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::Iterator
+ UpperMatrix<MT,SO,true>::end( size_t i )
+{
+ if( SO )
+ return Iterator( matrix_, rows(), i );
+ else
+ return Iterator( matrix_, i, columns() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the upper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::ConstIterator
+ UpperMatrix<MT,SO,true>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the upper matrix adapts a \a rowMajor dense matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline typename UpperMatrix<MT,SO,true>::ConstIterator
+ UpperMatrix<MT,SO,true>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all upper and diagonal matrix elements.
+//
+// \param rhs Scalar value to be assigned to the upper and diagonal matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>&
+ UpperMatrix<MT,SO,true>::operator=( const ElementType& rhs )
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ matrix_(i,j) = rhs;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=i; j<columns(); ++j )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the upper
+// matrix by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::UpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = { { 1, 2, 3 },
+ { 0, 4 },
+ { 0, 0, 6 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>&
+ UpperMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ MT tmp( list );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all upper matrix elements.
+//
+// \param array \f$ N \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// This assignment operator offers the option to directly set all elements of the upper matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 0, 4 },
+ { 0, 0, 6 } };
+ blaze::UpperMatrix< blaze::StaticMatrix<int,3UL,3UL,rowMajor> > A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values. In case the given array does not represent a upper triangular matrix, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other // Data type of the initialization array
+ , size_t N > // Number of rows and columns of the initialization array
+inline UpperMatrix<MT,SO,true>&
+ UpperMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
+{
+ MT tmp( array );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for UpperMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>&
+ UpperMatrix<MT,SO,true>::operator=( const UpperMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for UpperMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline UpperMatrix<MT,SO,true>&
+ UpperMatrix<MT,SO,true>::operator=( UpperMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// upper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,true>& >
+ UpperMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsUpper<MT2>::value && !isUpper( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// upper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,true>& >
+ UpperMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ if( IsUpper<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an upper
+// matrix, i.e. the given matrix must be an upper matrix. In case the result is not an upper
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,true>& >
+ UpperMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsUpper<MT2>::value && !isUpper( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an upper
+// matrix, i.e. the given matrix must be an upper matrix. In case the result is not an upper
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,true>& >
+ UpperMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ if( IsUpper<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// upper matrix, i.e. the given matrix must be an upper matrix. In case the result is not
+// an upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,true>& >
+ UpperMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsUpper<MT2>::value && !isUpper( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// upper matrix, i.e. the given matrix must be an upper matrix. In case the result is not
+// an upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,true>& >
+ UpperMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ if( IsUpper<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be an upper matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline UpperMatrix<MT,SO,true>&
+ UpperMatrix<MT,SO,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, UpperMatrix<MT,SO,true> >&
+ UpperMatrix<MT,SO,true>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, UpperMatrix<MT,SO,true> >&
+ UpperMatrix<MT,SO,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UpperMatrix<MT,SO,true>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UpperMatrix<MT,SO,true>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the total
+// number of elements of a row/column. In case the upper matrix adapts a \a rowMajor dense
+// matrix the function returns the spacing between two rows, in case it adapts a \a columnMajor
+// dense matrix the function returns the spacing between two columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UpperMatrix<MT,SO,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UpperMatrix<MT,SO,true>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the upper
+// matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor dense matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UpperMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the upper matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UpperMatrix<MT,SO,true>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the upper matrix adapts a \a rowMajor dense matrix the function returns the number
+// of non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix the
+// function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline size_t UpperMatrix<MT,SO,true>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UpperMatrix<MT,SO,true>::reset()
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ clear( matrix_(i,j) );
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=i; j<columns(); ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UpperMatrix<MT,SO,true>::reset( size_t i )
+{
+ using blaze::clear;
+
+ if( SO ) {
+ for( size_t j=0UL; j<=i; ++j )
+ clear( matrix_(j,i) );
+ }
+ else {
+ for( size_t j=i; j<columns(); ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the upper matrix.
+//
+// \return void
+//
+// This function clears the upper matrix and returns it to its default state. The function has
+// the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
+// matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
+// to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
+// be reset to their default state.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UpperMatrix<MT,SO,true>::clear()
+{
+ using blaze::clear;
+
+ if( IsResizable<MT>::value ) {
+ clear( matrix_ );
+ }
+ else {
+ reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the upper matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// In case the upper matrix adapts a resizable matrix, this function resizes the matrix using
+// the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
+// in case the capacity of the matrix is too small. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, the resize operation potentially changes all matrix elements. In order
+// to preserve the old matrix values, the \a preserve flag can be set to \a true. Also note that
+// in case the size of the matrix is increased, only the new elements in the lower part of the
+// matrix are default initialized.\n
+// The following example illustrates the resize operation of a \f$ 3 \times 3 \f$ matrix to a
+// \f$ 4 \times 4 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 0 & 4 & 5 \\
+ 0 & 0 & 6 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & x \\
+ 0 & 4 & 5 & x \\
+ 0 & 0 & 6 & x \\
+ 0 & 0 & 0 & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+void UpperMatrix<MT,SO,true>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+
+ const size_t oldsize( matrix_.rows() );
+
+ matrix_.resize( n, n, true );
+
+ if( n > oldsize ) {
+ const size_t increment( n - oldsize );
+ submatrix( matrix_, oldsize, 0UL, increment, n-1 ).reset();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param n Number of additional rows and columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a n rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. The new elements are default initialized.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UpperMatrix<MT,SO,true>::extend( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ UNUSED_PARAMETER( preserve );
+
+ resize( rows() + n, true );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the upper matrix.
+// \return void
+//
+// This function increases the capacity of the upper matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UpperMatrix<MT,SO,true>::reserve( size_t elements )
+{
+ matrix_.reserve( elements );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the scalar value
+inline UpperMatrix<MT,SO,true>& UpperMatrix<MT,SO,true>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UpperMatrix<MT,SO,true>::swap( UpperMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for an upper triangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for an upper triangular
+// matrix with fixed-size adapted matrix of type \a MT. Note that this function can only be
+// called in case the adapted dense matrix is a fixed-size matrix (as for instance StaticMatrix).
+// The attempt to call this function in case the adapted matrix is resizable matrix will result
+// in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UpperMatrix<MT,SO,true>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for an upper triangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for an upper triangular
+// matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UpperMatrix<MT,SO,true>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n + 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the upper matrix are intact.
+//
+// \return \a true in case the upper matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the upper matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UpperMatrix<MT,SO,true>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isUpper( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UpperMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UpperMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UpperMatrix<MT,SO,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline bool UpperMatrix<MT,SO,true>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the upper matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UpperMatrix<MT,SO,true>::SIMDType
+ UpperMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
+{
+ return matrix_.load( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the upper matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UpperMatrix<MT,SO,true>::SIMDType
+ UpperMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the upper matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+BLAZE_ALWAYS_INLINE typename UpperMatrix<MT,SO,true>::SIMDType
+ UpperMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ return matrix_.loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a resizable matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT UpperMatrix<MT,SO,true>::construct( size_t n, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ return MT( n, n, ElementType() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a fixed-size matrix with homogeneously initialized upper and diagonal elements.
+//
+// \param init The initial value of the upper and diagonal matrix elements.
+// \return The newly constructed matrix.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline const MT UpperMatrix<MT,SO,true>::construct( const ElementType& init, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SQUARE( MT );
+
+ MT tmp;
+
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ for( size_t i=0UL; i<=j; ++i )
+ tmp(i,j) = init;
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i )
+ for( size_t j=i; j<columns(); ++j )
+ tmp(i,j) = init;
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructing a matrix as a copy from another matrix.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of upper matrix.
+// \return The newly constructed matrix.
+//
+// In case the given matrix is not an upper matrix, a \a std::invalid_argument exception is
+// thrown.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 // Storage order of the foreign matrix
+ , typename T > // Type of the third argument
+inline const MT UpperMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
+{
+ const MT tmp( ~m );
+
+ if( !IsUpper<MT2>::value && !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ return tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uppermatrix/Sparse.h b/src/cpu/blaze/math/adaptors/uppermatrix/Sparse.h
new file mode 100644
index 00000000..43bc1b34
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uppermatrix/Sparse.h
@@ -0,0 +1,2071 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uppermatrix/Sparse.h
+// \brief UpperMatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UPPERMATRIX_SPARSE_H_
+#define _BLAZE_MATH_ADAPTORS_UPPERMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <vector>
+#include <blaze/math/adaptors/Forward.h>
+#include <blaze/math/adaptors/uppermatrix/BaseTemplate.h>
+#include <blaze/math/adaptors/uppermatrix/UpperProxy.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Resizable.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/sparse/SparseMatrix.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of UpperMatrix for sparse matrices.
+// \ingroup upper_matrix
+//
+// This specialization of UpperMatrix adapts the class template to the requirements of sparse
+// matrices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+class UpperMatrix<MT,SO,false>
+ : public SparseMatrix< UpperMatrix<MT,SO,false>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix.
+ typedef TransposeType_<MT> TT; //!< Transpose type of the sparse matrix.
+ typedef ElementType_<MT> ET; //!< Element type of the sparse matrix.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef UpperMatrix<MT,SO,false> This; //!< Type of this UpperMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this UpperMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef UpperMatrix<OT,!SO,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef LowerMatrix<TT,!SO,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ET ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef UpperProxy<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain an UpperMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ //! The type of the other UpperMatrix.
+ typedef UpperMatrix< typename MT::template Rebind<ET>::Other > Other;
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UpperMatrix();
+ explicit inline UpperMatrix( size_t n );
+ explicit inline UpperMatrix( size_t n, size_t nonzeros );
+ explicit inline UpperMatrix( size_t n, const std::vector<size_t>& nonzeros );
+
+ inline UpperMatrix( const UpperMatrix& m );
+ inline UpperMatrix( UpperMatrix&& m ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline UpperMatrix( const Matrix<MT2,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline UpperMatrix& operator=( const UpperMatrix& rhs );
+ inline UpperMatrix& operator=( UpperMatrix&& rhs ) noexcept;
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UpperMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UpperMatrix& > operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UpperMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UpperMatrix& > operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< IsComputation<MT2>, UpperMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< IsComputation<MT2>, UpperMatrix& > operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline UpperMatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, UpperMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, UpperMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void resize ( size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ inline void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ template< typename Other > inline UpperMatrix& scale( const Other& scalar );
+ template< typename Other > inline UpperMatrix& scaleDiagonal( Other scale );
+ inline void swap( UpperMatrix& m ) noexcept;
+
+ static inline constexpr size_t maxNonZeros() noexcept;
+ static inline constexpr size_t maxNonZeros( size_t n ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void resetLower();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT matrix_; //!< The adapted sparse matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2 >
+ friend bool isDefault( const UpperMatrix<MT2,SO2,DF2>& m );
+
+ template< typename MT2, bool SO2, bool DF2 >
+ friend MT2& derestrict( UpperMatrix<MT2,SO2,DF2>& m );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
+ BLAZE_STATIC_ASSERT( Rows<MT>::value == Columns<MT>::value );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for UpperMatrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UpperMatrix<MT,SO,false>::UpperMatrix()
+ : matrix_() // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+//
+// The matrix is initialized to the zero matrix and has no free capacity.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UpperMatrix<MT,SO,false>::UpperMatrix( size_t n )
+ : matrix_( n, n ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized to the zero matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UpperMatrix<MT,SO,false>::UpperMatrix( size_t n, size_t nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ n \times n \f$.
+//
+// \param n The number of rows and columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+//
+// The matrix is initialized to the zero matrix and will have the specified capacity in each
+// row/column. Note that in case of a row-major matrix the given vector must have at least
+// \a m elements, in case of a column-major matrix at least \a n elements.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UpperMatrix<MT,SO,false>::UpperMatrix( size_t n, const std::vector<size_t>& nonzeros )
+ : matrix_( n, n, nonzeros ) // The adapted sparse matrix
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for UpperMatrix.
+//
+// \param m The upper matrix to be copied.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UpperMatrix<MT,SO,false>::UpperMatrix( const UpperMatrix& m )
+ : matrix_( m.matrix_ ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for UpperMatrix.
+//
+// \param m The upper matrix to be moved into this instance.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UpperMatrix<MT,SO,false>::UpperMatrix( UpperMatrix&& m ) noexcept
+ : matrix_( std::move( m.matrix_ ) ) // The adapted sparse matrix
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of upper matrix.
+//
+// This constructor initializes the upper matrix as a copy of the given matrix. In case the
+// given matrix is not an upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline UpperMatrix<MT,SO,false>::UpperMatrix( const Matrix<MT2,SO2>& m )
+ : matrix_( ~m ) // The adapted sparse matrix
+{
+ if( !IsUpper<MT2>::value && !isUpper( matrix_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" );
+ }
+
+ if( !IsUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Reference
+ UpperMatrix<MT,SO,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return Reference( matrix_, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
+// contrast, the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstReference
+ UpperMatrix<MT,SO,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
+
+ return matrix_(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Reference
+ UpperMatrix<MT,SO,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// The function call operator provides access to the elements at position (i,j). The attempt to
+// assign to an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+//
+// Note that in contrast to the subscript operator this function always performs a check of the
+// given access indices.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstReference
+ UpperMatrix<MT,SO,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::begin( size_t i )
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstIterator
+ UpperMatrix<MT,SO,false>::begin( size_t i ) const
+{
+ return matrix_.begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator to the
+// first element of row \a i, in case it adapts a \a columnMajor sparse matrix the function
+// returns an iterator to the first element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstIterator
+ UpperMatrix<MT,SO,false>::cbegin( size_t i ) const
+{
+ return matrix_.cbegin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::end( size_t i )
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstIterator
+ UpperMatrix<MT,SO,false>::end( size_t i ) const
+{
+ return matrix_.end(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the upper matrix adapts a \a rowMajor sparse matrix the function returns an iterator
+// just past the last element of row \a i, in case it adapts a \a columnMajor sparse matrix the
+// function returns an iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstIterator
+ UpperMatrix<MT,SO,false>::cend( size_t i ) const
+{
+ return matrix_.cend(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for UpperMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UpperMatrix<MT,SO,false>&
+ UpperMatrix<MT,SO,false>::operator=( const UpperMatrix& rhs )
+{
+ matrix_ = rhs.matrix_;
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for UpperMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline UpperMatrix<MT,SO,false>&
+ UpperMatrix<MT,SO,false>::operator=( UpperMatrix&& rhs ) noexcept
+{
+ matrix_ = std::move( rhs.matrix_ );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for general matrices.
+//
+// \param rhs The general matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// upper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,false>& >
+ UpperMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsUpper<MT2>::value && !isUpper( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ = ~rhs;
+
+ if( !IsUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for matrix computations.
+//
+// \param rhs The matrix computation to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
+// matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
+// a \a std::invalid_argument exception is thrown. Also note that the given matrix must be an
+// upper matrix. Otherwise, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,false>& >
+ UpperMatrix<MT,SO,false>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ if( IsUpper<MT2>::value ) {
+ matrix_ = ~rhs;
+ }
+ else {
+ MT tmp( ~rhs );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+ }
+
+ if( !IsUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side general matrix to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an upper
+// matrix, i.e. the given matrix must be an upper matrix. In case the result is not an upper
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,false>& >
+ UpperMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsUpper<MT2>::value && !isUpper( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ += ~rhs;
+
+ if( !IsUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be added.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the addition operation must be an upper
+// matrix, i.e. the given matrix must be an upper matrix. In case the result is not an upper
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,false>& >
+ UpperMatrix<MT,SO,false>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ if( IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ if( IsUpper<MT2>::value ) {
+ matrix_ += ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ += tmp;
+ }
+
+ if( !IsUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side general matrix to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// upper matrix, i.e. the given matrix must be an upper matrix. In case the result is not
+// an upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,false>& >
+ UpperMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsUpper<MT2>::value && !isUpper( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ -= ~rhs;
+
+ if( !IsUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix computation to be subtracted.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Invalid assignment to upper matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument
+// exception is thrown. Also note that the result of the subtraction operation must be an
+// upper matrix, i.e. the given matrix must be an upper matrix. In case the result is not
+// an upper matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsComputation<MT2>, UpperMatrix<MT,SO,false>& >
+ UpperMatrix<MT,SO,false>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ if( !IsSquare<MT2>::value && !isSquare( ~rhs ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ if( IsUpper<MT2>::value ) {
+ matrix_ -= ~rhs;
+ }
+ else {
+ const ResultType_<MT2> tmp( ~rhs );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ -= tmp;
+ }
+
+ if( !IsUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also note that the result of the multiplication operation must be an upper matrix.
+// In case it is not, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline UpperMatrix<MT,SO,false>&
+ UpperMatrix<MT,SO,false>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ if( matrix_.rows() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ MT tmp( matrix_ * ~rhs );
+
+ if( !isUpper( tmp ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" );
+ }
+
+ matrix_ = std::move( tmp );
+
+ if( !IsUpper<MT2>::value )
+ resetLower();
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, UpperMatrix<MT,SO,false> >&
+ UpperMatrix<MT,SO,false>::operator*=( Other rhs )
+{
+ matrix_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, UpperMatrix<MT,SO,false> >&
+ UpperMatrix<MT,SO,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ matrix_ /= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UpperMatrix<MT,SO,false>::rows() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UpperMatrix<MT,SO,false>::columns() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UpperMatrix<MT,SO,false>::capacity() const noexcept
+{
+ return matrix_.capacity();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the upper
+// matrix adapts a \a rowMajor sparse matrix the function returns the capacity of row \a i, in
+// case it adapts a \a columnMajor sparse matrix the function returns the capacity of column
+// \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UpperMatrix<MT,SO,false>::capacity( size_t i ) const noexcept
+{
+ return matrix_.capacity(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the upper matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UpperMatrix<MT,SO,false>::nonZeros() const
+{
+ return matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the upper matrix adapts a \a rowMajor sparse matrix the function returns the number
+// of non-zero elements in row \a i, in case it adapts a to \a columnMajor sparse matrix the
+// function returns the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline size_t UpperMatrix<MT,SO,false>::nonZeros( size_t i ) const
+{
+ return matrix_.nonZeros(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::reset()
+{
+ matrix_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+// \exception std::invalid_argument Invalid row/column access index.
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the reset() function has no impact on the capacity of the matrix or row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::reset( size_t i )
+{
+ matrix_.reset( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the upper matrix.
+//
+// \return void
+//
+// This function clears the upper matrix and returns it to its default state.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::clear()
+{
+ using blaze::clear;
+
+ clear( matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting elements of the upper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to lower matrix element.
+//
+// This function sets the value of an element of the upper matrix. In case the upper matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted. The attempt to set an element in the
+// lower part of the matrix (i.e. below the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ if( i > j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to lower matrix element" );
+ }
+
+ return matrix_.set( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting elements into the upper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+// \exception std::invalid_argument Invalid access to lower matrix element.
+//
+// This function inserts a new element into the upper matrix. However, duplicate elements are
+// not allowed. In case the upper matrix already contains an element with row index \a i and
+// column index \a j, a \a std::invalid_argument exception is thrown. Also, the attempt to
+// insert an element in the lower part of the matrix (i.e. below the diagonal) will result in
+// a \a std::invalid_argument exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ if( i > j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to lower matrix element" );
+ }
+
+ return matrix_.insert( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the upper matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the upper matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::erase( size_t i, size_t j )
+{
+ matrix_.erase( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing elements from the upper matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the upper matrix. In case the upper matrix adapts a
+// \a rowMajor sparse matrix the function erases an element from row \a i, in case it adapts
+// a \a columnMajor sparse matrix the function erases an element from column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::erase( size_t i, Iterator pos )
+{
+ return matrix_.erase( i, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the upper matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of element from the upper matrix. In case the upper matrix adapts
+// a \a rowMajor sparse matrix the function erases a range of elements from row \a i, in case it
+// adapts a \a columnMajor matrix the function erases a range of elements from column \a i.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ return matrix_.erase( i, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the upper matrix.
+//
+// \param n The new number of rows and columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+void UpperMatrix<MT,SO,false>::resize( size_t n, bool preserve )
+{
+ BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square upper matrix detected" );
+
+ matrix_.resize( n, n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the upper matrix.
+//
+// \param nonzeros The new minimum capacity of the upper matrix.
+// \return void
+//
+// This function increases the capacity of the upper matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::reserve( size_t nonzeros )
+{
+ matrix_.reserve( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the upper matrix.
+//
+// \param i The row/column index \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the upper matrix to at least
+// \a nonzeros elements. The current values of the upper matrix and all other individual
+// row/column capacities are preserved. In case the upper matrix adapts a \a rowMajor sparse
+// matrix the function reserves capacity for row \a i. In case it adapts a \a columnMajor the
+// function reserves capacity for column \a i. The index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::reserve( size_t i, size_t nonzeros )
+{
+ matrix_.reserve( i, nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::trim()
+{
+ matrix_.trim();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the upper matrix.
+//
+// \param i The index of the row/column to be trimmed \f$[0..N-1]\f$.
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::trim( size_t i )
+{
+ matrix_.trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline UpperMatrix<MT,SO,false>&
+ UpperMatrix<MT,SO,false>::scale( const Other& scalar )
+{
+ matrix_.scale( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the upper matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the upper matrix.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the scalar value
+inline UpperMatrix<MT,SO,false>&
+ UpperMatrix<MT,SO,false>::scaleDiagonal( Other scalar )
+{
+ matrix_.scaleDiagonal( scalar );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::swap( UpperMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( matrix_, m.matrix_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for an upper triangular matrix.
+//
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for an upper triangular
+// matrix with fixed-size adapted matrix of type \a MT. Note that this function can only be
+// called in case the adapted dense matrix is a fixed-size matrix. The attempt to call this
+// function in case the adapted matrix is resizable matrix will result in a compile time error.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UpperMatrix<MT,SO,false>::maxNonZeros() noexcept
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT );
+
+ return maxNonZeros( Rows<MT>::value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum number of non-zero values for an upper triangular matrix.
+//
+// \param n The number of rows and columns of the matrix.
+// \return The maximum number of non-zero values.
+//
+// This function returns the maximum possible number of non-zero values for an upper triangular
+// matrix of the given number of rows and columns.
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline constexpr size_t UpperMatrix<MT,SO,false>::maxNonZeros( size_t n ) noexcept
+{
+ return ( ( n + 1UL ) * n ) / 2UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the complete lower part of the matrix to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the adapted dense matrix
+ , bool SO > // Storage order of the adapted dense matrix
+inline void UpperMatrix<MT,SO,false>::resetLower()
+{
+ if( SO ) {
+ for( size_t j=0UL; j<columns(); ++j )
+ matrix_.erase( j, matrix_.upperBound( j, j ), matrix_.end( j ) );
+ }
+ else {
+ for( size_t i=1UL; i<rows(); ++i )
+ matrix_.erase( i, matrix_.begin( i ), matrix_.lowerBound( i, i ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the upper
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned upper matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::find( size_t i, size_t j )
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the upper
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned upper matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstIterator
+ UpperMatrix<MT,SO,false>::find( size_t i, size_t j ) const
+{
+ return matrix_.find( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned upper matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::lowerBound( size_t i, size_t j )
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned upper matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstIterator
+ UpperMatrix<MT,SO,false>::lowerBound( size_t i, size_t j ) const
+{
+ return matrix_.lowerBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned upper matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::Iterator
+ UpperMatrix<MT,SO,false>::upperBound( size_t i, size_t j )
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned upper matrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline typename UpperMatrix<MT,SO,false>::ConstIterator
+ UpperMatrix<MT,SO,false>::upperBound( size_t i, size_t j ) const
+{
+ return matrix_.upperBound( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending elements to the specified row/column of the upper matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to lower matrix element.
+//
+// This function provides a very efficient way to fill an upper sparse matrix with elements. It
+// appends a new element to the end of the specified row/column without any additional memory
+// allocation. Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (newly created) sparse matrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::UpperMatrix;
+ using blaze::rowMajor;
+
+ UpperMatrix< CompressedMatrix<double,rowMajor> > A( 4 );
+
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 0, 1, 1.0 ); // Appending the value 1 in row 0 with column index 1
+ A.finalize( 0 ); // Finalizing row 0
+ A.append( 1, 2, 2.0 ); // Appending the value 2 in row 1 with column index 2
+ A.finalize( 1 ); // Finalizing row 1
+ A.finalize( 2 ); // Finalizing the empty row 2 to prepare row 3
+ A.append( 3, 3, 3.0 ); // Appending the value 3 in row 3 with column index 3
+ A.finalize( 3 ); // Finalizing row 3
+ \endcode
+
+// Note that although append() does not allocate new memory it still invalidates all iterators
+// returned by the end() functions! Also note that the attempt to append an element within the
+// lower part of the matrix (i.e. below the diagonal) will result in a \a std::invalid_argument
+// exception.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( i > j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to lower matrix element" );
+ }
+
+ matrix_.append( i, j, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..N-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline void UpperMatrix<MT,SO,false>::finalize( size_t i )
+{
+ matrix_.finalize( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the upper matrix are intact.
+//
+// \return \a true in case the upper matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the upper matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool UpperMatrix<MT,SO,false>::isIntact() const noexcept
+{
+ using blaze::isIntact;
+
+ return ( isIntact( matrix_ ) && isUpper( matrix_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UpperMatrix<MT,SO,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.canAlias( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool UpperMatrix<MT,SO,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the adapted sparse matrix
+ , bool SO > // Storage order of the adapted sparse matrix
+inline bool UpperMatrix<MT,SO,false>::canSMPAssign() const noexcept
+{
+ return matrix_.canSMPAssign();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/adaptors/uppermatrix/UpperProxy.h b/src/cpu/blaze/math/adaptors/uppermatrix/UpperProxy.h
new file mode 100644
index 00000000..0c942ecc
--- /dev/null
+++ b/src/cpu/blaze/math/adaptors/uppermatrix/UpperProxy.h
@@ -0,0 +1,665 @@
+//=================================================================================================
+/*!
+// \file blaze/math/adaptors/uppermatrix/UpperProxy.h
+// \brief Header file for the UpperProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_ADAPTORS_UPPERMATRIX_UPPERPROXY_H_
+#define _BLAZE_MATH_ADAPTORS_UPPERMATRIX_UPPERPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/typetraits/AddConst.h>
+#include <blaze/util/typetraits/AddReference.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for upper triangular matrices.
+// \ingroup upper_matrix
+//
+// The UpperProxy provides controlled access to the elements of a non-const upper triangular
+// matrix. It guarantees that the upper matrix invariant is not violated, i.e. that elements
+// in the lower part of the matrix remain default values. The following example illustrates
+// this by means of a \f$ 3 \times 3 \f$ dense upper matrix:
+
+ \code
+ // Creating a 3x3 upper dense matrix
+ blaze::UpperMatrix< blaze::DynamicMatrix<int> > A( 3UL );
+
+ A(0,0) = -2; // ( -2 3 0 )
+ A(0,1) = 3; // => A = ( 0 0 5 )
+ A(1,2) = 5; // ( 0 0 0 )
+
+ A(2,0) = 7; // Invalid assignment to lower matrix element; results in an exception!
+ \endcode
+*/
+template< typename MT > // Type of the adapted matrix
+class UpperProxy : public Proxy< UpperProxy<MT>, ElementType_<MT> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Reference type of the underlying matrix type.
+ typedef AddConst_< typename MT::Reference > ReferenceType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented matrix element.
+ typedef AddReference_<ReferenceType> RawReference; //!< Reference-to-non-const to the represented element.
+ typedef const RepresentedType& ConstReference; //!< Reference-to-const to the represented element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UpperProxy( MT& matrix, size_t row, size_t column );
+ inline UpperProxy( const UpperProxy& up );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline const UpperProxy& operator=( const UpperProxy& up ) const;
+
+ template< typename T >
+ inline const UpperProxy& operator=( initializer_list<T> list ) const;
+
+ template< typename T >
+ inline const UpperProxy& operator=( initializer_list< initializer_list<T> > list ) const;
+
+ template< typename T > inline const UpperProxy& operator= ( const T& value ) const;
+ template< typename T > inline const UpperProxy& operator+=( const T& value ) const;
+ template< typename T > inline const UpperProxy& operator-=( const T& value ) const;
+ template< typename T > inline const UpperProxy& operator*=( const T& value ) const;
+ template< typename T > inline const UpperProxy& operator/=( const T& value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline RawReference get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator ConstReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ ReferenceType value_; //!< Reference to the accessed matrix element.
+ const bool restricted_; //!< Access flag for the accessed matrix element.
+ /*!< The flag indicates if access to the matrix element is
+ restricted. It is \a true in case the proxy represents
+ an element in the lower part of the matrix. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a UpperProxy.
+//
+// \param matrix Reference to the adapted matrix.
+// \param row The row-index of the accessed matrix element.
+// \param column The column-index of the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UpperProxy<MT>::UpperProxy( MT& matrix, size_t row, size_t column )
+ : value_ ( matrix( row, column ) ) // Reference to the accessed matrix element
+ , restricted_( column < row ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for UpperProxy.
+//
+// \param up Upper proxy to be copied.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UpperProxy<MT>::UpperProxy( const UpperProxy& up )
+ : value_ ( up.value_ ) // Reference to the accessed matrix element
+ , restricted_( up.restricted_ ) // Access flag for the accessed matrix element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for UpperProxy.
+//
+// \param up Upper proxy to be copied.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// In case the proxy represents an element in the lower matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+inline const UpperProxy<MT>& UpperProxy<MT>::operator=( const UpperProxy& up ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix element" );
+ }
+
+ value_ = up.value_;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// In case the proxy represents an element in the lower matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UpperProxy<MT>& UpperProxy<MT>::operator=( initializer_list<T> list ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed matrix element.
+//
+// \param list The list to be assigned to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// In case the proxy represents an element in the lower matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UpperProxy<MT>& UpperProxy<MT>::operator=( initializer_list< initializer_list<T> > list ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix element" );
+ }
+
+ value_ = list;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed matrix element.
+//
+// \param value The new value of the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// In case the proxy represents an element in the lower matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UpperProxy<MT>& UpperProxy<MT>::operator=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix element" );
+ }
+
+ value_ = value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be added to the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// In case the proxy represents an element in the lower matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UpperProxy<MT>& UpperProxy<MT>::operator+=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix element" );
+ }
+
+ value_ += value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed matrix element.
+//
+// \param value The right-hand side value to be subtracted from the matrix element.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// In case the proxy represents an element in the lower matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UpperProxy<MT>& UpperProxy<MT>::operator-=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix element" );
+ }
+
+ value_ -= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// In case the proxy represents an element in the lower matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UpperProxy<MT>& UpperProxy<MT>::operator*=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix element" );
+ }
+
+ value_ *= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned proxy.
+// \exception std::invalid_argument Invalid assignment to lower matrix element.
+//
+// In case the proxy represents an element in the lower matrix, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the adapted matrix
+template< typename T > // Type of the right-hand side value
+inline const UpperProxy<MT>& UpperProxy<MT>::operator/=( const T& value ) const
+{
+ if( restricted_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix element" );
+ }
+
+ value_ /= value;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed matrix element.
+//
+// \return Direct/raw reference to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline typename UpperProxy<MT>::RawReference UpperProxy<MT>::get() const noexcept
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted matrix element..
+//
+// \return \a true in case access to the matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the adapted matrix
+inline bool UpperProxy<MT>::isRestricted() const noexcept
+{
+ return restricted_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed matrix element.
+//
+// \return Reference-to-const to the accessed matrix element.
+*/
+template< typename MT > // Type of the adapted matrix
+inline UpperProxy<MT>::operator ConstReference() const noexcept
+{
+ return static_cast<ConstReference>( value_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UpperProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const UpperProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const UpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const UpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const UpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const UpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const UpperProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const UpperProxy<MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup upper_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial
+// value.
+*/
+template< typename MT >
+inline void reset( const UpperProxy<MT>& proxy )
+{
+ using blaze::reset;
+
+ reset( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup upper_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial
+// state.
+*/
+template< typename MT >
+inline void clear( const UpperProxy<MT>& proxy )
+{
+ using blaze::clear;
+
+ clear( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup upper_matrix
+//
+// \param proxy The given access proxy
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const UpperProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup upper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const UpperProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup upper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const UpperProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup upper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const UpperProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup upper_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const UpperProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/blas/BLAS.h b/src/cpu/blaze/math/blas/BLAS.h
new file mode 100644
index 00000000..4e7b8d7a
--- /dev/null
+++ b/src/cpu/blaze/math/blas/BLAS.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/blas/BLAS.h
+// \brief BLAS module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_BLAS_BLAS_H_
+#define _BLAZE_MATH_BLAS_BLAS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup blas BLAS
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/blas/dot.h b/src/cpu/blaze/math/blas/dot.h
new file mode 100644
index 00000000..bfd80ca5
--- /dev/null
+++ b/src/cpu/blaze/math/blas/dot.h
@@ -0,0 +1,227 @@
+//=================================================================================================
+/*!
+// \file blaze/math/blas/dot.h
+// \brief Header file for BLAS dot product (dot)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_BLAS_DOT_H_
+#define _BLAZE_MATH_BLAS_DOT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/ConstDataAccess.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLAS WRAPPER FUNCTIONS (GEMV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name BLAS wrapper functions (gemv) */
+//@{
+#if BLAZE_BLAS_MODE
+
+float dot( const int n, const float* x, const int incX, const float* y, const int incY );
+
+double dot( const int n, const double* x, const int incX, const double* y, const int incY );
+
+complex<float> dot( const int n, const complex<float>* x, const int incX,
+ const complex<float>* y, const int incY );
+
+complex<double> dot( const int n, const complex<double>* x, const int incX,
+ const complex<double>* y, const int incY );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+ElementType_<VT1> dot( const DenseVector<VT1,TF1>& x, const DenseVector<VT2,TF2>& y );
+
+#endif
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense vector dot product for single precision operands
+// (\f$ s=\vec{x}*\vec{y} \f$).
+// \ingroup blas
+//
+// \param n The size of the two dense vectors \a x and \a y \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \param y Pointer to the first element of vector \a y.
+// \param incY The stride within vector \a y.
+// \return void
+//
+// This function performs the dense vector dot product for single precision operands based on
+// the BLAS cblas_sdot() function.
+*/
+BLAZE_ALWAYS_INLINE float dot( const int n, const float* x, const int incX,
+ const float* y, const int incY )
+{
+ return cblas_sdot( n, x, incX, y, incY );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense vector dot product for double precision operands
+// (\f$ s=\vec{x}*\vec{y} \f$).
+// \ingroup blas
+//
+// \param n The size of the two dense vectors \a x and \a y \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \param y Pointer to the first element of vector \a y.
+// \param incY The stride within vector \a y.
+// \return void
+//
+// This function performs the dense vector dot product for double precision operands based on
+// the BLAS cblas_ddot() function.
+*/
+BLAZE_ALWAYS_INLINE double dot( const int n, const double* x, const int incX,
+ const double* y, const int incY )
+{
+ return cblas_ddot( n, x, incX, y, incY );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense vector dot product for single precision complex operands
+// (\f$ s=\vec{x}*\vec{y} \f$).
+// \ingroup blas
+//
+// \param n The size of the two dense vectors \a x and \a y \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \param y Pointer to the first element of vector \a y.
+// \param incY The stride within vector \a y.
+// \return void
+//
+// This function performs the dense vector dot product for single precision complex operands
+// based on the BLAS cblas_cdotu_sub() function.
+*/
+BLAZE_ALWAYS_INLINE complex<float> dot( const int n, const complex<float>* x, const int incX,
+ const complex<float>* y, const int incY )
+{
+ complex<float> tmp;
+ cblas_cdotu_sub( n, x, incX, y, incY, &tmp );
+ return tmp;
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense vector dot product for double precision complex operands
+// (\f$ s=\vec{x}*\vec{y} \f$).
+// \ingroup blas
+//
+// \param n The size of the two dense vectors \a x and \a y \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \param y Pointer to the first element of vector \a y.
+// \param incY The stride within vector \a y.
+// \return void
+//
+// This function performs the dense vector dot product for double precision complex operands
+// based on the BLAS cblas_zdotu_sub() function.
+*/
+BLAZE_ALWAYS_INLINE complex<double> dot( const int n, const complex<double>* x, const int incX,
+ const complex<double>* y, const int incY )
+{
+ complex<double> tmp;
+ cblas_zdotu_sub( n, x, incX, y, incY, &tmp );
+ return tmp;
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense vector dot product (\f$ s=\vec{x}*\vec{y} \f$).
+// \ingroup blas
+//
+// \param y The left-hand side dense vector operand.
+// \param x The right-hand side dense vector operand.
+// \return void
+//
+// This function performs the dense vector dot product based on the BLAS dot() functions. Note
+// that the function only works for vectors with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with vectors of any other
+// element type results in a compile time error.
+*/
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+ElementType_<VT1> dot( const DenseVector<VT1,TF1>& x, const DenseVector<VT2,TF2>& y )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT2 );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( VT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( VT2 );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT2> );
+
+ const int n( numeric_cast<int>( (~x).size() ) );
+
+ return dot( n, (~x).data(), 1, (~y).data(), 1 );
+}
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/blas/gemm.h b/src/cpu/blaze/math/blas/gemm.h
new file mode 100644
index 00000000..7ba696f9
--- /dev/null
+++ b/src/cpu/blaze/math/blas/gemm.h
@@ -0,0 +1,298 @@
+//=================================================================================================
+/*!
+// \file blaze/math/blas/gemm.h
+// \brief Header file for BLAS general matrix/matrix multiplication functions (gemm)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_BLAS_GEMM_H_
+#define _BLAZE_MATH_BLAS_GEMM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/ConstDataAccess.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLAS WRAPPER FUNCTIONS (GEMM)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name BLAS wrapper functions (gemm) */
+//@{
+#if BLAZE_BLAS_MODE
+
+BLAZE_ALWAYS_INLINE void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, float alpha, const float* A, int lda,
+ const float* B, int ldb, float beta, float* C, int ldc );
+
+BLAZE_ALWAYS_INLINE void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, double alpha, const double* A, int lda,
+ const double* B, int ldb, double beta, float* C, int ldc );
+
+BLAZE_ALWAYS_INLINE void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, complex<float> alpha, const complex<float>* A,
+ int lda, const complex<float>* B, int ldb, complex<float> beta,
+ float* C, int ldc );
+
+BLAZE_ALWAYS_INLINE void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, complex<double> alpha, const complex<double>* A,
+ int lda, const complex<double>* B, int ldb, complex<double> beta,
+ float* C, int ldc );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2, typename MT3, bool SO3, typename ST >
+BLAZE_ALWAYS_INLINE void gemm( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ const DenseMatrix<MT3,SO3>& B, ST alpha, ST beta );
+
+#endif
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense matrix multiplication with single precision
+// matrices (\f$ C=\alpha*A*B+\beta*C \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param transB Specifies whether to transpose matrix \a B (\a CblasNoTrans or \a CblasTrans).
+// \param m The number of rows of matrix \a A and \a C \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B and \a C \f$[0..\infty)\f$.
+// \param k The number of columns of matrix \a A and rows in matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*B \f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \param beta The scaling factor for \f$ C \f$.
+// \param C Pointer to the first element of matrix \a C.
+// \param ldc The total number of elements between two rows/columns of matrix \a C \f$[0..\infty)\f$.
+// \return void
+//
+// This function performs the dense matrix/dense matrix multiplication for single precision
+// matrices based on the BLAS cblas_sgemm() function.
+*/
+BLAZE_ALWAYS_INLINE void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, float alpha, const float* A, int lda,
+ const float* B, int ldb, float beta, float* C, int ldc )
+{
+ cblas_sgemm( order, transA, transB, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense matrix multiplication with double precision
+// matrices (\f$ C=\alpha*A*B+\beta*C \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param transB Specifies whether to transpose matrix \a B (\a CblasNoTrans or \a CblasTrans).
+// \param m The number of rows of matrix \a A and \a C \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B and \a C \f$[0..\infty)\f$.
+// \param k The number of columns of matrix \a A and rows in matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*B \f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \param beta The scaling factor for \f$ C \f$.
+// \param C Pointer to the first element of matrix \a C.
+// \param ldc The total number of elements between two rows/columns of matrix \a C \f$[0..\infty)\f$.
+// \return void
+//
+// This function performs the dense matrix/dense matrix multiplication for double precision
+// matrices based on the BLAS cblas_dgemm() function.
+*/
+BLAZE_ALWAYS_INLINE void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, double alpha, const double* A, int lda,
+ const double* B, int ldb, double beta, double* C, int ldc )
+{
+ cblas_dgemm( order, transA, transB, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense matrix multiplication with single precision
+// matrices (\f$ C=\alpha*A*B+\beta*C \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param transB Specifies whether to transpose matrix \a B (\a CblasNoTrans or \a CblasTrans).
+// \param m The number of rows of matrix \a A and \a C \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B and \a C \f$[0..\infty)\f$.
+// \param k The number of columns of matrix \a A and rows in matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*B \f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \param beta The scaling factor for \f$ C \f$.
+// \param C Pointer to the first element of matrix \a C.
+// \param ldc The total number of elements between two rows/columns of matrix \a C \f$[0..\infty)\f$.
+// \return void
+//
+// This function performs the dense matrix/dense matrix multiplication for single precision
+// complex matrices based on the BLAS cblas_cgemm() function.
+*/
+BLAZE_ALWAYS_INLINE void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, complex<float> alpha, const complex<float>* A,
+ int lda, const complex<float>* B, int ldb, complex<float> beta,
+ complex<float>* C, int ldc )
+{
+ cblas_cgemm( order, transA, transB, m, n, k, &alpha, A, lda, B, ldb, &beta, C, ldc );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense matrix multiplication with double precision
+// matrices (\f$ C=\alpha*A*B+\beta*C \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param transB Specifies whether to transpose matrix \a B (\a CblasNoTrans or \a CblasTrans).
+// \param m The number of rows of matrix \a A and \a C \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B and \a C \f$[0..\infty)\f$.
+// \param k The number of columns of matrix \a A and rows in matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*B \f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \param beta The scaling factor for \f$ C \f$.
+// \param C Pointer to the first element of matrix \a C.
+// \param ldc The total number of elements between two rows/columns of matrix \a C \f$[0..\infty)\f$.
+// \return void
+//
+// This function performs the dense matrix/dense matrix multiplication for double precision
+// complex matrices based on the BLAS cblas_zgemm() function.
+*/
+BLAZE_ALWAYS_INLINE void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
+ int m, int n, int k, complex<double> alpha, const complex<double>* A,
+ int lda, const complex<double>* B, int ldb, complex<double> beta,
+ complex<double>* C, int ldc )
+{
+ cblas_zgemm( order, transA, transB, m, n, k, &alpha, A, lda, B, ldb, &beta, C, ldc );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense matrix multiplication (\f$ C=\alpha*A*B+\beta*C \f$).
+// \ingroup blas
+//
+// \param C The target left-hand side dense matrix.
+// \param A The left-hand side multiplication operand.
+// \param B The right-hand side multiplication operand.
+// \param alpha The scaling factor for \f$ A*B \f$.
+// \param beta The scaling factor for \f$ C \f$.
+// \return void
+//
+// This function performs the dense matrix/dense matrix multiplication based on the BLAS
+// gemm() functions. Note that the function only works for matrices with \c float, \c double,
+// \c complex<float>, and \c complex<double> element type. The attempt to call the function
+// with matrices of any other element type results in a compile time error.
+*/
+template< typename MT1 // Type of the left-hand side target matrix
+ , bool SO1 // Storage order of the left-hand side target matrix
+ , typename MT2 // Type of the left-hand side matrix operand
+ , bool SO2 // Storage order of the left-hand side matrix operand
+ , typename MT3 // Type of the right-hand side matrix operand
+ , bool SO3 // Storage order of the right-hand side matrix operand
+ , typename ST > // Type of the scalar factors
+BLAZE_ALWAYS_INLINE void gemm( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ const DenseMatrix<MT3,SO3>& B, ST alpha, ST beta )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT3 );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT3 );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT3> );
+
+ const int m ( numeric_cast<int>( (~A).rows() ) );
+ const int n ( numeric_cast<int>( (~B).columns() ) );
+ const int k ( numeric_cast<int>( (~A).columns() ) );
+ const int lda( numeric_cast<int>( (~A).spacing() ) );
+ const int ldb( numeric_cast<int>( (~B).spacing() ) );
+ const int ldc( numeric_cast<int>( (~C).spacing() ) );
+
+ gemm( ( IsRowMajorMatrix<MT1>::value )?( CblasRowMajor ):( CblasColMajor ),
+ ( SO1 == SO2 )?( CblasNoTrans ):( CblasTrans ),
+ ( SO1 == SO3 )?( CblasNoTrans ):( CblasTrans ),
+ m, n, k, alpha, (~A).data(), lda, (~B).data(), ldb, beta, (~C).data(), ldc );
+}
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/blas/gemv.h b/src/cpu/blaze/math/blas/gemv.h
new file mode 100644
index 00000000..3477b81c
--- /dev/null
+++ b/src/cpu/blaze/math/blas/gemv.h
@@ -0,0 +1,337 @@
+//=================================================================================================
+/*!
+// \file blaze/math/blas/gemv.h
+// \brief Header file for BLAS general matrix/vector multiplication functions (gemv)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_BLAS_GEMV_H_
+#define _BLAZE_MATH_BLAS_GEMV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/ConstDataAccess.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLAS WRAPPER FUNCTIONS (GEMV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name BLAS wrapper functions (gemv) */
+//@{
+#if BLAZE_BLAS_MODE
+
+BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n,
+ float alpha, const float* A, int lda, const float* x, int incX,
+ float beta, float* y, int incY );
+
+BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n,
+ double alpha, const double* A, int lda, const double* x, int incX,
+ double beta, double* y, int incY );
+
+BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n,
+ complex<float> alpha, const complex<float>* A, int lda,
+ const complex<float>* x, int incX, complex<float> beta,
+ complex<float>* y, int incY );
+
+BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n,
+ complex<double> alpha, const complex<double>* A, int lda,
+ const complex<double>* x, int incX, complex<double> beta,
+ complex<double>* y, int incY );
+
+template< typename VT1, typename MT1, bool SO, typename VT2, typename ST >
+BLAZE_ALWAYS_INLINE void gemv( DenseVector<VT1,false>& y, const DenseMatrix<MT1,SO>& A,
+ const DenseVector<VT2,false>& x, ST alpha, ST beta );
+
+template< typename VT1, typename VT2, typename MT1, bool SO, typename ST >
+BLAZE_ALWAYS_INLINE void gemv( DenseVector<VT1,true>& y, const DenseVector<VT2,true>& x,
+ const DenseMatrix<MT1,SO>& A, ST alpha, ST beta );
+
+#endif
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense vector multiplication for single precision operands
+// (\f$ \vec{y}=\alpha*A*\vec{x}+\beta*\vec{y} \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param m The number of rows of matrix \a A \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a A \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*\vec{x} \f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \param beta The scaling factor for \f$ \vec{y} \f$.
+// \param y Pointer to the first element of vector \a y.
+// \param incY The stride within vector \a y.
+// \return void
+//
+// This function performs the dense matrix/dense vector multiplication for single precision
+// operands based on the BLAS cblas_sgemv() function.
+*/
+BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, int m, int n,
+ float alpha, const float* A, int lda, const float* x, int incX,
+ float beta, float* y, int incY )
+{
+ cblas_sgemv( order, transA, m, n, alpha, A, lda, x, incX, beta, y, incY );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense vector multiplication for double precision operands
+// (\f$ \vec{y}=\alpha*A*\vec{x}+\beta*\vec{y} \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param m The number of rows of matrix \a A \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a A \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*\vec{x} \f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \param beta The scaling factor for \f$ \vec{y} \f$.
+// \param y Pointer to the first element of vector \a y.
+// \param incY The stride within vector \a y.
+// \return void
+//
+// This function performs the dense matrix/dense vector multiplication for double precision
+// operands based on the BLAS cblas_dgemv() function.
+*/
+BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, int m, int n,
+ double alpha, const double* A, int lda, const double* x, int incX,
+ double beta, double* y, int incY )
+{
+ cblas_dgemv( order, transA, m, n, alpha, A, lda, x, incX, beta, y, incY );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense vector multiplication for single precision complex
+// operands (\f$ \vec{y}=\alpha*A*\vec{x}+\beta*\vec{y} \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param m The number of rows of matrix \a A \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a A \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*\vec{x} \f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \param beta The scaling factor for \f$ \vec{y} \f$.
+// \param y Pointer to the first element of vector \a y.
+// \param incY The stride within vector \a y.
+// \return void
+//
+// This function performs the dense matrix/dense vector multiplication for single precision
+// complex operands based on the BLAS cblas_cgemv() function.
+*/
+BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, int m, int n,
+ complex<float> alpha, const complex<float>* A, int lda,
+ const complex<float>* x, int incX, complex<float> beta,
+ complex<float>* y, int incY )
+{
+ cblas_cgemv( order, transA, m, n, &alpha, A, lda, x, incX, &beta, y, incY );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense vector multiplication for double precision complex
+// operands (\f$ \vec{y}=\alpha*A*\vec{x}+\beta*\vec{y} \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param m The number of rows of matrix \a A \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a A \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*\vec{x} \f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \param beta The scaling factor for \f$ \vec{y} \f$.
+// \param y Pointer to the first element of vector \a y.
+// \param incY The stride within vector \a y.
+// \return void
+//
+// This function performs the dense matrix/dense vector multiplication for double precision
+// complex operands based on the BLAS zblas_zgemv() function.
+*/
+BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, int m, int n,
+ complex<double> alpha, const complex<double>* A, int lda,
+ const complex<double>* x, int incX, complex<double> beta,
+ complex<double>* y, int incY )
+{
+ cblas_zgemv( order, transA, m, n, &alpha, A, lda, x, incX, &beta, y, incY );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a dense matrix/dense vector multiplication
+// (\f$ \vec{y}=\alpha*A*\vec{x}+\beta*\vec{y} \f$).
+// \ingroup blas
+//
+// \param y The target left-hand side dense vector.
+// \param A The left-hand side dense matrix operand.
+// \param x The right-hand side dense vector operand.
+// \param alpha The scaling factor for \f$ A*\vec{x} \f$.
+// \param beta The scaling factor for \f$ \vec{y} \f$.
+// \return void
+//
+// This function performs the dense matrix/dense vector multiplication based on the BLAS gemv()
+// functions. Note that the function only works for vectors and matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// vectors and matrices of any other element type results in a compile time error.
+*/
+template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , bool SO // Storage order of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST > // Type of the scalar factors
+BLAZE_ALWAYS_INLINE void gemv( DenseVector<VT1,false>& y, const DenseMatrix<MT1,SO>& A,
+ const DenseVector<VT2,false>& x, ST alpha, ST beta )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT2 );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( VT2 );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT2> );
+
+ const int m ( numeric_cast<int>( (~A).rows() ) );
+ const int n ( numeric_cast<int>( (~A).columns() ) );
+ const int lda( numeric_cast<int>( (~A).spacing() ) );
+
+ gemv( ( SO )?( CblasColMajor ):( CblasRowMajor ), CblasNoTrans, m, n, alpha,
+ (~A).data(), lda, (~x).data(), 1, beta, (~y).data(), 1 );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a transpose dense vector/dense matrix multiplication
+// (\f$ \vec{y}^T=\alpha*\vec{x}^T*A+\beta*\vec{y}^T \f$).
+// \ingroup blas
+//
+// \param y The target left-hand side dense vector.
+// \param x The left-hand side dense vector operand.
+// \param A The right-hand side dense matrix operand.
+// \param alpha The scaling factor for \f$ \vec{x}^T*A \f$.
+// \param beta The scaling factor for \f$ \vec{y}^T \f$.
+// \return void
+//
+// This function performs the transpose dense vector/dense matrix multiplication based on the
+// BLAS gemv() functions. Note that the function only works for vectors and matrices with \c float,
+// \c double, \c complex<float>, or \c complex<double> element type. The attempt to call the
+// function with vectors and matrices of any other element type results in a compile time error.
+*/
+template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , bool SO // Storage order of the right-hand side matrix operand
+ , typename ST > // Type of the scalar factors
+BLAZE_ALWAYS_INLINE void gemv( DenseVector<VT1,true>& y, const DenseVector<VT2,true>& x,
+ const DenseMatrix<MT1,SO>& A, ST alpha, ST beta )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT2 );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( VT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT1 );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT2> );
+
+ const int m ( numeric_cast<int>( (~A).rows() ) );
+ const int n ( numeric_cast<int>( (~A).columns() ) );
+ const int lda( numeric_cast<int>( (~A).spacing() ) );
+
+ gemv( ( SO )?( CblasColMajor ):( CblasRowMajor ), CblasTrans, m, n, alpha,
+ (~A).data(), lda, (~x).data(), 1, beta, (~y).data(), 1 );
+}
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/blas/trmm.h b/src/cpu/blaze/math/blas/trmm.h
new file mode 100644
index 00000000..1f2d4557
--- /dev/null
+++ b/src/cpu/blaze/math/blas/trmm.h
@@ -0,0 +1,289 @@
+//=================================================================================================
+/*!
+// \file blaze/math/blas/trmm.h
+// \brief Header file for BLAS triangular matrix/matrix multiplication functions (trmm)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_BLAS_TRMM_H_
+#define _BLAZE_MATH_BLAS_TRMM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/ConstDataAccess.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLAS WRAPPER FUNCTIONS (TRMM)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name BLAS wrapper functions (trmm) */
+//@{
+#if BLAZE_BLAS_MODE
+
+BLAZE_ALWAYS_INLINE void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ float alpha, const float* A, int lda, float* B, int ldb );
+
+BLAZE_ALWAYS_INLINE void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ double alpha, const double* A, int lda, double* B, int ldb );
+
+BLAZE_ALWAYS_INLINE void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ complex<float> alpha, const complex<float>* A, int lda,
+ complex<float>* B, int ldb );
+
+BLAZE_ALWAYS_INLINE void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ complex<double> alpha, const complex<double>* A, int lda,
+ complex<double>* B, int ldb );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2, typename ST >
+BLAZE_ALWAYS_INLINE void trmm( DenseMatrix<MT1,SO1>& B, const DenseMatrix<MT2,SO2>& A,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha );
+
+#endif
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense matrix multiplication with single
+// precision matrices (\f$ B=\alpha*A*B \f$ or \f$ B=\alpha*B*A \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasRowMajor or \a CblasColMajor).
+// \param side \a CblasLeft to compute \f$ B=\alpha*A*B \f$, \a CblasRight to compute \f$ B=\alpha*B*A \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param m The number of rows of matrix \a B \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*B \f$ or \f$ B*A \f$.
+// \param A Pointer to the first element of the triangular matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \return void
+//
+// This function performs the scaling and multiplication of a triangular matrix by a matrix
+// based on the cblas_strmm() function. Note that matrix \a A is expected to be a square matrix.
+*/
+BLAZE_ALWAYS_INLINE void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ float alpha, const float* A, int lda, float* B, int ldb )
+{
+ cblas_strmm( order, side, uplo, transA, diag, m, n, alpha, A, lda, B, ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense matrix multiplication with double
+// precision matrices (\f$ B=\alpha*A*B \f$ or \f$ B=\alpha*B*A \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasRowMajor or \a CblasColMajor).
+// \param side \a CblasLeft to compute \f$ B=\alpha*A*B \f$, \a CblasRight to compute \f$ B=\alpha*B*A \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param m The number of rows of matrix \a B \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*B \f$ or \f$ B*A \f$.
+// \param A Pointer to the first element of the triangular matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \return void
+//
+// This function performs the scaling and multiplication of a triangular matrix by a matrix
+// based on the cblas_dtrmm() function. Note that matrix \a A is expected to be a square matrix.
+*/
+BLAZE_ALWAYS_INLINE void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ double alpha, const double* A, int lda, double* B, int ldb )
+{
+ cblas_dtrmm( order, side, uplo, transA, diag, m, n, alpha, A, lda, B, ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense matrix multiplication with single
+// precision complex matrices (\f$ B=\alpha*A*B \f$ or \f$ B=\alpha*B*A \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasRowMajor or \a CblasColMajor).
+// \param side \a CblasLeft to compute \f$ B=\alpha*A*B \f$, \a CblasRight to compute \f$ B=\alpha*B*A \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param m The number of rows of matrix \a B \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*B \f$ or \f$ B*A \f$.
+// \param A Pointer to the first element of the triangular matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \return void
+//
+// This function performs the scaling and multiplication of a triangular matrix by a matrix
+// based on the cblas_ctrmm() function. Note that matrix \a A is expected to be a square matrix.
+*/
+BLAZE_ALWAYS_INLINE void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ complex<float> alpha, const complex<float>* A, int lda,
+ complex<float>* B, int ldb )
+{
+ cblas_ctrmm( order, side, uplo, transA, diag, m, n, &alpha, A, lda, B, ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense matrix multiplication with double
+// precision complex matrices (\f$ B=\alpha*A*B \f$ or \f$ B=\alpha*B*A \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasRowMajor or \a CblasColMajor).
+// \param side \a CblasLeft to compute \f$ B=\alpha*A*B \f$, \a CblasRight to compute \f$ B=\alpha*B*A \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param m The number of rows of matrix \a B \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ A*B \f$ or \f$ B*A \f$.
+// \param A Pointer to the first element of the triangular matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \return void
+//
+// This function performs the scaling and multiplication of a triangular matrix by a matrix
+// based on the cblas_ztrmm() function. Note that matrix \a A is expected to be a square matrix.
+*/
+BLAZE_ALWAYS_INLINE void trmm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ complex<double> alpha, const complex<double>* A, int lda,
+ complex<double>* B, int ldb )
+{
+ cblas_ztrmm( order, side, uplo, transA, diag, m, n, &alpha, A, lda, B, ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense matrix multiplication
+// (\f$ B=\alpha*A*B \f$ or \f$ B=\alpha*B*A \f$).
+// \ingroup blas
+//
+// \param B The target dense matrix.
+// \param A The dense matrix multiplication operand.
+// \param side \a CblasLeft to compute \f$ B=\alpha*A*B \f$, \a CblasRight to compute \f$ B=\alpha*B*A \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param alpha The scaling factor for \f$ A*B \f$ or \f$ B*A \f$.
+// \return void
+//
+// This function performs the scaling and multiplication of a triangular matrix by a matrix
+// based on the BLAS trmm() functions. Note that the function only works for matrices with
+// \c float, \c double, \c complex<float>, and \c complex<double> element type. The attempt to
+// call the function with matrices of any other element type results in a compile time error.
+// Also note that matrix \a A is expected to be a square matrix.
+*/
+template< typename MT1 // Type of the left-hand side target matrix
+ , bool SO1 // Storage order of the left-hand side target matrix
+ , typename MT2 // Type of the left-hand side matrix operand
+ , bool SO2 // Storage order of the left-hand side matrix operand
+ , typename ST > // Type of the scalar factor
+BLAZE_ALWAYS_INLINE void trmm( DenseMatrix<MT1,SO1>& B, const DenseMatrix<MT2,SO2>& A,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~A).rows() == (~A).columns(), "Non-square triangular matrix detected" );
+ BLAZE_INTERNAL_ASSERT( side == CblasLeft || side == CblasRight, "Invalid side argument detected" );
+ BLAZE_INTERNAL_ASSERT( uplo == CblasLower || uplo == CblasUpper, "Invalid uplo argument detected" );
+
+ const int m ( numeric_cast<int>( (~B).rows() ) );
+ const int n ( numeric_cast<int>( (~B).columns() ) );
+ const int lda( numeric_cast<int>( (~A).spacing() ) );
+ const int ldb( numeric_cast<int>( (~B).spacing() ) );
+
+ trmm( ( IsRowMajorMatrix<MT1>::value )?( CblasRowMajor ):( CblasColMajor ),
+ side,
+ ( SO1 == SO2 )?( uplo ):( ( uplo == CblasLower )?( CblasUpper ):( CblasLower ) ),
+ ( SO1 == SO2 )?( CblasNoTrans ):( CblasTrans ),
+ CblasNonUnit,
+ m, n, alpha, (~A).data(), lda, (~B).data(), ldb );
+}
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/blas/trmv.h b/src/cpu/blaze/math/blas/trmv.h
new file mode 100644
index 00000000..028af0f7
--- /dev/null
+++ b/src/cpu/blaze/math/blas/trmv.h
@@ -0,0 +1,312 @@
+//=================================================================================================
+/*!
+// \file blaze/math/blas/trmv.h
+// \brief Header file for BLAS triangular matrix/vector multiplication functions (trmv)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_BLAS_TRMV_H_
+#define _BLAZE_MATH_BLAS_TRMV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/ConstDataAccess.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLAS WRAPPER FUNCTIONS (TRMV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name BLAS wrapper functions (trmv) */
+//@{
+#if BLAZE_BLAS_MODE
+
+BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int n, const float* A, int lda, float* x,
+ int incX );
+
+BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int n, const double* A, int lda, double* x,
+ int incX );
+
+BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int n, const complex<float>* A, int lda,
+ complex<float>* x, int incX );
+
+BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int n, const complex<double>* A, int lda,
+ complex<double>* x, int incX );
+
+template< typename VT, typename MT, bool SO >
+BLAZE_ALWAYS_INLINE void trmv( DenseVector<VT,false>& x, const DenseMatrix<MT,SO>& A,
+ CBLAS_UPLO uplo );
+
+template< typename VT, typename MT, bool SO >
+BLAZE_ALWAYS_INLINE void trmv( DenseVector<VT,true>& x, const DenseMatrix<MT,SO>& A,
+ CBLAS_UPLO uplo );
+
+#endif
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense vector multiplication for single
+// precision operands (\f$ \vec{x}=A*\vec{x} \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \return void
+//
+// This function performs the multiplication of a single precision triangular matrix by a vector
+// based on the cblas_strmv() function.
+*/
+BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int n, const float* A, int lda, float* x,
+ int incX )
+{
+ cblas_strmv( order, uplo, transA, diag, n, A, lda, x, incX );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense vector multiplication for double
+// precision operands (\f$ \vec{x}=A*\vec{x} \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \return void
+//
+// This function performs the multiplication of a double precision triangular matrix by a vector
+// based on the cblas_dtrmv() function.
+*/
+BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int n, const double* A, int lda, double* x,
+ int incX )
+{
+ cblas_dtrmv( order, uplo, transA, diag, n, A, lda, x, incX );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense vector multiplication for single
+// precision complex operands (\f$ \vec{x}=A*\vec{x} \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \return void
+//
+// This function performs the multiplication of a single precision complex triangular matrix by a
+// vector based on the cblas_ctrmv() function.
+*/
+BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int n, const complex<float>* A, int lda,
+ complex<float>* x, int incX )
+{
+ cblas_ctrmv( order, uplo, transA, diag, n, A, lda, x, incX );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense vector multiplication for double
+// precision complex operands (\f$ \vec{x}=A*\vec{x} \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a A (\a CblasColMajor or \a CblasColMajor).
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param A Pointer to the first element of matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \return void
+//
+// This function performs the multiplication of a double precision complex triangular matrix by a
+// vector based on the cblas_ztrmv() function.
+*/
+BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA,
+ CBLAS_DIAG diag, int n, const complex<double>* A, int lda,
+ complex<double>* x, int incX )
+{
+ cblas_ztrmv( order, uplo, transA, diag, n, A, lda, x, incX );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a triangular dense matrix/dense vector multiplication
+// (\f$ \vec{x}=A*\vec{x} \f$).
+// \ingroup blas
+//
+// \param x The target left-hand side dense vector.
+// \param A The dense matrix operand.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \return void
+//
+// This function performs the multiplication of a triangular matrix by a vector based on the BLAS
+// trmv() functions. Note that the function only works for vectors and matrices with \c float,
+// \c double, \c complex<float>, or \c complex<double> element type. The attempt to call the
+// function with vectors and matrices of any other element type results in a compile time error.
+*/
+template< typename VT // Type of the target vector
+ , typename MT // Type of the matrix operand
+ , bool SO > // Storage order of the matrix operand
+BLAZE_ALWAYS_INLINE void trmv( DenseVector<VT,false>& x, const DenseMatrix<MT,SO>& A,
+ CBLAS_UPLO uplo )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( (~A).rows() == (~A).columns(), "Non-square triangular matrix detected" );
+ BLAZE_INTERNAL_ASSERT( uplo == CblasLower || uplo == CblasUpper, "Invalid uplo argument detected" );
+
+ const int n ( numeric_cast<int>( (~A).rows() ) );
+ const int lda( numeric_cast<int>( (~A).spacing() ) );
+
+ trmv( ( IsRowMajorMatrix<MT>::value )?( CblasRowMajor ):( CblasColMajor ),
+ uplo, CblasNoTrans, CblasNonUnit, n, (~A).data(), lda, (~x).data(), 1 );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for a transpose dense vector/triangular dense matrix multiplication
+// (\f$ \vec{x}^T=\vec{x}^T*A \f$).
+// \ingroup blas
+//
+// \param x The target left-hand side dense vector.
+// \param A The dense matrix operand.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \return void
+//
+// This function performs the multiplication of a vector and a triangular matrix based on the BLAS
+// trmv() functions. Note that the function only works for vectors and matrices with \c float,
+// \c double, \c complex<float>, or \c complex<double> element type. The attempt to call the
+// function with vectors and matrices of any other element type results in a compile time error.
+*/
+template< typename VT // Type of the target vector
+ , typename MT // Type of the matrix operand
+ , bool SO > // Storage order of the matrix operand
+BLAZE_ALWAYS_INLINE void trmv( DenseVector<VT,true>& x, const DenseMatrix<MT,SO>& A,
+ CBLAS_UPLO uplo )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( (~A).rows() == (~A).columns(), "Non-square triangular matrix detected" );
+ BLAZE_INTERNAL_ASSERT( uplo == CblasLower || uplo == CblasUpper, "Invalid uplo argument detected" );
+
+ const int n ( numeric_cast<int>( (~A).rows() ) );
+ const int lda( numeric_cast<int>( (~A).spacing() ) );
+
+ trmv( ( IsRowMajorMatrix<MT>::value )?( CblasRowMajor ):( CblasColMajor ),
+ uplo, CblasTrans, CblasNonUnit, n, (~A).data(), lda, (~x).data(), 1 );
+}
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/blas/trsm.h b/src/cpu/blaze/math/blas/trsm.h
new file mode 100644
index 00000000..75f09d69
--- /dev/null
+++ b/src/cpu/blaze/math/blas/trsm.h
@@ -0,0 +1,358 @@
+//=================================================================================================
+/*!
+// \file blaze/math/blas/trsm.h
+// \brief Header file for BLAS triangular system solver functions (trsm)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_BLAS_TRSM_H_
+#define _BLAZE_MATH_BLAS_TRSM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/ConstDataAccess.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLAS WRAPPER FUNCTIONS (TRSM)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name BLAS wrapper functions (trsm) */
+//@{
+#if BLAZE_BLAS_MODE
+
+BLAZE_ALWAYS_INLINE void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ float alpha, const float* A, int lda, float* B, int ldb );
+
+BLAZE_ALWAYS_INLINE void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ double alpha, const double* A, int lda, double* B, int ldb );
+
+BLAZE_ALWAYS_INLINE void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ complex<float> alpha, const complex<float>* A, int lda,
+ complex<float>* B, int ldb );
+
+BLAZE_ALWAYS_INLINE void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ complex<double> alpha, const complex<double>* A, int lda,
+ complex<double>* B, int ldb );
+
+template< typename MT, bool SO, typename VT, bool TF, typename ST >
+BLAZE_ALWAYS_INLINE void trsm( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2, typename ST >
+BLAZE_ALWAYS_INLINE void trsm( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha );
+
+#endif
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for solving a triangular system of equations with single precision matrices
+// (\f$ A*X=\alpha*B \f$ or \f$ X*A=\alpha*B \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a B (\a CblasRowMajor or \a CblasColMajor).
+// \param side \a CblasLeft to compute \f$ A*X=\alpha*B \f$, \a CblasRight to compute \f$ X*A=\alpha*B \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param m The number of rows of matrix \a B \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ B \f$.
+// \param A Pointer to the first element of the triangular matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \return void
+//
+// This function solves a triangular system of equations with multiple values for the right side
+// based on the cblas_strsm() function. During the solution process, matrix \a B is overwritten
+// with the resulting matrix \a X. Note that matrix \a A is expected to be a square matrix.
+*/
+BLAZE_ALWAYS_INLINE void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ float alpha, const float* A, int lda, float* B, int ldb )
+{
+ cblas_strsm( order, side, uplo, transA, diag, m, n, alpha, A, lda, B, ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for solving a triangular system of equations with double precision matrices
+// (\f$ A*X=\alpha*B \f$ or \f$ X*A=\alpha*B \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a B (\a CblasRowMajor or \a CblasColMajor).
+// \param side \a CblasLeft to compute \f$ A*X=\alpha*B \f$, \a CblasRight to compute \f$ X*A=\alpha*B \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param m The number of rows of matrix \a B \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ B \f$.
+// \param A Pointer to the first element of the triangular matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \return void
+//
+// This function solves a triangular system of equations with multiple values for the right side
+// based on the cblas_dtrsm() function. During the solution process, matrix \a B is overwritten
+// with the resulting matrix \a X. Note that matrix \a A is expected to be a square matrix.
+*/
+BLAZE_ALWAYS_INLINE void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ double alpha, const double* A, int lda, double* B, int ldb )
+{
+ cblas_dtrsm( order, side, uplo, transA, diag, m, n, alpha, A, lda, B, ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for solving a triangular system of equations with single precision complex
+// matrices (\f$ A*X=\alpha*B \f$ or \f$ X*A=\alpha*B \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a B (\a CblasRowMajor or \a CblasColMajor).
+// \param side \a CblasLeft to compute \f$ A*X=\alpha*B \f$, \a CblasRight to compute \f$ X*A=\alpha*B \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param m The number of rows of matrix \a B \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ B \f$.
+// \param A Pointer to the first element of the triangular matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \return void
+//
+// This function solves a triangular system of equations with multiple values for the right side
+// based on the cblas_ctrsm() function. During the solution process, matrix \a B is overwritten
+// with the resulting matrix \a X. Note that matrix \a A is expected to be a square matrix.
+*/
+BLAZE_ALWAYS_INLINE void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ complex<float> alpha, const complex<float>* A, int lda,
+ complex<float>* B, int ldb )
+{
+ cblas_ctrsm( order, side, uplo, transA, diag, m, n, &alpha, A, lda, B, ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for solving a triangular system of equations with double precision complex
+// matrices (\f$ A*X=\alpha*B \f$ or \f$ X*A=\alpha*B \f$).
+// \ingroup blas
+//
+// \param order Specifies the storage order of matrix \a B (\a CblasRowMajor or \a CblasColMajor).
+// \param side \a CblasLeft to compute \f$ A*X=\alpha*B \f$, \a CblasRight to compute \f$ X*A=\alpha*B \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param transA Specifies whether to transpose matrix \a A (\a CblasNoTrans or \a CblasTrans).
+// \param diag Specifies whether \a A is unitriangular (\a CblasNonUnit or \a CblasUnit).
+// \param m The number of rows of matrix \a B \f$[0..\infty)\f$.
+// \param n The number of columns of matrix \a B \f$[0..\infty)\f$.
+// \param alpha The scaling factor for \f$ B \f$.
+// \param A Pointer to the first element of the triangular matrix \a A.
+// \param lda The total number of elements between two rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of matrix \a B.
+// \param ldb The total number of elements between two rows/columns of matrix \a B \f$[0..\infty)\f$.
+// \return void
+//
+// This function solves a triangular system of equations with multiple values for the right side
+// based on the cblas_ztrsm() function. During the solution process, matrix \a B is overwritten
+// with the resulting matrix \a X. Note that matrix \a A is expected to be a square matrix.
+*/
+BLAZE_ALWAYS_INLINE void trsm( CBLAS_ORDER order, CBLAS_SIDE side, CBLAS_UPLO uplo,
+ CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, int m, int n,
+ complex<double> alpha, const complex<double>* A, int lda,
+ complex<double>* B, int ldb )
+{
+ cblas_ztrsm( order, side, uplo, transA, diag, m, n, &alpha, A, lda, B, ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for solving a triangular system of equations (\f$ A*x=\alpha*b \f$ or
+// \f$ x*A=\alpha*b \f$).
+// \ingroup blas
+//
+// \param A The system matrix.
+// \param b The right-hand side vector.
+// \param side \a CblasLeft to compute \f$ A*x=\alpha*b \f$, \a CblasRight to compute \f$ x*A=\alpha*b \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param alpha The scaling factor for \f$ b \f$.
+// \return void
+//
+// This function solves a triangular system of equations based on the BLAS trsm() functions.
+// During the solution process, vector \a b is overwritten with the resulting vector \a x. Note
+// that the function only works for matrices with \c float, \c double, \c complex<float>, and
+// \c complex<double> element type. The attempt to call the function with matrices of any other
+// element type results in a compile time error. Also note that matrix \a A is expected to be a
+// square matrix.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side matrix
+ , bool TF // Storage order of the right-hand side matrix
+ , typename ST > // Type of the scalar factor
+BLAZE_ALWAYS_INLINE void trsm( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<VT> );
+
+ BLAZE_INTERNAL_ASSERT( (~A).rows() == (~A).columns(), "Non-square triangular matrix detected" );
+ BLAZE_INTERNAL_ASSERT( side == CblasLeft || side == CblasRight, "Invalid side argument detected" );
+ BLAZE_INTERNAL_ASSERT( uplo == CblasLower || uplo == CblasUpper, "Invalid uplo argument detected" );
+
+ const int m ( ( side == CblasLeft )?( numeric_cast<int>( (~b).size() ) ):( 1 ) );
+ const int n ( ( side == CblasRight )?( numeric_cast<int>( (~b).size() ) ):( 1 ) );
+ const int lda( numeric_cast<int>( (~A).spacing() ) );
+ const int ldb( ( IsRowMajorMatrix<MT>::value )?( n ):( m ) );
+
+ trsm( ( IsRowMajorMatrix<MT>::value )?( CblasRowMajor ):( CblasColMajor ),
+ side,
+ uplo,
+ CblasNoTrans,
+ CblasNonUnit,
+ m, n, alpha, (~A).data(), lda, (~b).data(), ldb );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if BLAZE_BLAS_MODE
+/*!\brief BLAS kernel for solving a triangular system of equations (\f$ A*X=\alpha*B \f$ or
+// \f$ X*A=\alpha*B \f$).
+// \ingroup blas
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param side \a CblasLeft to compute \f$ A*X=\alpha*B \f$, \a CblasRight to compute \f$ X*A=\alpha*B \f$.
+// \param uplo \a CblasLower to use the lower triangle from \a A, \a CblasUpper to use the upper triangle.
+// \param alpha The scaling factor for \f$ B \f$.
+// \return void
+//
+// This function solves a triangular system of equations with multiple values for the right side
+// based on the BLAS trsm() functions. During the solution process, matrix \a B is overwritten
+// with the resulting matrix \a X. Note that the function only works for matrices with \c float,
+// \c double, \c complex<float>, and \c complex<double> element type. The attempt to call the
+// function with matrices of any other element type results in a compile time error. Also note
+// that matrix \a A is expected to be a square matrix.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 // Storage order of the right-hand side matrix
+ , typename ST > // Type of the scalar factor
+BLAZE_ALWAYS_INLINE void trsm( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS ( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~A).rows() == (~A).columns(), "Non-square triangular matrix detected" );
+ BLAZE_INTERNAL_ASSERT( side == CblasLeft || side == CblasRight, "Invalid side argument detected" );
+ BLAZE_INTERNAL_ASSERT( uplo == CblasLower || uplo == CblasUpper, "Invalid uplo argument detected" );
+
+ const int m ( numeric_cast<int>( (~B).rows() ) );
+ const int n ( numeric_cast<int>( (~B).columns() ) );
+ const int lda( numeric_cast<int>( (~A).spacing() ) );
+ const int ldb( numeric_cast<int>( (~B).spacing() ) );
+
+ trsm( ( IsRowMajorMatrix<MT2>::value )?( CblasRowMajor ):( CblasColMajor ),
+ side,
+ ( SO1 == SO2 )?( uplo ):( ( uplo == CblasLower )?( CblasUpper ):( CblasLower ) ),
+ ( SO1 == SO2 )?( CblasNoTrans ):( CblasTrans ),
+ CblasNonUnit,
+ m, n, alpha, (~A).data(), lda, (~B).data(), ldb );
+}
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Adaptor.h b/src/cpu/blaze/math/constraints/Adaptor.h
new file mode 100644
index 00000000..26df38c5
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Adaptor.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Adaptor.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_ADAPTOR_H_
+#define _BLAZE_MATH_CONSTRAINTS_ADAPTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsAdaptor.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_ADAPTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an adaptor type (as for instance a LowerMatrix,
+// UpperMatrix, or SymmetricMatrix) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_ADAPTOR_TYPE(T) \
+ static_assert( ::blaze::IsAdaptor<T>::value, "Non-adaptor type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_ADAPTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an adaptor type (as for instance LowerMatrix, UpperMatrix,
+// or SymmetricMatrix) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE(T) \
+ static_assert( !::blaze::IsAdaptor<T>::value, "Adaptor type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/AddExpr.h b/src/cpu/blaze/math/constraints/AddExpr.h
new file mode 100644
index 00000000..5a3a1f2f
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/AddExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/AddExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_ADDEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_ADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsAddExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_ADDEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an addition expression (i.e. a type derived from the
+// AddExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_ADDEXPR_TYPE(T) \
+ static_assert( ::blaze::IsAddExpr<T>::value, "Non-addition expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_ADDEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an addition expression (i.e. a type derived from the
+// AddExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_ADDEXPR_TYPE(T) \
+ static_assert( !::blaze::IsAddExpr<T>::value, "Addition expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Aligned.h b/src/cpu/blaze/math/constraints/Aligned.h
new file mode 100644
index 00000000..cf1f4834
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Aligned.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Aligned.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_ALIGNED_H_
+#define _BLAZE_MATH_CONSTRAINTS_ALIGNED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsAligned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_ALIGNED_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does not provide aligned data values with respect to the
+// requirements of the available instruction set a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_ALIGNED_TYPE(T) \
+ static_assert( ::blaze::IsAligned<T>::value, "Non-aligned type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_ALIGNED_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does provide aligned data values with respect to the
+// requirements of the available instruction set a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_ALIGNED_TYPE(T) \
+ static_assert( !::blaze::IsAligned<T>::value, "Aligned type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/BLASCompatible.h b/src/cpu/blaze/math/constraints/BLASCompatible.h
new file mode 100644
index 00000000..bec44b13
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/BLASCompatible.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/BLASCompatible.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_BLASCOMPATIBLE_H_
+#define _BLAZE_MATH_CONSTRAINTS_BLASCOMPATIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_BLAS_COMPATIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a BLAS compatible data type (i.e. float, double,
+// complex<float>, or complex<double>), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE(T) \
+ static_assert( ::blaze::IsBLASCompatible<T>::value, "Non-BLAS compatible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_BLAS_COMPATIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a BLAS compatible type (i.e. float, double, complex<float>,
+// or complex<double>), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_BLAS_COMPATIBLE_TYPE(T) \
+ static_assert( !::blaze::IsBLASCompatible<T>::value, "BLAS compatible type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Column.h b/src/cpu/blaze/math/constraints/Column.h
new file mode 100644
index 00000000..a8f5dcb5
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Column.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Column.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_COLUMN_H_
+#define _BLAZE_MATH_CONSTRAINTS_COLUMN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumn.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_COLUMN_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a column type (i.e. a dense or sparse column), a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_TYPE(T) \
+ static_assert( ::blaze::IsColumn<T>::value, "Non-column type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COLUMN_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a column type (i.e. a dense or sparse column), a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COLUMN_TYPE(T) \
+ static_assert( !::blaze::IsColumn<T>::value, "Column type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/ColumnMajorMatrix.h b/src/cpu/blaze/math/constraints/ColumnMajorMatrix.h
new file mode 100644
index 00000000..3e3a10e4
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/ColumnMajorMatrix.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/ColumnMajorMatrix.h
+// \brief Constraints on the storage order of matrix types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_COLUMNMAJORMATRIX_H_
+#define _BLAZE_MATH_CONSTRAINTS_COLUMNMAJORMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_COLUMN_MAJOR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a column-major dense or sparse matrix type (i.e. a
+// matrix type whose storage order is set to \a true) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsColumnMajorMatrix<T>::value, "Non-column-major matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COLUMN_MAJOR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a column-major dense or sparse matrix type (i.e. a matrix
+// type whose storage order is set to \a true) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COLUMN_MAJOR_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsColumnMajorMatrix<T>::value, "Column-major matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/ColumnVector.h b/src/cpu/blaze/math/constraints/ColumnVector.h
new file mode 100644
index 00000000..4cf652e2
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/ColumnVector.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/ColumnVector.h
+// \brief Constraint on the transpose flag of vector types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_COLUMNVECTOR_H_
+#define _BLAZE_MATH_CONSTRAINTS_COLUMNVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnVector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_COLUMN_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a column dense or sparse vector type (i.e. a vector
+// type whose transposition flag is set to blaze::columnVector) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE(T) \
+ static_assert( ::blaze::IsColumnVector<T>::value, "Non-column vector type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COLUMN_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a column dense or sparse vector type (i.e. a vector type
+// whose transposition flag is set to blaze::columnVector) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COLUMN_VECTOR_TYPE(T) \
+ static_assert( !::blaze::IsColumnVector<T>::value, "Column vector type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Columns.h b/src/cpu/blaze/math/constraints/Columns.h
new file mode 100644
index 00000000..322a197e
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Columns.h
@@ -0,0 +1,101 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Columns.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_COLUMNS_H_
+#define _BLAZE_MATH_CONSTRAINTS_COLUMNS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_HAVE_EQUAL_NUMBER_OF_COLUMNS CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the number of columns of the two given matrix types \a T1 and \a T2 can be evaluated
+// at compile time and in case the number of columns is not equal, a compilation error is created.
+// Note that in case the number of columns of either of the two matrix types cannot be determined
+// no compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_EQUAL_NUMBER_OF_COLUMNS(T1,T2) \
+ static_assert( ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Columns<T2> > \
+ >::value, "Invalid number of columns detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_EQUAL_NUMBER_OF_COLUMNS CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the number of columns of the two given matrix types \a T1 and \a T2 can be evaluated at
+// compile time and in case the number of columns is equal, a compilation error is created. Note
+// that in case the number of columns of either of the two matrix types cannot be determined no
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_EQUAL_NUMBER_OF_COLUMNS(T1,T2) \
+ static_assert( ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Not< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Columns<T2> > > \
+ >::value, "Invalid number of columns detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Computation.h b/src/cpu/blaze/math/constraints/Computation.h
new file mode 100644
index 00000000..32eb1920
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Computation.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Computation.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_COMPUTATION_H_
+#define _BLAZE_MATH_CONSTRAINTS_COMPUTATION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsComputation.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_COMPUTATION_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a computational expression (i.e. a type derived from
+// the Computation base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COMPUTATION_TYPE(T) \
+ static_assert( ::blaze::IsComputation<T>::value, "Non-computation type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COMPUTATION_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a computational expression (i.e. a type derived from the
+// Computation base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE(T) \
+ static_assert( !::blaze::IsComputation<T>::value, "Computation type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/ConstDataAccess.h b/src/cpu/blaze/math/constraints/ConstDataAccess.h
new file mode 100644
index 00000000..bf80d3c8
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/ConstDataAccess.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/ConstDataAccess.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_CONSTDATAACCESS_H_
+#define _BLAZE_MATH_CONSTRAINTS_CONSTDATAACCESS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_HAVE_CONST_DATA_ACCESS CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does not provide low-level data access to constant data,
+// i.e. does not have a const 'data' member function, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS(T) \
+ static_assert( ::blaze::HasConstDataAccess<T>::value, "Type without const data access detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_CONST_DATA_ACCESS CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does provide low-level data access to constant data, i.e.
+// does have a const 'data' member function, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_CONST_DATA_ACCESS(T) \
+ static_assert( !::blaze::HasConstDataAccess<T>::value, "Type with const data access detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Constraints.h b/src/cpu/blaze/math/constraints/Constraints.h
new file mode 100644
index 00000000..889af2ed
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Constraints.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Constraints.h
+// \brief Documentation for the mathematical constraints module
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_CONSTRAINTS_H_
+#define _BLAZE_MATH_CONSTRAINTS_CONSTRAINTS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup math_constraints Compile time constraints
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/CrossExpr.h b/src/cpu/blaze/math/constraints/CrossExpr.h
new file mode 100644
index 00000000..7f18c812
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/CrossExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/CrossExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_CROSSEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_CROSSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsCrossExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_CROSSEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a cross product expression (i.e. a type derived from
+// the CrossExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_CROSSEXPR_TYPE(T) \
+ static_assert( ::blaze::IsCrossExpr<T>::value, "Non-cross product expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_CROSSEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a cross product expression (i.e. a type derived from the
+// CrossExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_CROSSEXPR_TYPE(T) \
+ static_assert( !::blaze::IsCrossExpr<T>::value, "Cross product expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Custom.h b/src/cpu/blaze/math/constraints/Custom.h
new file mode 100644
index 00000000..9833f65e
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Custom.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Custom.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_CUSTOM_H_
+#define _BLAZE_MATH_CONSTRAINTS_CUSTOM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsCustom.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_CUSTOM_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a custom data type, i.e. a custom vector or matrix,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_CUSTOM_TYPE(T) \
+ static_assert( ::blaze::IsCustom<T>::value, "Non-custom type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_CUSTOM_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a custom data type, i.e. a custom vector or matrix,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_CUSTOM_TYPE(T) \
+ static_assert( !::blaze::IsCustom<T>::value, "Custom type dected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/DenseMatrix.h b/src/cpu/blaze/math/constraints/DenseMatrix.h
new file mode 100644
index 00000000..6d741380
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/DenseMatrix.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/DenseMatrix.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_DENSEMATRIX_H_
+#define _BLAZE_MATH_CONSTRAINTS_DENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_DENSE_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a dense, N-dimensional matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsDenseMatrix<T>::value, "Non-dense matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_DENSE_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a dense, N-dimensional matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_DENSE_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsDenseMatrix<T>::value, "Dense matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/DenseVector.h b/src/cpu/blaze/math/constraints/DenseVector.h
new file mode 100644
index 00000000..b3318f80
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/DenseVector.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/DenseVector.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_DENSEVECTOR_H_
+#define _BLAZE_MATH_CONSTRAINTS_DENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsDenseVector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_DENSE_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a dense, N-dimensional vector type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE(T) \
+ static_assert( ::blaze::IsDenseVector<T>::value, "Non-dense vector type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_DENSE_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a dense, N-dimensional vector type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_DENSE_VECTOR_TYPE(T) \
+ static_assert( !::blaze::IsDenseVector<T>::value, "Dense vector type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Diagonal.h b/src/cpu/blaze/math/constraints/Diagonal.h
new file mode 100644
index 00000000..989aabbb
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Diagonal.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Diagonal.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_DIAGONAL_H_
+#define _BLAZE_MATH_CONSTRAINTS_DIAGONAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsDiagonal.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_DIAGONAL_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a diagonal matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_DIAGONAL_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsDiagonal<T>::value, "Non-diagonal matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_DIAGONAL_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a diagonal matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsDiagonal<T>::value, "Diagonal matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/DivExpr.h b/src/cpu/blaze/math/constraints/DivExpr.h
new file mode 100644
index 00000000..c1098324
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/DivExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/DivExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_DIVEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_DIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsDivExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_DIVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a division expression (i.e. a type derived from the
+// DivExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_DIVEXPR_TYPE(T) \
+ static_assert( ::blaze::IsDivExpr<T>::value, "Non-division expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_DIVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a division expression (i.e. a type derived from the
+// DivExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_DIVEXPR_TYPE(T) \
+ static_assert( !::blaze::IsDivExpr<T>::value, "Division expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/EvalExpr.h b/src/cpu/blaze/math/constraints/EvalExpr.h
new file mode 100644
index 00000000..3ee1fbd9
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/EvalExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/EvalExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_EVALEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_EVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsEvalExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_EVALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an evaluation expression (i.e. a type derived from
+// the EvalExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_EVALEXPR_TYPE(T) \
+ static_assert( ::blaze::IsEvalExpr<T>::value, "Non-evaluation expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_EVALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an evaluation expression (i.e. a type derived from the
+// EvalExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_EVALEXPR_TYPE(T) \
+ static_assert( !::blaze::IsEvalExpr<T>::value, "Evaluation expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Expression.h b/src/cpu/blaze/math/constraints/Expression.h
new file mode 100644
index 00000000..b602ac91
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Expression.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Expression.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_EXPRESSION_H_
+#define _BLAZE_MATH_CONSTRAINTS_EXPRESSION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsExpression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_EXPRESSION_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an expression (i.e. a type derived from the Expression
+// base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE(T) \
+ static_assert( ::blaze::IsExpression<T>::value, "Non-expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_EXPRESSION_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an expression (i.e. a type derived from the Expression
+// base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_EXPRESSION_TYPE(T) \
+ static_assert( !::blaze::IsExpression<T>::value, "Expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/ForEachExpr.h b/src/cpu/blaze/math/constraints/ForEachExpr.h
new file mode 100644
index 00000000..532fbdf1
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/ForEachExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/ForEachExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_FOREACHEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_FOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsForEachExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_FOREACHEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a for-each expression (i.e. a type derived from the
+// ForEachExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_FOREACHEXPR_TYPE(T) \
+ static_assert( ::blaze::IsForEachExpr<T>::value, "Non-for-each expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_FOREACHEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a for-each expression (i.e. a type derived from the
+// ForEachExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_FOREACHEXPR_TYPE(T) \
+ static_assert( !::blaze::IsForEachExpr<T>::value, "For-each expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/General.h b/src/cpu/blaze/math/constraints/General.h
new file mode 100644
index 00000000..69e0e273
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/General.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/General.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_GENERAL_H_
+#define _BLAZE_MATH_CONSTRAINTS_GENERAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsGeneral.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_GENERAL_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a general matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_GENERAL_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsGeneral<T>::value, "Non-general matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_GENERAL_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a general matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_GENERAL_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsGeneral<T>::value, "General matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Hermitian.h b/src/cpu/blaze/math/constraints/Hermitian.h
new file mode 100644
index 00000000..08b09cd5
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Hermitian.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Hermitian.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_HERMITIAN_H_
+#define _BLAZE_MATH_CONSTRAINTS_HERMITIAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsHermitian.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_HERMITIAN_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an Hermitian matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_HERMITIAN_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsHermitian<T>::value, "Non-Hermitian matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_HERMITIAN_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an Hermitian matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsHermitian<T>::value, "Hermitian matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Identity.h b/src/cpu/blaze/math/constraints/Identity.h
new file mode 100644
index 00000000..5e8903c3
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Identity.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Identity.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_IDENTITY_H_
+#define _BLAZE_MATH_CONSTRAINTS_IDENTITY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsIdentity.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_IDENTITY_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an identity matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_IDENTITY_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsIdentity<T>::value, "Non-identity matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_IDENTITY_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an identity matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_IDENTITY_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsIdentity<T>::value, "Identity matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Invertible.h b/src/cpu/blaze/math/constraints/Invertible.h
new file mode 100644
index 00000000..da19f368
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Invertible.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Invertible.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_INVERTIBLE_H_
+#define _BLAZE_MATH_CONSTRAINTS_INVERTIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsInvertible.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_INVERTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an invertible data type (i.e. a BLAS compatible type,
+// <tt>long double</tt>, or any matrix with BLAS compatible element type), a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_INVERTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsInvertible<T>::value, "Non-invertible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_INVERTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an invertible data type (i.e. a BLAS compatible type,
+// <tt>long double</tt>, or any matrix with BLAS compatible element type), a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_INVERTIBLE_TYPE(T) \
+ static_assert( !blaze::IsInvertible<T>::value, "Invertible type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Lower.h b/src/cpu/blaze/math/constraints/Lower.h
new file mode 100644
index 00000000..a4cc6602
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Lower.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Lower.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_LOWER_H_
+#define _BLAZE_MATH_CONSTRAINTS_LOWER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsLower.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_LOWER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a lower triangular matrix type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_LOWER_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsLower<T>::value, "Non-lower triangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_LOWER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a lower triangular matrix type, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsLower<T>::value, "Lower triangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatEvalExpr.h b/src/cpu/blaze/math/constraints/MatEvalExpr.h
new file mode 100644
index 00000000..a77ad21d
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatEvalExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatEvalExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATEVALEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatEvalExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATEVALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix evaluation expression (i.e. a type derived
+// from the MatEvalExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATEVALEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatEvalExpr<T>::value, "Non-matrix evaluation expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATEVALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix evaluation expression (i.e. a type derived from
+// the MatEvalExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATEVALEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatEvalExpr<T>::value, "Matrix evaluation expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatForEachExpr.h b/src/cpu/blaze/math/constraints/MatForEachExpr.h
new file mode 100644
index 00000000..0c1d8382
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatForEachExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatForEachExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATFOREACHEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatForEachExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATFOREACHEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix for-each expression (i.e. a type derived
+// from the MatForEachExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATFOREACHEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatForEachExpr<T>::value, "Non-matrix for-each expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATFOREACHEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix for-each expression (i.e. a type derived from
+// the MatForEachExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATFOREACHEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatForEachExpr<T>::value, "Matrix for-each expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatInvExpr.h b/src/cpu/blaze/math/constraints/MatInvExpr.h
new file mode 100644
index 00000000..7135fe0b
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatInvExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatInvExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATINVEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATINVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatInvExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATINVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix inversion expression (i.e. a type derived
+// from the MatInvExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATINVEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatInvExpr<T>::value, "Non-matrix inversion expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATINVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix inversion expression (i.e. a type derived from
+// the MatInvExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATINVEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatInvExpr<T>::value, "Matrix inversion expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatMatAddExpr.h b/src/cpu/blaze/math/constraints/MatMatAddExpr.h
new file mode 100644
index 00000000..faba790a
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatMatAddExpr.h
@@ -0,0 +1,151 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatMatAddExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATMATADDEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsMatMatAddExpr.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATMATADDEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix/matrix addition expression (i.e. a type
+// derived from the MatMatAddExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATMATADDEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatMatAddExpr<T>::value, "Non-matrix/matrix addition expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATMATADDEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix/matrix addition expression (i.e. a type derived
+// from the MatMatAddExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATADDEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatMatAddExpr<T>::value, "Matrix/matrix addition expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_MATMATADDEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid matrix/matrix addition,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::IsMatrix<T1> \
+ , ::blaze::IsMatrix<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::Rows<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Columns<T2> > > \
+ >::value, "Invalid matrix/matrix addition expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_MATMATADDEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid matrix/matrix addition, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_MATMATADDEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::IsMatrix<T1> \
+ , ::blaze::IsMatrix<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::Rows<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Columns<T2> > > > \
+ >::value, "Valid matrix/matrix addition expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatMatMultExpr.h b/src/cpu/blaze/math/constraints/MatMatMultExpr.h
new file mode 100644
index 00000000..cc258ae4
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatMatMultExpr.h
@@ -0,0 +1,145 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatMatMultExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATMATMULTEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATMATMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix/matrix multiplication expression (i.e. a type
+// derived from the MatMatMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATMATMULTEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatMatMultExpr<T>::value, "Non-matrix/matrix multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATMATMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix/matrix multiplication expression (i.e. a type
+// derived from the MatMatMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATMULTEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatMatMultExpr<T>::value, "Matrix/matrix multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_MATMATMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid matrix/matrix multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::IsMatrix<T1> \
+ , ::blaze::IsMatrix<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Rows<T2> > > \
+ >::value, "Invalid matrix/matrix multiplication expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_MATMATMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid matrix/matrix multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_MATMATMULTEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::IsMatrix<T1> \
+ , ::blaze::IsMatrix<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Rows<T2> > > > \
+ >::value, "Valid matrix/matrix multiplication expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatMatSubExpr.h b/src/cpu/blaze/math/constraints/MatMatSubExpr.h
new file mode 100644
index 00000000..d558d863
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatMatSubExpr.h
@@ -0,0 +1,151 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatMatSubExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATMATSUBEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsMatMatSubExpr.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATMATSUBEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix/matrix subtraction expression (i.e. a type
+// derived from the MatMatSubExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATMATSUBEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatMatSubExpr<T>::value, "Non-matrix/matrix subtraction expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATMATSUBEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix/matrix subtraction expression (i.e. a type derived
+// from the MatMatSubExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATSUBEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatMatSubExpr<T>::value, "Matrix/matrix subtraction expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_MATMATSUBEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid matrix/matrix subtraction,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::IsMatrix<T1> \
+ , ::blaze::IsMatrix<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::Rows<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Columns<T2> > > \
+ >::value, "Invalid matrix/matrix subtraction expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_MATMATSUBEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid matrix/matrix subtraction, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_MATMATSUBEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::IsMatrix<T1> \
+ , ::blaze::IsMatrix<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::Rows<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Columns<T2> > > > \
+ >::value, "Valid matrix/matrix subtraction expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatScalarDivExpr.h b/src/cpu/blaze/math/constraints/MatScalarDivExpr.h
new file mode 100644
index 00000000..f5186df9
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatScalarDivExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatScalarDivExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATSCALARDIVEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatScalarDivExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATSCALARDIVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix/scalar division expression (i.e. a type
+// derived from the MatScalarDivExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATSCALARDIVEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatScalarDivExpr<T>::value, "Non-matrix/scalar division expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATSCALARDIVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix/scalar division expression (i.e. a type derived
+// from the MatScalarDivExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATSCALARDIVEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatScalarDivExpr<T>::value, "Matrix/scalar division expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatScalarMultExpr.h b/src/cpu/blaze/math/constraints/MatScalarMultExpr.h
new file mode 100644
index 00000000..511feb8b
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatScalarMultExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatScalarMultExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATSCALARMULTEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatScalarMultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATSCALARMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix/scalar multiplication expression (i.e. a type
+// derived from the MatScalarMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATSCALARMULTEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatScalarMultExpr<T>::value, "Non-matrix/scalar multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATSCALARMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix/scalar multiplication expression (i.e. a type
+// derived from the MatScalarMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATSCALARMULTEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatScalarMultExpr<T>::value, "Matrix/scalar multiplication expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatSerialExpr.h b/src/cpu/blaze/math/constraints/MatSerialExpr.h
new file mode 100644
index 00000000..8edc240b
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatSerialExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatSerialExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATSERIALEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatSerialExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATSERIALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix serial evaluation expression (i.e. a type
+// derived from the MatSerialExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATSERIALEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatSerialExpr<T>::value, "Non-matrix serial evaluation expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATSERIALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix serial evaluation expression (i.e. a type derived
+// from the MatSerialExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATSERIALEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatSerialExpr<T>::value, "Matrix serial evaluation expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatTransExpr.h b/src/cpu/blaze/math/constraints/MatTransExpr.h
new file mode 100644
index 00000000..ecc0143d
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatTransExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatTransExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATTRANSEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatTransExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATTRANSEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix transposition expression (i.e. a type derived
+// from the MatTransExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATTRANSEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatTransExpr<T>::value, "Non-matrix transposition expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATTRANSEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix transposition expression (i.e. a type derived from
+// the MatTransExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATTRANSEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatTransExpr<T>::value, "Matrix transposition expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MatVecMultExpr.h b/src/cpu/blaze/math/constraints/MatVecMultExpr.h
new file mode 100644
index 00000000..6ca00067
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MatVecMultExpr.h
@@ -0,0 +1,146 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MatVecMultExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATVECMULTEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsMatVecMultExpr.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATVECMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a matrix/vector multiplication expression (i.e. a type
+// derived from the MatVecMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATVECMULTEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMatVecMultExpr<T>::value, "Non-matrix/vector multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATVECMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a matrix/vector multiplication expression (i.e. a type
+// derived from the MatVecMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATVECMULTEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMatVecMultExpr<T>::value, "Matrix/vector multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_MATVECMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid matrix/vector multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::IsMatrix<T1> \
+ , ::blaze::IsColumnVector<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Size<T2> > > \
+ >::value, "Invalid matrix/vector multiplication expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_MATVECMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid matrix/vector multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_MATVECMULTEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::IsMatrix<T1> \
+ , ::blaze::IsColumnVector<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Columns<T1>, ::blaze::Size<T2> > > > \
+ >::value, "Valid matrix/vector multiplication expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Matrix.h b/src/cpu/blaze/math/constraints/Matrix.h
new file mode 100644
index 00000000..42ca72d4
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Matrix.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Matrix.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MATRIX_H_
+#define _BLAZE_MATH_CONSTRAINTS_MATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a N-dimensional matrix type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsMatrix<T>::value, "Non-matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a N-dimensional matrix type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsMatrix<T>::value, "Matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MultExpr.h b/src/cpu/blaze/math/constraints/MultExpr.h
new file mode 100644
index 00000000..5bb43491
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MultExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MultExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MULTEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_MULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a multiplication expression (i.e. a type derived from
+// the MultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MULTEXPR_TYPE(T) \
+ static_assert( ::blaze::IsMultExpr<T>::value, "Non-multiplication expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a multiplication expression (i.e. a type derived from the
+// MultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MULTEXPR_TYPE(T) \
+ static_assert( !::blaze::IsMultExpr<T>::value, "Multiplication expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/MutableDataAccess.h b/src/cpu/blaze/math/constraints/MutableDataAccess.h
new file mode 100644
index 00000000..13e7e418
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/MutableDataAccess.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/MutableDataAccess.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_MUTABLEDATAACCESS_H_
+#define _BLAZE_MATH_CONSTRAINTS_MUTABLEDATAACCESS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_HAVE_MUTABLE_DATA_ACCESS CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does not provide low-level data access to mutable data,
+// i.e. does not have a non-const 'data' member function, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS(T) \
+ static_assert( ::blaze::HasMutableDataAccess<T>::value, "Type without mutable data access detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_MUTABLE_DATA_ACCESS CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does provide low-level data access to mutable data, i.e.
+// does have a non-const 'data' member function, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_MUTABLE_DATA_ACCESS(T) \
+ static_assert( !::blaze::HasMutableDataAccess<T>::value, "Type with mutable data access detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/NumericMatrix.h b/src/cpu/blaze/math/constraints/NumericMatrix.h
new file mode 100644
index 00000000..f8c04c2b
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/NumericMatrix.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/NumericMatrix.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_NUMERICMATRIX_H_
+#define _BLAZE_MATH_CONSTRAINTS_NUMERICMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsNumericMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_NUMERIC_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a numeric matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NUMERIC_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsNumericMatrix<T>::value, "Non-numeric matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NUMERIC_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a numeric matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NUMERIC_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsNumericMatrix<T>::value, "Numeric matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/NumericVector.h b/src/cpu/blaze/math/constraints/NumericVector.h
new file mode 100644
index 00000000..ca9bda7a
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/NumericVector.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/NumericVector.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_NUMERICVECTOR_H_
+#define _BLAZE_MATH_CONSTRAINTS_NUMERICVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsNumericVector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_NUMERIC_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a numeric vector type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NUMERIC_VECTOR_TYPE(T) \
+ static_assert( ::blaze::IsNumericVector<T>::value, "Non-numeric vector type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NUMERIC_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a numeric vector type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NUMERIC_VECTOR_TYPE(T) \
+ static_assert( !::blaze::IsNumericVector<T>::value, "Numeric vector type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/OpposedView.h b/src/cpu/blaze/math/constraints/OpposedView.h
new file mode 100644
index 00000000..a833d470
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/OpposedView.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/OpposedView.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_OPPOSEDVIEW_H_
+#define _BLAZE_MATH_CONSTRAINTS_OPPOSEDVIEW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsOpposedView.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_OPPOSED_VIEW CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an opposed view, i.e. is not a view that is opposed
+// to the natural storage order of its underlying type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_OPPOSED_VIEW(T) \
+ static_assert( ::blaze::IsOpposedView<T>::value, "Non-opposed view detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_OPPOSED_VIEW CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an opposed view, i.e. is a view that is opposed to the
+// natural storage order of its underlying type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_OPPOSED_VIEW(T) \
+ static_assert( !::blaze::IsOpposedView<T>::value, "Opposed view detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Padded.h b/src/cpu/blaze/math/constraints/Padded.h
new file mode 100644
index 00000000..4de88e20
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Padded.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Padded.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_PADDED_H_
+#define _BLAZE_MATH_CONSTRAINTS_PADDED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsPadded.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_PADDED_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does not employ or simulate padding (i.e. a special treatment
+// of remainder elements is necessary) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_PADDED_TYPE(T) \
+ static_assert( ::blaze::IsPadded<T>::value, "Non-padded type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_PADDED_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does employ or simulate padding (i.e. no special treatment
+// of remainder elements is necessary) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_PADDED_TYPE(T) \
+ static_assert( !::blaze::IsPadded<T>::value, "Padded type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Proxy.h b/src/cpu/blaze/math/constraints/Proxy.h
new file mode 100644
index 00000000..2ae8addc
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Proxy.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Proxy.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_PROXY_H_
+#define _BLAZE_MATH_CONSTRAINTS_PROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsProxy.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_PROXY_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a proxy type (i.e. a type derived from the Proxy class
+// template), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_PROXY_TYPE(T) \
+ static_assert( ::blaze::IsProxy<T>::value, "Non-proxy type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_PROXY_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a proxy type (i.e. a type derived from the Proxy class
+// template), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_PROXY_TYPE(T) \
+ static_assert( !::blaze::IsProxy<T>::value, "Proxy type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/RequiresEvaluation.h b/src/cpu/blaze/math/constraints/RequiresEvaluation.h
new file mode 100644
index 00000000..181c47dc
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/RequiresEvaluation.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/RequiresEvaluation.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_REQUIRESEVALUATION_H_
+#define _BLAZE_MATH_CONSTRAINTS_REQUIRESEVALUATION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_REQUIRE_EVALUATION CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does not require an intermediate evaluation within composite
+// expressions, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_REQUIRE_EVALUATION(T) \
+ static_assert( ::blaze::RequiresEvaluation<T>::value, "Type without evaluation requirement detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_REQUIRE_EVALUATION CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T requires an intermediate evaluation within composite
+// expressions, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T) \
+ static_assert( !::blaze::RequiresEvaluation<T>::value, "Type with evaluation requirement detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Resizable.h b/src/cpu/blaze/math/constraints/Resizable.h
new file mode 100644
index 00000000..fc3edc76
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Resizable.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Resizable.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_RESIZABLE_H_
+#define _BLAZE_MATH_CONSTRAINTS_RESIZABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsResizable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_RESIZABLE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not resizable, i.e. does not have a 'resize' member
+// function that could be used to change the size, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_RESIZABLE(T) \
+ static_assert( ::blaze::IsResizable<T>::value, "Non-resizable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_RESIZABLE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is resizable, i.e. has a 'resize' member function that can
+// be used to change the size, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE(T) \
+ static_assert( !::blaze::IsResizable<T>::value, "Resizable type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Restricted.h b/src/cpu/blaze/math/constraints/Restricted.h
new file mode 100644
index 00000000..9458f1dc
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Restricted.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Restricted.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_RESTRICTED_H_
+#define _BLAZE_MATH_CONSTRAINTS_RESTRICTED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsRestricted.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_RESTRICTED CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does not have a restricted data access, i.e. does not restrict
+// specific operations on its data, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_RESTRICTED(T) \
+ static_assert( ::blaze::IsRestricted<T>::value, "Unrestricted type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_RESTRICTED CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T does have a restricted data access, i.e. does not restrict
+// any operation on its data, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_RESTRICTED(T) \
+ static_assert( !::blaze::IsRestricted<T>::value, "Restricted type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Row.h b/src/cpu/blaze/math/constraints/Row.h
new file mode 100644
index 00000000..2beab821
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Row.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Row.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_ROW_H_
+#define _BLAZE_MATH_CONSTRAINTS_ROW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsRow.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_ROW_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a row type (i.e. a dense or sparse row), a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_ROW_TYPE(T) \
+ static_assert( ::blaze::IsRow<T>::value, "Non-row type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_ROW_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a row type (i.e. a dense or sparse row), a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_ROW_TYPE(T) \
+ static_assert( !::blaze::IsRow<T>::value, "Row type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/RowMajorMatrix.h b/src/cpu/blaze/math/constraints/RowMajorMatrix.h
new file mode 100644
index 00000000..990fda7d
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/RowMajorMatrix.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/RowMajorMatrix.h
+// \brief Constraints on the storage order of matrix types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_ROWMAJORMATRIX_H_
+#define _BLAZE_MATH_CONSTRAINTS_ROWMAJORMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_ROW_MAJOR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a row-major dense or sparse matrix type (i.e. a matrix
+// type whose storage order is set to \a false) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsRowMajorMatrix<T>::value, "Non-row-major matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_ROW_MAJOR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a row-major dense or sparse matrix type (i.e. a matrix
+// type whose storage order is set to \a false) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_ROW_MAJOR_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsRowMajorMatrix<T>::value, "Row-major matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/RowVector.h b/src/cpu/blaze/math/constraints/RowVector.h
new file mode 100644
index 00000000..ce82c8dc
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/RowVector.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/RowVector.h
+// \brief Constraint on the transpose flag of vector types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_ROWVECTOR_H_
+#define _BLAZE_MATH_CONSTRAINTS_ROWVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsRowVector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_ROW_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a row dense or sparse vector type (i.e. a vector type
+// whose transposition flag is set to blaze::rowVector) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE(T) \
+ static_assert( ::blaze::IsRowVector<T>::value, "Non-row vector type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_ROW_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a row dense or sparse vector type (i.e. a vector type
+// whose transposition flag is set to blaze::rowVector) a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_ROW_VECTOR_TYPE(T) \
+ static_assert( !::blaze::IsRowVector<T>::value, "Row vector type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Rows.h b/src/cpu/blaze/math/constraints/Rows.h
new file mode 100644
index 00000000..86849d88
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Rows.h
@@ -0,0 +1,101 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Rows.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_ROWS_H_
+#define _BLAZE_MATH_CONSTRAINTS_ROWS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_HAVE_EQUAL_NUMBER_OF_ROWS CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the number of rows of the two given matrix types \a T1 and \a T2 can be evaluated at
+// compile time and in case the number of rows is not equal, a compilation error is created.
+// Note that in case the number of rows of either of the two matrix types cannot be determined
+// no compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_EQUAL_NUMBER_OF_ROWS(T1,T2) \
+ static_assert( ::blaze::Or< ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::Rows<T2> > \
+ >::value, "Invalid number of rows detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_EQUAL_NUMBER_OF_ROWS CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the number of rows of the two given matrix types \a T1 and \a T2 can be evaluated at
+// compile time and in case the number of rows is equal, a compilation error is created. Note
+// that in case the number of rows of either of the two matrix types cannot be determined no
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_EQUAL_NUMBER_OF_ROWS(T1,T2) \
+ static_assert( ::blaze::Or< ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Not< ::blaze::Equal< ::blaze::Rows<T1>, ::blaze::Rows<T2> > > \
+ >::value, "Invalid number of rows detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/SIMDEnabled.h b/src/cpu/blaze/math/constraints/SIMDEnabled.h
new file mode 100644
index 00000000..e8bf8243
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/SIMDEnabled.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/SIMDEnabled.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SIMDENABLED_H_
+#define _BLAZE_MATH_CONSTRAINTS_SIMDENABLED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSIMDEnabled.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SIMD_ENABLED CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not SIMD-enabled (i.e. does not provide the according
+// SIMD member functions), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SIMD_ENABLED(T) \
+ static_assert( ::blaze::IsSIMDEnabled<T>::value, "Non-SIMD enabled type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SIMD_ENABLED CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is SIMD-enabled (i.e. does provide the according SIMD member
+// functions), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SIMD_ENABLED(T) \
+ static_assert( !::blaze::IsSIMDEnabled<T>::value, "SIMD enabled type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/SIMDPack.h b/src/cpu/blaze/math/constraints/SIMDPack.h
new file mode 100644
index 00000000..0569074e
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/SIMDPack.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/SIMDPack.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SIMDPACK_H_
+#define _BLAZE_MATH_CONSTRAINTS_SIMDPACK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSIMDPack.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SIMD_PACK CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a SIMD pack, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK(T) \
+ static_assert( ::blaze::IsSIMDPack<T>::value, "Non-SIMD pack detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SIMD_PACK CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a SIMD pack, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SIMD_PACK(T) \
+ static_assert( !::blaze::IsSIMDPack<T>::value, "SIMD pack detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/SMPAssignable.h b/src/cpu/blaze/math/constraints/SMPAssignable.h
new file mode 100644
index 00000000..7b12bfe3
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/SMPAssignable.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/SMPAssignable.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SMPASSIGNABLE_H_
+#define _BLAZE_MATH_CONSTRAINTS_SMPASSIGNABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SMP_ASSIGNABLE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not SMP-assignable (i.e. cannot be assigned by multiple
+// threads), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SMP_ASSIGNABLE(T) \
+ static_assert( ::blaze::IsSMPAssignable<T>::value, "Non-SMP assignable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SMP_ASSIGNABLE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is SMP-assignable (can be assigned by multiple threads), a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE(T) \
+ static_assert( !::blaze::IsSMPAssignable<T>::value, "SMP assignable type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/SerialExpr.h b/src/cpu/blaze/math/constraints/SerialExpr.h
new file mode 100644
index 00000000..4d21a2a7
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/SerialExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/SerialExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SERIALEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_SERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSerialExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SERIALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a serial evaluation expression (i.e. a type derived
+// from the SerialExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SERIALEXPR_TYPE(T) \
+ static_assert( ::blaze::IsSerialExpr<T>::value, "Non-serial evaluation expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SERIALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a serial evaluation expression (i.e. a type derived from
+// the SerialExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SERIALEXPR_TYPE(T) \
+ static_assert( !::blaze::IsSerialExpr<T>::value, "Serial evaluation expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Size.h b/src/cpu/blaze/math/constraints/Size.h
new file mode 100644
index 00000000..bb3bf531
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Size.h
@@ -0,0 +1,101 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Size.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SIZE_H_
+#define _BLAZE_MATH_CONSTRAINTS_SIZE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_HAVE_EQUAL_SIZE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the size of the two given vector types \a T1 and \a T2 can be evaluated at compile
+// time and in case these sizes are not equal, a compilation error is created. Note that in
+// case the size of either of the two vector types cannot be determined no compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_EQUAL_SIZE(T1,T2) \
+ static_assert( ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > \
+ >::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_EQUAL_SIZE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the size of the two given vector types \a T1 and \a T2 can be evaluated at compile
+// time and in case these sizes are equal, a compilation error is created. Note that in case
+// the size of either of the two vector types cannot be determined no compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_EQUAL_SIZE(T1,T2) \
+ static_assert( ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Not< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > \
+ >::value, "Invalid size detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/SparseElement.h b/src/cpu/blaze/math/constraints/SparseElement.h
new file mode 100644
index 00000000..00b54f10
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/SparseElement.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/SparseElement.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SPARSEELEMENT_H_
+#define _BLAZE_MATH_CONSTRAINTS_SPARSEELEMENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSparseElement.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SPARSE_ELEMENT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a sparse element type (i.e. a type derived from the
+// SparseElement base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_ELEMENT_TYPE(T) \
+ static_assert( ::blaze::IsSparseElement<T>::value, "Non-sparse element type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SPARSE_ELEMENT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a sparse element type (i.e. a type derived from the
+// SparseElement base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SPARSE_ELEMENT_TYPE(T) \
+ static_assert( !::blaze::IsSparseElement<T>::value, "Sparse element type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/SparseMatrix.h b/src/cpu/blaze/math/constraints/SparseMatrix.h
new file mode 100644
index 00000000..820b463b
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/SparseMatrix.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/SparseMatrix.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SPARSEMATRIX_H_
+#define _BLAZE_MATH_CONSTRAINTS_SPARSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SPARSE_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a sparse, N-dimensional matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsSparseMatrix<T>::value, "Non-sparse matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SPARSE_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a sparse, N-dimensional matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SPARSE_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsSparseMatrix<T>::value, "Sparse matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/SparseVector.h b/src/cpu/blaze/math/constraints/SparseVector.h
new file mode 100644
index 00000000..ba9bf04e
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/SparseVector.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/SparseVector.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SPARSEVECTOR_H_
+#define _BLAZE_MATH_CONSTRAINTS_SPARSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSparseVector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SPARSE_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a sparse, N-dimensional vector type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE(T) \
+ static_assert( ::blaze::IsSparseVector<T>::value, "Non-sparse vector type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SPARSE_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a sparse, N-dimensional vector type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SPARSE_VECTOR_TYPE(T) \
+ static_assert( !::blaze::IsSparseVector<T>::value, "Sparse vector type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Square.h b/src/cpu/blaze/math/constraints/Square.h
new file mode 100644
index 00000000..e51bd819
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Square.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Square.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SQUARE_H_
+#define _BLAZE_MATH_CONSTRAINTS_SQUARE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSquare.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SQUARE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a square matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SQUARE(T) \
+ static_assert( ::blaze::IsSquare<T>::value, "Non-square matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SQUARE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a square matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SQUARE(T) \
+ static_assert( !::blaze::IsSquare<T>::value, "Square matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/StorageOrder.h b/src/cpu/blaze/math/constraints/StorageOrder.h
new file mode 100644
index 00000000..ec1737b4
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/StorageOrder.h
@@ -0,0 +1,114 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/StorageOrder.h
+// \brief Constraints on the storage order of matrix types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_STORAGEORDER_H_
+#define _BLAZE_MATH_CONSTRAINTS_STORAGEORDER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/StorageOrder.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_MATRIX_WITH_STORAGE_ORDER CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a dense or sparse matrix type and in case the
+// storage order of the given dense or sparse vector type \a T is not set to \a SO, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER(T,SO) \
+ static_assert( ::blaze::IsMatrix<T>::value && \
+ ::blaze::StorageOrder<T>::value == SO, "Invalid storage order detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATRICES_MUST_HAVE_SAME_STORAGE_ORDER CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case either of the two given data types \a T1 or \a T2 is not a matrix type and in case
+// the storage order of both matrix types doesn't match, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER(T1,T2) \
+ static_assert( ::blaze::IsMatrix<T1>::value && \
+ ::blaze::IsMatrix<T2>::value && \
+ ::blaze::StorageOrder<T1>::value == ::blaze::StorageOrder<T2>::value, "Invalid storage order failed" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATRICES_MUST_HAVE_DIFFERENT_STORAGE_ORDER CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case either of the two given data types \a T1 or \a T2 is not a matrix type and in case
+// the storage order of both matrix types does match, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_DIFFERENT_STORAGE_ORDER(T1,T2) \
+ static_assert( ::blaze::IsMatrix<T1>::value && \
+ ::blaze::IsMatrix<T2>::value && \
+ ::blaze::StorageOrder<T1>::value != ::blaze::StorageOrder<T2>::value, "Invalid storage order detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/StrictlyLower.h b/src/cpu/blaze/math/constraints/StrictlyLower.h
new file mode 100644
index 00000000..6c0f072c
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/StrictlyLower.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/StrictlyLower.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_STRICTLYLOWER_H_
+#define _BLAZE_MATH_CONSTRAINTS_STRICTLYLOWER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_STRICTLY_LOWER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a strictly lower triangular matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_STRICTLY_LOWER_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsStrictlyLower<T>::value, "Non-strictly lower triangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_STRICTLY_LOWER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a strictly lower triangular matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_LOWER_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsStrictlyLower<T>::value, "Strictly lower triangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/StrictlyTriangular.h b/src/cpu/blaze/math/constraints/StrictlyTriangular.h
new file mode 100644
index 00000000..e2de25b6
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/StrictlyTriangular.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/StrictlyTriangular.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_STRICTLYTRIANGULAR_H_
+#define _BLAZE_MATH_CONSTRAINTS_STRICTLYTRIANGULAR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a strictly lower or upper triangular matrix type, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsStrictlyTriangular<T>::value, "Non-strictly triangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a strictly lower or upper triangular matrix type, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsStrictlyTriangular<T>::value, "Strictly triangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/StrictlyUpper.h b/src/cpu/blaze/math/constraints/StrictlyUpper.h
new file mode 100644
index 00000000..0fbfed12
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/StrictlyUpper.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/StrictlyUpper.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_STRICTLYUPPER_H_
+#define _BLAZE_MATH_CONSTRAINTS_STRICTLYUPPER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_STRICTLY_UPPER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a strictly upper triangular matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_STRICTLY_UPPER_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsStrictlyUpper<T>::value, "Non-strictly upper triangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_STRICTLY_UPPER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a strictly upper triangular matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_UPPER_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsStrictlyUpper<T>::value, "Strictly upper triangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/SubExpr.h b/src/cpu/blaze/math/constraints/SubExpr.h
new file mode 100644
index 00000000..729515d0
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/SubExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/SubExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SUBEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_SUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSubExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SUBEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a subtraction expression (i.e. a type derived from the
+// SubExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SUBEXPR_TYPE(T) \
+ static_assert( ::blaze::IsSubExpr<T>::value, "Non-subtraction expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SUBEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a subtraction expression (i.e. a type derived from the
+// SubExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SUBEXPR_TYPE(T) \
+ static_assert( !::blaze::IsSubExpr<T>::value, "Subtraction expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Submatrix.h b/src/cpu/blaze/math/constraints/Submatrix.h
new file mode 100644
index 00000000..c8f13f52
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Submatrix.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Submatrix.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SUBMATRIX_H_
+#define _BLAZE_MATH_CONSTRAINTS_SUBMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSubmatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SUBMATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a submatrix type (i.e. a dense or sparse submatrix),
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SUBMATRIX_TYPE(T) \
+ static_assert( ::blaze::IsSubmatrix<T>::value, "Non-submatrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SUBMATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a submatrix type (i.e. a dense or sparse submatrix), a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE(T) \
+ static_assert( !::blaze::IsSubmatrix<T>::value, "Submatrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Subvector.h b/src/cpu/blaze/math/constraints/Subvector.h
new file mode 100644
index 00000000..d504870b
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Subvector.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Subvector.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SUBVECTOR_H_
+#define _BLAZE_MATH_CONSTRAINTS_SUBVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSubvector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SUBVECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a subvector type (i.e. a dense or sparse subvector),
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SUBVECTOR_TYPE(T) \
+ static_assert( ::blaze::IsSubvector<T>::value, "Non-subvector type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SUBVECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a subvector type (i.e. a dense or sparse subvector), a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SUBVECTOR_TYPE(T) \
+ static_assert( !::blaze::IsSubvector<T>::value, "Subvector type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Symmetric.h b/src/cpu/blaze/math/constraints/Symmetric.h
new file mode 100644
index 00000000..cfa9a1d5
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Symmetric.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Symmetric.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_SYMMETRIC_H_
+#define _BLAZE_MATH_CONSTRAINTS_SYMMETRIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsSymmetric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SYMMETRIC_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a symmetric matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SYMMETRIC_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsSymmetric<T>::value, "Non-symmetric matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a symmetric matrix type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsSymmetric<T>::value, "Symmetric matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/TVecMatMultExpr.h b/src/cpu/blaze/math/constraints/TVecMatMultExpr.h
new file mode 100644
index 00000000..66789f49
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/TVecMatMultExpr.h
@@ -0,0 +1,146 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/TVecMatMultExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_TVECMATMULTEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_TVECMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsTVecMatMultExpr.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_TVECMATMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector/matrix multiplication expression (i.e. a type
+// derived from the TVecMatMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_TVECMATMULTEXPR_TYPE(T) \
+ static_assert( ::blaze::IsTVecMatMultExpr<T>::value, "Non-vector/matrix multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_TVECMATMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector/matrix multiplication expression (i.e. a type
+// derived from the TVecMatMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_TVECMATMULTEXPR_TYPE(T) \
+ static_assert( !::blaze::IsTVecMatMultExpr<T>::value, "Vector/matrix multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_TVECMATMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid vector/matrix multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsMatrix<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Rows<T2> > > \
+ >::value, "Invalid vector/matrix multiplication expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_TVECMATMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid vector/matrix multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_TVECMATMULTEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsMatrix<T2> \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Rows<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Rows<T2> > > > \
+ >::value, "Valid vector/matrix multiplication expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/TransExpr.h b/src/cpu/blaze/math/constraints/TransExpr.h
new file mode 100644
index 00000000..bf004c00
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/TransExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/TransExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_TRANSEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_TRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsTransExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_TRANSEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a transposition expression (i.e. a type derived from
+// the TransExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_TRANSEXPR_TYPE(T) \
+ static_assert( ::blaze::IsTransExpr<T>::value, "Non-transposition expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_TRANSEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a transposition expression (i.e. a type derived from the
+// TransExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE(T) \
+ static_assert( !::blaze::IsTransExpr<T>::value, "Transposition expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/TransposeFlag.h b/src/cpu/blaze/math/constraints/TransposeFlag.h
new file mode 100644
index 00000000..bc5b710a
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/TransposeFlag.h
@@ -0,0 +1,114 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/TransposeFlag.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_TRANSPOSEFLAG_H_
+#define _BLAZE_MATH_CONSTRAINTS_TRANSPOSEFLAG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/math/typetraits/TransposeFlag.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a dense or sparse vector type and in case the
+// transpose flag of the given dense or sparse vector type \a T is not set to \a TF, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG(T,TF) \
+ static_assert( ::blaze::IsVector<T>::value && \
+ ::blaze::TransposeFlag<T>::value == TF, "Invalid transpose flag detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// VECTORS_MUST_HAVE_SAME_TRANSPOSE_FLAG CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case either of the two given data types \a T1 or \a T2 is not a vector type and in case
+// the transpose flags of both vector types don't match, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_VECTORS_MUST_HAVE_SAME_TRANSPOSE_FLAG(T1,T2) \
+ static_assert( ::blaze::IsVector<T1>::value && \
+ ::blaze::IsVector<T2>::value && \
+ ::blaze::TransposeFlag<T1>::value == ::blaze::TransposeFlag<T2>::value, "Invalid transpose flag detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// VECTORS_MUST_HAVE_DIFFERENT_TRANSPOSE_FLAG CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case either of the two given data types \a T1 or \a T2 is not a vector type and in case
+// the transpose flags of both vector types does match, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_VECTORS_MUST_HAVE_DIFFERENT_TRANSPOSE_FLAG(T1,T2) \
+ static_assert( ::blaze::IsVector<T1>::value && \
+ ::blaze::IsVector<T2>::value && \
+ ::blaze::TransposeFlag<T1>::value != ::blaze::TransposeFlag<T2>::value, "Invalid transpose flag detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Triangular.h b/src/cpu/blaze/math/constraints/Triangular.h
new file mode 100644
index 00000000..9c5195ee
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Triangular.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Triangular.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_TRIANGULAR_H_
+#define _BLAZE_MATH_CONSTRAINTS_TRIANGULAR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsTriangular.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_TRIANGULAR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a lower or upper triangular matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_TRIANGULAR_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsTriangular<T>::value, "Non-triangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_TRIANGULAR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a lower or upper triangular matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_TRIANGULAR_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsTriangular<T>::value, "Triangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/UniLower.h b/src/cpu/blaze/math/constraints/UniLower.h
new file mode 100644
index 00000000..01556810
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/UniLower.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/UniLower.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_UNILOWER_H_
+#define _BLAZE_MATH_CONSTRAINTS_UNILOWER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsUniLower.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_UNILOWER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a lower unitriangular matrix type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_UNILOWER_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsUniLower<T>::value, "Non-lower unitriangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_UNILOWER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a lower unitriangular matrix type, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_UNILOWER_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsUniLower<T>::value, "Lower unitriangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/UniTriangular.h b/src/cpu/blaze/math/constraints/UniTriangular.h
new file mode 100644
index 00000000..aa46dbef
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/UniTriangular.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/UniTriangular.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_UNITRIANGULAR_H_
+#define _BLAZE_MATH_CONSTRAINTS_UNITRIANGULAR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsUniTriangular.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_UNITRIANGULAR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a lower or upper unitriangular matrix type, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_UNITRIANGULAR_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsUniTriangular<T>::value, "Non-unitriangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a lower or upper unitriangular matrix type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsUniTriangular<T>::value, "Unitriangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/UniUpper.h b/src/cpu/blaze/math/constraints/UniUpper.h
new file mode 100644
index 00000000..2c08d5bb
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/UniUpper.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/UniUpper.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_UNIUPPER_H_
+#define _BLAZE_MATH_CONSTRAINTS_UNIUPPER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsUniUpper.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_UNIUPPER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a upper unitriangular matrix type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_UNIUPPER_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsUniUpper<T>::value, "Non-upper unitriangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_UNIUPPER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a upper unitriangular matrix type, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_UNIUPPER_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsUniUpper<T>::value, "Upper unitriangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Upper.h b/src/cpu/blaze/math/constraints/Upper.h
new file mode 100644
index 00000000..01f6ad5d
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Upper.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Upper.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_UPPER_H_
+#define _BLAZE_MATH_CONSTRAINTS_UPPER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsUpper.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_UPPER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a upper triangular matrix type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_UPPER_MATRIX_TYPE(T) \
+ static_assert( ::blaze::IsUpper<T>::value, "Non-upper triangular matrix type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_UPPER_MATRIX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a upper triangular matrix type, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE(T) \
+ static_assert( !::blaze::IsUpper<T>::value, "Upper triangular matrix type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecEvalExpr.h b/src/cpu/blaze/math/constraints/VecEvalExpr.h
new file mode 100644
index 00000000..9506c555
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecEvalExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecEvalExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECEVALEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVecEvalExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECEVALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector evaluation expression (i.e. a type derived
+// from the VecEvalExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECEVALEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecEvalExpr<T>::value, "Non-vector evaluation expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECEVALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector evaluation expression (i.e. a type derived from
+// the VecEvalExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECEVALEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecEvalExpr<T>::value, "Vector evaluation expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecForEachExpr.h b/src/cpu/blaze/math/constraints/VecForEachExpr.h
new file mode 100644
index 00000000..ff2b1e8f
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecForEachExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecForEachExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECFOREACHEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVecForEachExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECFOREACHEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector for-each expression (i.e. a type derived
+// from the VecForEachExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECFOREACHEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecForEachExpr<T>::value, "Non-vector for-each expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECFOREACHEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector for-each expression (i.e. a type derived from
+// the VecForEachExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECFOREACHEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecForEachExpr<T>::value, "Vector for-each expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecScalarDivExpr.h b/src/cpu/blaze/math/constraints/VecScalarDivExpr.h
new file mode 100644
index 00000000..5280d173
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecScalarDivExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecScalarDivExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECSCALARDIVEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVecScalarDivExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECSCALARDIVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector/scalar division expression (i.e. a type
+// derived from the VecScalarDivExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECSCALARDIVEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecScalarDivExpr<T>::value, "Non-vector/scalar division expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECSCALARDIVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector/scalar division expression (i.e. a type derived
+// from the VecScalarDivExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECSCALARDIVEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecScalarDivExpr<T>::value, "Vector/scalar division expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecScalarMultExpr.h b/src/cpu/blaze/math/constraints/VecScalarMultExpr.h
new file mode 100644
index 00000000..ec14ba3f
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecScalarMultExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecScalarMultExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECSCALARMULTEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVecScalarMultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECSCALARMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector/scalar multiplication expression (i.e. a type
+// derived from the VecScalarMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECSCALARMULTEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecScalarMultExpr<T>::value, "Non-vector/scalar multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECSCALARMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector/scalar multiplication expression (i.e. a type
+// derived from the VecScalarMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECSCALARMULTEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecScalarMultExpr<T>::value, "Vector/scalar multiplication expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecSerialExpr.h b/src/cpu/blaze/math/constraints/VecSerialExpr.h
new file mode 100644
index 00000000..fc46fec4
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecSerialExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecSerialExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECSERIALEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVecSerialExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECSERIALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector serial evaluation expression (i.e. a type
+// derived from the VecSerialExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECSERIALEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecSerialExpr<T>::value, "Non-vector serial evaluation expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECSERIALEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector serial evaluation expression (i.e. a type derived
+// from the VecSerialExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECSERIALEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecSerialExpr<T>::value, "Vector serial evaluation expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecTVecMultExpr.h b/src/cpu/blaze/math/constraints/VecTVecMultExpr.h
new file mode 100644
index 00000000..9fcddfb3
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecTVecMultExpr.h
@@ -0,0 +1,135 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecTVecMultExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECTVECMULTEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECTVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVecTVecMultExpr.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECTVECMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not an outer product expression (i.e. a type derived from
+// the VecTVecMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECTVECMULTEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecTVecMultExpr<T>::value, "Non-outer product expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECTVECMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is an outer product expression (i.e. a type derived from the
+// VecTVecMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECTVECMULTEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecTVecMultExpr<T>::value, "Outer product expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_VECTVECMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid vector/vector multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_VECTVECMULTEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsRowVector<T2> \
+ >::value, "Invalid vector/vector multiplication expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_VECTVECMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid vector/vector multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_VECTVECMULTEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ >::value, "Valid vector/vector multiplication expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecTransExpr.h b/src/cpu/blaze/math/constraints/VecTransExpr.h
new file mode 100644
index 00000000..4f66f1df
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecTransExpr.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecTransExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECTRANSEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVecTransExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECTRANSEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector transposition expression (i.e. a type derived
+// from the VecTransExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECTRANSEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecTransExpr<T>::value, "Non-vector transposition expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECTRANSEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector transposition expression (i.e. a type derived from
+// the VecTransExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECTRANSEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecTransExpr<T>::value, "Vector transposition expression type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecVecAddExpr.h b/src/cpu/blaze/math/constraints/VecVecAddExpr.h
new file mode 100644
index 00000000..de1ede20
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecVecAddExpr.h
@@ -0,0 +1,149 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecVecAddExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECVECADDEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECVECADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVecVecAddExpr.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECVECADDEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector/vector addition expression (i.e. a type
+// derived from the VecVecAddExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECVECADDEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecVecAddExpr<T>::value, "Non-vector/vector addition expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECVECADDEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector/vector addition expression (i.e. a type derived
+// from the VecVecAddExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECVECADDEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecVecAddExpr<T>::value, "Vector/vector addition expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_VECVECADDEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid vector/vector addition,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECADDEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::Or< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ , ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsColumnVector<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > \
+ >::value, "Invalid vector/vector addition expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_VECVECADDEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid vector/vector addition, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_VECVECADDEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::Or< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ , ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsColumnVector<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > > \
+ >::value, "" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecVecDivExpr.h b/src/cpu/blaze/math/constraints/VecVecDivExpr.h
new file mode 100644
index 00000000..d4912c0a
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecVecDivExpr.h
@@ -0,0 +1,149 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecVecDivExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECVECDIVEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECVECDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVecVecDivExpr.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECVECDIVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector/vector division expression (i.e. a type
+// derived from the VecVecDivExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECVECDIVEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecVecDivExpr<T>::value, "Non-vector/vector division expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECVECDIVEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector/vector division expression (i.e. a type derived
+// from the VecVecDivExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECVECDIVEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecVecDivExpr<T>::value, "Vector/vector division expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_VECVECDIVEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid vector/vector division, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECDIVEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::Or< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ , ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsColumnVector<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > \
+ >::value, "Invalid vector/vector division expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_VECVECDIVEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid vector/vector division, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_VECVECDIVEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::Or< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ , ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsColumnVector<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > > \
+ >::value, "Valid vector/vector division expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecVecMultExpr.h b/src/cpu/blaze/math/constraints/VecVecMultExpr.h
new file mode 100644
index 00000000..fa1b02b1
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecVecMultExpr.h
@@ -0,0 +1,149 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecVecMultExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECVECMULTEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVecVecMultExpr.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECVECMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector/vector multiplication expression (i.e. a type
+// derived from the VecVecMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECVECMULTEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecVecMultExpr<T>::value, "Non-vector/vector multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECVECMULTEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector/vector multiplication expression (i.e. a type
+// derived from the VecVecMultExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECVECMULTEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecVecMultExpr<T>::value, "Vector/vector multiplication expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_VECVECMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid vector/vector multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECMULTEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::Or< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ , ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsColumnVector<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > \
+ >::value, "Invalid vector/vector multiplication expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_VECVECMULTEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid vector/vector multiplication,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_VECVECMULTEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::Or< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ , ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsColumnVector<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > > \
+ >::value, "Valid vector/vector multiplication expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/VecVecSubExpr.h b/src/cpu/blaze/math/constraints/VecVecSubExpr.h
new file mode 100644
index 00000000..5baa69de
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/VecVecSubExpr.h
@@ -0,0 +1,149 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/VecVecSubExpr.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECVECSUBEXPR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECVECSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVecVecSubExpr.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/SizeT.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECVECSUBEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a vector/vector subtraction expression (i.e. a type
+// derived from the VecVecSubExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECVECSUBEXPR_TYPE(T) \
+ static_assert( ::blaze::IsVecVecSubExpr<T>::value, "Non-vector/vector subtraction expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECVECSUBEXPR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a vector/vector subtraction expression (i.e. a type derived
+// from the VecVecSubExpr base class), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECVECSUBEXPR_TYPE(T) \
+ static_assert( !::blaze::IsVecVecSubExpr<T>::value, "Vector/vector subtraction expression type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_FORM_VALID_VECVECSUBEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do not form a valid vector/vector subtraction,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECSUBEXPR(T1,T2) \
+ static_assert( ::blaze::And< ::blaze::Or< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ , ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsColumnVector<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > \
+ >::value, "Invalid vector/vector subtraction expression detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_FORM_VALID_VECVECSUBEXPR CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data types \a T1 and \a T2 do form a valid vector/vector subtraction, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_FORM_VALID_VECVECSUBEXPR(T1,T2) \
+ static_assert( ::blaze::Not< ::blaze::And< ::blaze::Or< ::blaze::And< ::blaze::IsRowVector<T1> \
+ , ::blaze::IsRowVector<T2> > \
+ , ::blaze::And< ::blaze::IsColumnVector<T1> \
+ , ::blaze::IsColumnVector<T2> > > \
+ , ::blaze::Or< ::blaze::Equal< ::blaze::Size<T1>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T2>, ::blaze::SizeT<0UL> > \
+ , ::blaze::Equal< ::blaze::Size<T1>, ::blaze::Size<T2> > > > \
+ >::value, "Valid vector/vector subtraction expression detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/Vector.h b/src/cpu/blaze/math/constraints/Vector.h
new file mode 100644
index 00000000..4277a714
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/Vector.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/Vector.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VECTOR_H_
+#define _BLAZE_MATH_CONSTRAINTS_VECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a N-dimensional vector type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECTOR_TYPE(T) \
+ static_assert( ::blaze::IsVector<T>::value, "Non-vector type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECTOR_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a N-dimensional vector type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECTOR_TYPE(T) \
+ static_assert( !::blaze::IsVector<T>::value, "Vector type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/constraints/View.h b/src/cpu/blaze/math/constraints/View.h
new file mode 100644
index 00000000..ff79c45f
--- /dev/null
+++ b/src/cpu/blaze/math/constraints/View.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/constraints/View.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_CONSTRAINTS_VIEW_H_
+#define _BLAZE_MATH_CONSTRAINTS_VIEW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsView.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VIEW_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is not a view type (i.e. a subvector, submatrix, row, column,
+// ...), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VIEW_TYPE(T) \
+ static_assert( ::blaze::IsView<T>::value, "Non-view type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VIEW_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup math_constraints
+//
+// In case the given data type \a T is a view type (i.e. a subvector, submatrix, row, column,
+// ...), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VIEW_TYPE(T) \
+ static_assert( !::blaze::IsView<T>::value, "View type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/CustomMatrix.h b/src/cpu/blaze/math/dense/CustomMatrix.h
new file mode 100644
index 00000000..69485c06
--- /dev/null
+++ b/src/cpu/blaze/math/dense/CustomMatrix.h
@@ -0,0 +1,6636 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/CustomMatrix.h
+// \brief Header file for the implementation of a customizable matrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_CUSTOMMATRIX_H_
+#define _BLAZE_MATH_DENSE_CUSTOMMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <boost/smart_ptr/shared_array.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/Diagonal.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/dense/DenseIterator.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/PaddingFlag.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/InvExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsCustom.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/CacheSize.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/StorageOrder.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Misalignment.h>
+#include <blaze/util/policies/NoDelete.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/AlignmentOf.h>
+#include <blaze/util/typetraits/IsClass.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup custom_matrix CustomMatrix
+// \ingroup dense_matrix
+*/
+/*!\brief Efficient implementation of a customizable matrix.
+// \ingroup custom_matrix
+//
+// The CustomMatrix class template provides the functionality to represent an external array of
+// elements of arbitrary type and a fixed size as a native \b Blaze dense matrix data structure.
+// Thus in contrast to all other dense matrix types a custom matrix does not perform any kind
+// of memory allocation by itself, but it is provided with an existing array of element during
+// construction. A custom matrix can therefore be considered an alias to the existing array.
+//
+// The type of the elements, the properties of the given array of elements and the storage order
+// of the matrix can be specified via the following four template parameters:
+
+ \code
+ template< typename Type, bool AF, bool PF, bool SO >
+ class CustomMatrix;
+ \endcode
+
+// - Type: specifies the type of the matrix elements. CustomMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - AF : specifies whether the represented, external arrays are properly aligned with
+// respect to the available instruction set (SSE, AVX, ...) or not.
+// - PF : specified whether the represented, external arrays are properly padded with
+// respect to the available instruction set (SSE, AVX, ...) or not.
+// - SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// The following examples give an impression of several possible types of custom matrices:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+
+ // Definition of a custom row-major matrix for unaligned, unpadded integer arrays
+ typedef CustomMatrix<int,unaligned,unpadded,rowMajor> UnalignedUnpadded;
+
+ // Definition of a custom column-major matrix for unaligned but padded 'float' arrays
+ typedef CustomMatrix<float,unaligned,padded,columnMajor> UnalignedPadded;
+
+ // Definition of a custom row-major matrix for aligned, unpadded 'double' arrays
+ typedef CustomMatrix<double,aligned,unpadded,rowMajor> AlignedUnpadded;
+
+ // Definition of a custom column-major matrix for aligned, padded 'complex<double>' arrays
+ typedef CustomMatrix<complex<double>,aligned,padded,columnMajor> AlignedPadded;
+ \endcode
+
+// \n \section custommatrix_special_properties Special Properties of Custom Matrices
+//
+// In comparison with the remaining \b Blaze dense matrix types CustomMatrix has several special
+// characteristics. All of these result from the fact that a custom matrix is not performing any
+// kind of memory allocation, but instead is given an existing array of elements. The following
+// sections discuss all of these characteristics:
+//
+// -# <b>\ref custommatrix_memory_management</b>
+// -# <b>\ref custommatrix_copy_operations</b>
+// -# <b>\ref custommatrix_alignment</b>
+// -# <b>\ref custommatrix_padding</b>
+//
+// \n \subsection custommatrix_memory_management Memory Management
+//
+// The CustomMatrix class template acts as an adaptor for an existing array of elements. As such
+// it provides everything that is required to use the array just like a native \b Blaze dense
+// matrix data structure. However, this flexibility comes with the price that the user of a custom
+// matrix is responsible for the resource management.
+//
+// When constructing a custom matrix there are two choices: Either a user manually manages the
+// array of elements outside the custom matrix, or alternatively passes the responsibility for
+// the memory management to an instance of CustomMatrix. In the second case the CustomMatrix
+// class employs shared ownership between all copies of the custom matrix, which reference the
+// same array.
+//
+// The following examples give an impression of several possible custom matrices:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::ArrayDelete;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of a 3x4 custom row-major matrix with unaligned, unpadded and externally
+ // managed integer array. Note that the std::vector must be guaranteed to outlive the
+ // custom matrix!
+ std::vector<int> vec( 12UL );
+ CustomMatrix<int,unaligned,unpadded> A( &vec[0], 3UL, 4UL );
+
+ // Definition of a 3x4 custom row-major matrix for unaligned, unpadded integer arrays.
+ // The responsibility for the memory management is passed to the custom matrix by
+ // providing a deleter of type 'blaze::ArrayDelete' that is used during the destruction
+ // of the custom matrix.
+ CustomMatrix<int,unaligned,unpadded,rowMajor> B( new int[12], 3UL, 4UL, ArrayDelete() );
+
+ // Definition of a custom 8x12 matrix for an aligned and padded integer array of
+ // capacity 128 (including 8 padding elements per row). The memory management is passed
+ // to the custom matrix by providing a deleter of type 'blaze::Deallocate'.
+ CustomMatrix<int,aligned,padded> C( allocate<int>( 128UL ), 8UL, 12UL, 16UL, Deallocate() );
+ \endcode
+
+// It is possible to pass any type of deleter to the constructor. The deleter is only required
+// to provide a function call operator that can be passed the pointer to the managed array. As
+// an example the following code snipped shows the implementation of two native \b Blaze deleters
+// blaze::ArrayDelete and blaze::Deallocate:
+
+ \code
+ namespace blaze {
+
+ struct ArrayDelete
+ {
+ template< typename Type >
+ inline void operator()( Type ptr ) const { boost::checked_array_delete( ptr ); }
+ };
+
+ struct Deallocate
+ {
+ template< typename Type >
+ inline void operator()( Type ptr ) const { deallocate( ptr ); }
+ };
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection custommatrix_copy_operations Copy Operations
+//
+// As with all dense matrices it is possible to copy construct a custom matrix:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::unaligned;
+ using blaze::unpadded;
+
+ typedef CustomMatrix<int,unaligned,unpadded> CustomType;
+
+ std::vector<int> vec( 6UL, 10 ); // Vector of 6 integers of the value 10
+ CustomType A( &vec[0], 2UL, 3UL ); // Represent the std::vector as Blaze dense matrix
+ a[1] = 20; // Also modifies the std::vector
+
+ CustomType B( a ); // Creating a copy of vector a
+ b[2] = 20; // Also affect matrix A and the std::vector
+ \endcode
+
+// It is important to note that a custom matrix acts as a reference to the specified array. Thus
+// the result of the copy constructor is a new custom matrix that is referencing and representing
+// the same array as the original custom matrix. In case a deleter has been provided to the first
+// custom matrix, both matrices share the responsibility to destroy the array when the last matrix
+// goes out of scope.
+//
+// In contrast to copy construction, just as with references, copy assignment does not change
+// which array is referenced by the custom matrices, but modifies the values of the array:
+
+ \code
+ std::vector<int> vec2( 6UL, 4 ); // Vector of 6 integers of the value 4
+ CustomType C( &vec2[0], 2UL, 3UL ); // Represent the std::vector as Blaze dense matrix
+
+ A = C; // Copy assignment: Set all values of matrix A and B to 4.
+ \endcode
+
+// \n \subsection custommatrix_alignment Alignment
+//
+// In case the custom matrix is specified as \a aligned the passed array must adhere to some
+// alignment restrictions based on the alignment requirements of the used data type and the
+// used instruction set (SSE, AVX, ...). The restriction applies to the first element of each
+// row/column: In case of a row-major matrix the first element of each row must be properly
+// aligned, in case of a column-major matrix the first element of each column must be properly
+// aligned. For instance, if a row-major matrix is used and AVX is active the first element of
+// each row must be 32-bit aligned:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::Deallocate;
+ using blaze::aligned;
+ using blaze::padded;
+ using blaze::rowMajor;
+
+ int* array = blaze::allocate<int>( 40UL ); // Is guaranteed to be 32-bit aligned
+ CustomMatrix<int,aligned,padded,rowMajor> A( array, 5UL, 6UL, 8UL, Deallocate() );
+ \endcode
+
+// In the example, the row-major matrix has six columns. However, since with AVX eight integer
+// values are loaded together the matrix is padded with two additional elements. This guarantees
+// that the first element of each row is 32-bit aligned. In case the alignment requirements are
+// violated, a \a std::invalid_argument exception is thrown.
+//
+// \n \subsection custommatrix_padding Padding
+//
+// Adding padding elements to the end of an array can have a significant impact on performance.
+// For instance, assuming that AVX is available, then two aligned, padded, 3x3 double precision
+// matrices can be added via three SIMD addition operations:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::padded;
+
+ typedef CustomMatrix<double,aligned,padded> CustomType;
+
+ // Creating padded custom 3x3 matrix with an additional padding element in each row
+ CustomType A( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+ CustomType B( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+ CustomType C( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+
+ // ... Initialization
+
+ C = A + B; // AVX-based matrix addition
+ \endcode
+
+// In this example, maximum performance is possible. However, in case no padding elements are
+// inserted a scalar addition has to be used:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unpadded;
+
+ typedef CustomMatrix<double,aligned,unpadded> CustomType;
+
+ // Creating unpadded custom 3x3 matrix
+ CustomType A( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+ CustomType B( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+ CustomType C( allocate<double>( 12UL ), 3UL, 3UL, 4UL, Deallocate() );
+
+ // ... Initialization
+
+ C = A + B; // Scalar matrix addition
+ \endcode
+
+// Note that the construction of padded and unpadded aligned matrices looks identical. However,
+// in case of padded matrices, \b Blaze will zero initialize the padding element and use them
+// in all computations in order to achieve maximum performance. In case of an unpadded matrix
+// \b Blaze will ignore the elements with the downside that it is not possible to load a complete
+// row to an AVX register, which makes it necessary to fall back to a scalar addition.
+//
+// The number of padding elements is required to be sufficient with respect to the available
+// instruction set: In case of an aligned padded custom matrix the added padding elements must
+// guarantee that the total number of elements in each row/column is a multiple of the SIMD
+// vector width. In case of an unaligned padded matrix the number of padding elements can be
+// greater or equal the number of padding elements of an aligned padded custom matrix. In case
+// the padding is insufficient with respect to the available instruction set, a
+// \a std::invalid_argument exception is thrown.
+//
+//
+// \n \section custommatrix_arithmetic_operations Arithmetic Operations
+//
+// The use of custom matrices in arithmetic operations is designed to be as natural and intuitive
+// as possible. All operations (addition, subtraction, multiplication, scaling, ...) can be
+// expressed similar to a text book representation. Also, custom matrices can be combined with all
+// other dense and sparse vectors and matrices. The following example gives an impression of the
+// use of CustomMatrix:
+
+ \code
+ using blaze::CustomMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::ArrayDelete;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Non-initialized custom 2x3 row-major matrix. All given arrays are considered to be
+ // unaligned and unpadded. The memory is managed via 'ArrayDelete'.
+ CustomMatrix<double,unaligned,unpadded> A( new double[6], 2UL, 3UL, blaze::ArrayDelete() );
+
+ A(0,0) = 1.0; A(0,1) = 2.0; A(0,2) = 3.0; // Initialization of the first row
+ A(1,0) = 4.0; A(1,1) = 5.0; A(1,2) = 6.0; // Initialization of the second row
+
+ // Non-initialized custom 2x3 row-major matrix with padding elements. All given arrays are
+ // required to be properly aligned and padded. The memory is managed via 'Deallocate'.
+ CustomMatrix<double,aligned,padded> B( allocate<double>( 16UL ), 2UL, 3UL, 8UL, Deallocate() );
+
+ B(0,0) = 1.0; B(0,1) = 3.0; B(0,2) = 5.0; // Initialization of the first row
+ B(1,0) = 2.0; B(1,1) = 4.0; B(1,2) = 6.0; // Initialization of the second row
+
+ CompressedMatrix<float> C( 2, 3 ); // Empty row-major sparse single precision matrix
+ DynamicMatrix<float> D( 3, 2, 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix
+
+ DynamicMatrix<double,rowMajor> E( A ); // Creation of a new row-major matrix as a copy of A
+ DynamicMatrix<double,columnMajor> F; // Creation of a default column-major matrix
+
+ E = A + B; // Matrix addition and assignment to a row-major matrix
+ F = A - C; // Matrix subtraction and assignment to a column-major matrix
+ F = A * D; // Matrix multiplication between two matrices of different element types
+
+ A *= 2.0; // In-place scaling of matrix A
+ E = 2.0 * B; // Scaling of matrix B
+ F = D * 2.0; // Scaling of matrix D
+
+ E += A - B; // Addition assignment
+ E -= A + C; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO = defaultStorageOrder > // Storage order
+class CustomMatrix : public DenseMatrix< CustomMatrix<Type,AF,PF,SO>, SO >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef CustomMatrix<Type,AF,PF,SO> This; //!< Type of this CustomMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this CustomMatrix instance.
+ typedef DynamicMatrix<Type,SO> ResultType; //!< Result type for expression template evaluations.
+ typedef DynamicMatrix<Type,!SO> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef DynamicMatrix<Type,!SO> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Type* Pointer; //!< Pointer to a non-constant matrix value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant matrix value.
+
+ typedef DenseIterator<Type,AF> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,AF> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a CustomMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef CustomMatrix<ET,AF,PF,SO> Other; //!< The type of the other CustomMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the element type of the matrix is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline CustomMatrix();
+ explicit inline CustomMatrix( Type* ptr, size_t m, size_t n );
+ explicit inline CustomMatrix( Type* ptr, size_t m, size_t n, size_t nn );
+
+ template< typename Deleter, typename = EnableIf_< IsClass<Deleter> > >
+ explicit inline CustomMatrix( Type* ptr, size_t m, size_t n, Deleter D );
+
+ template< typename Deleter >
+ explicit inline CustomMatrix( Type* ptr, size_t m, size_t n, size_t nn, Deleter D );
+
+ inline CustomMatrix( const CustomMatrix& m );
+ inline CustomMatrix( CustomMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t i ) noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i ) noexcept;
+ inline ConstIterator begin ( size_t i ) const noexcept;
+ inline ConstIterator cbegin( size_t i ) const noexcept;
+ inline Iterator end ( size_t i ) noexcept;
+ inline ConstIterator end ( size_t i ) const noexcept;
+ inline ConstIterator cend ( size_t i ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline CustomMatrix& operator=( const Type& set );
+ inline CustomMatrix& operator=( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other, size_t M, size_t N >
+ inline CustomMatrix& operator=( const Other (&array)[M][N] );
+
+ inline CustomMatrix& operator=( const CustomMatrix& rhs );
+ inline CustomMatrix& operator=( CustomMatrix&& rhs ) noexcept;
+
+ template< typename MT, bool SO2 > inline CustomMatrix& operator= ( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline CustomMatrix& operator+=( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline CustomMatrix& operator-=( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline CustomMatrix& operator*=( const Matrix<MT,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, CustomMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, CustomMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline CustomMatrix& transpose();
+ inline CustomMatrix& ctranspose();
+ template< typename Other > inline CustomMatrix& scale( const Other& scalar );
+ inline void swap( CustomMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Resource management functions***************************************************************
+ /*!\name Resource management functions */
+ //@{
+ inline void reset( Type* ptr, size_t m, size_t n );
+ inline void reset( Type* ptr, size_t m, size_t n, size_t nn );
+
+ template< typename Deleter, typename = EnableIf_< IsClass<Deleter> > >
+ inline void reset( Type* ptr, size_t m, size_t n, Deleter d );
+
+ template< typename Deleter >
+ inline void reset( Type* ptr, size_t m, size_t n, size_t nn, Deleter d );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDAdd< Type, ElementType_<MT> >::value &&
+ !IsDiagonal<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDSub< Type, ElementType_<MT> >::value &&
+ !IsDiagonal<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT >
+ inline DisableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void assign( const DenseMatrix<MT,!SO>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,!SO>& rhs );
+
+ template< typename MT >
+ inline DisableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void addAssign( const DenseMatrix<MT,!SO>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,!SO>& rhs );
+
+ template< typename MT >
+ inline DisableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void subAssign( const DenseMatrix<MT,!SO>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,!SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t m_; //!< The current number of rows of the matrix.
+ size_t n_; //!< The current number of columns of the matrix.
+ size_t nn_; //!< The number of elements between two rows.
+ boost::shared_array<Type> v_; //!< The dynamically allocated matrix elements.
+ /*!< Access to the matrix elements is gained via the function call
+ operator. In case of row-major order the memory layout of the
+ elements is
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ N & N+1 & N+2 & \cdots & 2 \cdot N-1 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ M \cdot N-N & M \cdot N-N+1 & M \cdot N-N+2 & \cdots & M \cdot N-1 \\
+ \end{array}\right)\f]. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for CustomMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>::CustomMatrix()
+ : m_ ( 0UL ) // The current number of rows of the matrix
+ , n_ ( 0UL ) // The current number of columns of the matrix
+ , nn_( 0UL ) // The number of elements between two rows
+ , v_ ( ) // The matrix elements
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This constructor creates an unpadded custom matrix of size \f$ m \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded custom matrices!
+// \note The custom matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>::CustomMatrix( Type* ptr, size_t m, size_t n )
+ : m_ ( m ) // The current number of rows of the matrix
+ , n_ ( n ) // The current number of columns of the matrix
+ , nn_( n ) // The number of elements between two rows
+ , v_ ( ) // The matrix elements
+{
+ BLAZE_STATIC_ASSERT( PF == unpadded );
+
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && ( !checkAlignment( ptr ) || nn_ % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ v_.reset( ptr, NoDelete() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This constructor creates a custom matrix of size \f$ m \times n \f$. The construction fails
+// if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The custom matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>::CustomMatrix( Type* ptr, size_t m, size_t n, size_t nn )
+ : m_ ( m ) // The current number of rows of the matrix
+ , n_ ( n ) // The current number of columns of the matrix
+ , nn_( nn ) // The number of elements between two rows
+ , v_ ( ) // The matrix elements
+{
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && ( !checkAlignment( ptr ) || nn_ % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ if( PF && IsVectorizable<Type>::value && ( nn_ < nextMultiple<size_t>( n_, SIMDSIZE ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded matrix" );
+ }
+
+ v_.reset( ptr, NoDelete() );
+
+ if( PF && IsVectorizable<Type>::value ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=n_; j<nn_; ++j )
+ v_[i*nn_+j] = Type();
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This constructor creates an unpadded custom matrix of size \f$ m \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded custom matrices!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Deleter // Type of the custom deleter
+ , typename > // Type restriction on the custom deleter
+inline CustomMatrix<Type,AF,PF,SO>::CustomMatrix( Type* ptr, size_t m, size_t n, Deleter d )
+ : m_ ( m ) // The current number of rows of the matrix
+ , n_ ( n ) // The current number of columns of the matrix
+ , nn_( n ) // The number of elements between two rows
+ , v_ ( ) // The matrix elements
+{
+ BLAZE_STATIC_ASSERT( PF == unpadded );
+
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && ( !checkAlignment( ptr ) || nn_ % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ v_.reset( ptr, d );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This constructor creates a custom matrix of size \f$ m \times n \f$. The construction fails
+// if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
+// available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Deleter > // Type of the custom deleter
+inline CustomMatrix<Type,AF,PF,SO>::CustomMatrix( Type* ptr, size_t m, size_t n, size_t nn, Deleter d )
+ : m_ ( m ) // The current number of rows of the matrix
+ , n_ ( n ) // The current number of columns of the matrix
+ , nn_( nn ) // The number of elements between two rows
+ , v_ ( ) // The matrix elements
+{
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && ( !checkAlignment( ptr ) || nn_ % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ if( PF && IsVectorizable<Type>::value && ( nn_ < nextMultiple<size_t>( n_, SIMDSIZE ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded matrix" );
+ }
+
+ v_.reset( ptr, d );
+
+ if( PF && IsVectorizable<Type>::value ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=n_; j<nn_; ++j )
+ v_[i*nn_+j] = Type();
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for CustomMatrix.
+//
+// \param m Matrix to be copied.
+//
+// The copy constructor initializes the custom matrix as an exact copy of the given custom matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>::CustomMatrix( const CustomMatrix& m )
+ : m_ ( m.m_ ) // The current number of rows of the matrix
+ , n_ ( m.n_ ) // The current number of columns of the matrix
+ , nn_( m.nn_ ) // The number of elements between two rows
+ , v_ ( m.v_ ) // The matrix elements
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The move constructor for CustomMatrix.
+//
+// \param m The matrix to be moved into this instance.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>::CustomMatrix( CustomMatrix&& m ) noexcept
+ : m_ ( m.m_ ) // The current number of rows of the matrix
+ , n_ ( m.n_ ) // The current number of columns of the matrix
+ , nn_( m.nn_ ) // The number of elements between two rows
+ , v_ ( std::move( m.v_ ) ) // The matrix elements
+{
+ m.m_ = 0UL;
+ m.n_ = 0UL;
+ m.nn_ = 0UL;
+
+ BLAZE_INTERNAL_ASSERT( m.data() == nullptr, "Invalid data reference detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::Reference
+ CustomMatrix<Type,AF,PF,SO>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
+ return v_[i*nn_+j];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::ConstReference
+ CustomMatrix<Type,AF,PF,SO>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
+ return v_[i*nn_+j];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::Reference
+ CustomMatrix<Type,AF,PF,SO>::at( size_t i, size_t j )
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::ConstReference
+ CustomMatrix<Type,AF,PF,SO>::at( size_t i, size_t j ) const
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::Pointer
+ CustomMatrix<Type,AF,PF,SO>::data() noexcept
+{
+ return v_.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::ConstPointer
+ CustomMatrix<Type,AF,PF,SO>::data() const noexcept
+{
+ return v_.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::Pointer
+ CustomMatrix<Type,AF,PF,SO>::data( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return v_.get() + i*nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::ConstPointer
+ CustomMatrix<Type,AF,PF,SO>::data( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return v_.get() + i*nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::Iterator
+ CustomMatrix<Type,AF,PF,SO>::begin( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return Iterator( v_.get() + i*nn_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::ConstIterator
+ CustomMatrix<Type,AF,PF,SO>::begin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return ConstIterator( v_.get() + i*nn_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::ConstIterator
+ CustomMatrix<Type,AF,PF,SO>::cbegin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return ConstIterator( v_.get() + i*nn_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::Iterator
+ CustomMatrix<Type,AF,PF,SO>::end( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return Iterator( v_.get() + i*nn_ + n_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::ConstIterator
+ CustomMatrix<Type,AF,PF,SO>::end( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return ConstIterator( v_.get() + i*nn_ + n_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline typename CustomMatrix<Type,AF,PF,SO>::ConstIterator
+ CustomMatrix<Type,AF,PF,SO>::cend( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return ConstIterator( v_.get() + i*nn_ + n_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Homogenous assignment to all matrix elements.
+//
+// \param rhs Scalar value to be assigned to all matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::operator=( const Type& rhs )
+{
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*nn_+j] = rhs;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to static matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the matrix
+// by means of an initializer list:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ const int array[9] = { 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0 };
+ blaze::CustomMatrix<int,unaligned,unpadded,rowMajor> A( array, 3UL, 3UL );
+ A = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>&
+ CustomMatrix<Type,AF,PF,SO>::operator=( initializer_list< initializer_list<Type> > list )
+{
+ if( list.size() != m_ || determineColumns( list ) > n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to custom matrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), v_.get()+i*nn_ ),
+ v_.get()+i*nn_+( PF ? nn_ : n_ ), Type() );
+ ++i;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array assignment to all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid array size.
+//
+// This assignment operator offers the option to directly set all elements of the matrix:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ const int array[9] = { 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0 };
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::CustomMatrix<int,unaligned,unpadded,rowMajor> A( array, 3UL, 3UL );
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the value 6 in the example). Note that the size of the array must
+// match the size of the custom matrix. Otherwise a \a std::invalid_argument exception is thrown.
+// Also note that after the assignment \a array will have the same entries as \a init.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Other // Data type of the initialization array
+ , size_t M // Number of rows of the initialization array
+ , size_t N > // Number of columns of the initialization array
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::operator=( const Other (&array)[M][N] )
+{
+ if( m_ != M || n_ != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" );
+ }
+
+ for( size_t i=0UL; i<M; ++i )
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*nn_+j] = array[i][j];
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for CustomMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// The matrix is initialized as a copy of the given matrix. In case the current sizes of the two
+// matrices don't match, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::operator=( const CustomMatrix& rhs )
+{
+ if( rhs.rows() != m_ || rhs.columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ smpAssign( *this, ~rhs );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Move assignment operator for CustomMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>&
+ CustomMatrix<Type,AF,PF,SO>::operator=( CustomMatrix&& rhs ) noexcept
+{
+ m_ = rhs.m_;
+ n_ = rhs.n_;
+ nn_ = rhs.nn_;
+ v_ = std::move( rhs.v_ );
+
+ rhs.m_ = 0UL;
+ rhs.n_ = 0UL;
+ rhs.nn_ = 0UL;
+
+ BLAZE_INTERNAL_ASSERT( rhs.data() == nullptr, "Invalid data reference detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// The matrix is initialized as a copy of the given matrix. In case the current sizes of the two
+// matrices don't match, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::operator=( const Matrix<MT,SO2>& rhs )
+{
+ typedef TransExprTrait_<This> TT;
+ typedef CTransExprTrait_<This> CT;
+ typedef InvExprTrait_<This> IT;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( IsSame<MT,TT>::value && (~rhs).isAliased( this ) ) {
+ transpose();
+ }
+ else if( IsSame<MT,CT>::value && (~rhs).isAliased( this ) ) {
+ ctranspose();
+ }
+ else if( !IsSame<MT,IT>::value && (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpAssign( *this, tmp );
+ }
+ else {
+ if( IsSparseMatrix<MT>::value )
+ reset();
+ smpAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::operator+=( const Matrix<MT,SO2>& rhs )
+{
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpAddAssign( *this, tmp );
+ }
+ else {
+ smpAddAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::operator-=( const Matrix<MT,SO2>& rhs )
+{
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpSubAssign( *this, tmp );
+ }
+ else {
+ smpSubAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::operator*=( const Matrix<MT,SO2>& rhs )
+{
+ if( m_ != n_ || (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const MultTrait_< ResultType, ResultType_<MT> > tmp( *this * (~rhs) );
+ smpAssign( *this, tmp );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, CustomMatrix<Type,AF,PF,SO> >&
+ CustomMatrix<Type,AF,PF,SO>::operator*=( Other rhs )
+{
+ smpAssign( *this, (*this) * rhs );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, CustomMatrix<Type,AF,PF,SO> >&
+ CustomMatrix<Type,AF,PF,SO>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ smpAssign( *this, (*this) / rhs );
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline size_t CustomMatrix<Type,AF,PF,SO>::rows() const noexcept
+{
+ return m_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline size_t CustomMatrix<Type,AF,PF,SO>::columns() const noexcept
+{
+ return n_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the
+// total number of elements of a row/column. In case the storage order is set to \a rowMajor
+// the function returns the spacing between two rows, in case the storage flag is set to
+// \a columnMajor the function returns the spacing between two columns.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline size_t CustomMatrix<Type,AF,PF,SO>::spacing() const noexcept
+{
+ return nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline size_t CustomMatrix<Type,AF,PF,SO>::capacity() const noexcept
+{
+ return m_ * nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline size_t CustomMatrix<Type,AF,PF,SO>::capacity( size_t i ) const noexcept
+{
+ UNUSED_PARAMETER( i );
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the dense matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline size_t CustomMatrix<Type,AF,PF,SO>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ if( !isDefault( v_[i*nn_+j] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline size_t CustomMatrix<Type,AF,PF,SO>::nonZeros( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t jend( i*nn_ + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=i*nn_; j<jend; ++j )
+ if( !isDefault( v_[j] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void CustomMatrix<Type,AF,PF,SO>::reset()
+{
+ using blaze::clear;
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ clear( v_[i*nn_+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void CustomMatrix<Type,AF,PF,SO>::reset( size_t i )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ for( size_t j=0UL; j<n_; ++j )
+ clear( v_[i*nn_+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the \f$ M \times N \f$ matrix.
+//
+// \return void
+//
+// After the clear() function, the size of the matrix is 0.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void CustomMatrix<Type,AF,PF,SO>::clear()
+{
+ m_ = 0UL;
+ n_ = 0UL;
+ nn_ = 0UL;
+ v_.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::logic_error Impossible transpose operation.
+//
+// In case the matrix is not a square matrix, a \a std::logic_error exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::transpose()
+{
+ using std::swap;
+
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
+ }
+
+ for( size_t i=1UL; i<m_; ++i )
+ for( size_t j=0UL; j<i; ++j )
+ swap( v_[i*nn_+j], v_[j*nn_+i] );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::logic_error Impossible transpose operation.
+//
+// In case the matrix is not a square matrix, a \a std::logic_error exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::ctranspose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
+ }
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ cswap( v_[i*nn_+j], v_[j*nn_+i] );
+ }
+ conjugate( v_[i*nn_+i] );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Other > // Data type of the scalar value
+inline CustomMatrix<Type,AF,PF,SO>& CustomMatrix<Type,AF,PF,SO>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*nn_+j] *= scalar;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void CustomMatrix<Type,AF,PF,SO>::swap( CustomMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( m_ , m.m_ );
+ swap( n_ , m.n_ );
+ swap( nn_, m.nn_ );
+ swap( v_ , m.v_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RESOURCE MANAGEMENT FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Resets the custom matrix and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This function resets the custom matrix to the given array of elements of size \f$ m \times n \f$.
+// The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This function is \b NOT available for padded custom matrices!
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom matrix referencing the array goes out of scope.
+// \note The custom matrix does NOT take responsibility for the new array of elements!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void CustomMatrix<Type,AF,PF,SO>::reset( Type* ptr, size_t m, size_t n )
+{
+ BLAZE_STATIC_ASSERT( PF == unpadded );
+
+ CustomMatrix tmp( ptr, m, n );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resets the custom matrix and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This function resets the custom matrix to the given array of elements of size \f$ m \times n \f$.
+// The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom matrix referencing the array goes out of scope.
+// \note The custom matrix does NOT take responsibility for the new array of elements!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void CustomMatrix<Type,AF,PF,SO>::reset( Type* ptr, size_t m, size_t n, size_t nn )
+{
+ CustomMatrix tmp( ptr, m, n, nn );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resets the custom matrix and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This function resets the custom matrix to the given array of elements of size \f$ m \times n \f$.
+// The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This function is \b NOT available for padded custom matrices!
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom matrix referencing the array goes out of scope.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Deleter // Type of the custom deleter
+ , typename > // Type restriction on the custom deleter
+inline void CustomMatrix<Type,AF,PF,SO>::reset( Type* ptr, size_t m, size_t n, Deleter d )
+{
+ BLAZE_STATIC_ASSERT( !IsClass<Deleter>::value || PF == unpadded );
+
+ CustomMatrix tmp( ptr, m, n, d );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resets the custom matrix and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param nn The total number of elements between two rows/columns.
+// \param d The deleter to destroy the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This function resets the custom matrix to the given array of elements of size \f$ m \times n \f$.
+// The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom matrix referencing the array goes out of scope.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Deleter > // Type of the custom deleter
+inline void CustomMatrix<Type,AF,PF,SO>::reset( Type* ptr, size_t m, size_t n, size_t nn, Deleter d )
+{
+ CustomMatrix tmp( ptr, m, n, nn, d );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool CustomMatrix<Type,AF,PF,SO>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool CustomMatrix<Type,AF,PF,SO>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline bool CustomMatrix<Type,AF,PF,SO>::isAligned() const noexcept
+{
+ return ( AF || ( checkAlignment( v_.get() ) && columns() % SIMDSIZE == 0UL ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline bool CustomMatrix<Type,AF,PF,SO>::canSMPAssign() const noexcept
+{
+ return ( rows() > SMP_DMATASSIGN_THRESHOLD );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller then the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename CustomMatrix<Type,AF,PF,SO>::SIMDType
+ CustomMatrix<Type,AF,PF,SO>::load( size_t i, size_t j ) const noexcept
+{
+ if( AF && PF )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename CustomMatrix<Type,AF,PF,SO>::SIMDType
+ CustomMatrix<Type,AF,PF,SO>::loada( size_t i, size_t j ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !PF || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+i*nn_+j ), "Invalid alignment detected" );
+
+ return loada( v_.get()+i*nn_+j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename CustomMatrix<Type,AF,PF,SO>::SIMDType
+ CustomMatrix<Type,AF,PF,SO>::loadu( size_t i, size_t j ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" );
+
+ return loadu( v_.get()+i*nn_+j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ CustomMatrix<Type,AF,PF,SO>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( AF && PF )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ CustomMatrix<Type,AF,PF,SO>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !PF || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+i*nn_+j ), "Invalid alignment detected" );
+
+ storea( v_.get()+i*nn_+j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ CustomMatrix<Type,AF,PF,SO>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" );
+
+ storeu( v_.get()+i*nn_+j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the column index (in case of a
+// row-major matrix) or the row index (in case of a column-major matrix) must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ CustomMatrix<Type,AF,PF,SO>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !PF || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+i*nn_+j ), "Invalid alignment detected" );
+
+ stream( v_.get()+i*nn_+j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename CustomMatrix<Type,AF,PF,SO>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ CustomMatrix<Type,AF,PF,SO>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ v_[i*nn_+j ] = (~rhs)(i,j );
+ v_[i*nn_+j+1UL] = (~rhs)(i,j+1UL);
+ }
+ if( jpos < n_ ) {
+ v_[i*nn_+jpos] = (~rhs)(i,jpos);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename CustomMatrix<Type,AF,PF,SO>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ CustomMatrix<Type,AF,PF,SO>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !PF || !IsPadded<MT>::value );
+
+ const size_t jpos( ( remainder )?( n_ & size_t(-SIMDSIZE) ):( n_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ if( AF && PF && useStreaming &&
+ ( m_*n_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) && !(~rhs).isAliased( this ) )
+ {
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ stream( i, j, (~rhs).load(i,j) );
+ }
+ for( ; remainder && j<n_; ++j ) {
+ v_[i*nn_+j] = (~rhs)(i,j);
+ }
+ }
+ }
+ else
+ {
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+ ConstIterator_<MT> it( (~rhs).begin(i) );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ store( i, j , it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE , it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE*2UL, it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE*3UL, it.load() ); it += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, j, it.load() );
+ }
+ for( ; remainder && j<n_; ++j, ++it ) {
+ v_[i*nn_+j] = *it;
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline void CustomMatrix<Type,AF,PF,SO>::assign( const DenseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( m_, ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( n_, jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ v_[i*nn_+j] = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,SO>::assign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*nn_+element->index()] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,SO>::assign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*nn_+j] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename CustomMatrix<Type,AF,PF,SO>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ CustomMatrix<Type,AF,PF,SO>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[i*nn_+i] += (~rhs)(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ size_t j( jbegin );
+
+ for( ; (j+2UL) <= jend; j+=2UL ) {
+ v_[i*nn_+j ] += (~rhs)(i,j );
+ v_[i*nn_+j+1UL] += (~rhs)(i,j+1UL);
+ }
+ if( j < jend ) {
+ v_[i*nn_+j] += (~rhs)(i,j);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename CustomMatrix<Type,AF,PF,SO>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ CustomMatrix<Type,AF,PF,SO>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !PF || !IsPadded<MT>::value );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+ ConstIterator_<MT> it( (~rhs).begin(i) + jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ store( i, j , load(i,j ) + it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE , load(i,j+SIMDSIZE ) + it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE*2UL, load(i,j+SIMDSIZE*2UL) + it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE*3UL, load(i,j+SIMDSIZE*3UL) + it.load() ); it += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, j, load(i,j) + it.load() );
+ }
+ for( ; remainder && j<jend; ++j, ++it ) {
+ v_[i*nn_+j] += *it;
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline void CustomMatrix<Type,AF,PF,SO>::addAssign( const DenseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( m_, ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block )
+ {
+ if( IsLower<MT>::value && ii < jj ) break;
+ if( IsUpper<MT>::value && ii > jj ) continue;
+
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( max( ( IsStrictlyUpper<MT>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( min( ( IsStrictlyLower<MT>::value ? i : i+1UL ), n_, jj+block ) )
+ :( min( n_, jj+block ) ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ v_[i*nn_+j] += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,SO>::addAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*nn_+element->index()] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,SO>::addAssign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*nn_+j] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename CustomMatrix<Type,AF,PF,SO>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ CustomMatrix<Type,AF,PF,SO>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[i*nn_+i] -= (~rhs)(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ size_t j( jbegin );
+
+ for( ; (j+2UL) <= jend; j+=2UL ) {
+ v_[i*nn_+j ] -= (~rhs)(i,j );
+ v_[i*nn_+j+1UL] -= (~rhs)(i,j+1UL);
+ }
+ if( j < jend ) {
+ v_[i*nn_+j] -= (~rhs)(i,j);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename CustomMatrix<Type,AF,PF,SO>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ CustomMatrix<Type,AF,PF,SO>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !PF || !IsPadded<MT>::value );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+ ConstIterator_<MT> it( (~rhs).begin(i) + jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ store( i, j , load(i,j ) - it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE , load(i,j+SIMDSIZE ) - it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE*2UL, load(i,j+SIMDSIZE*2UL) - it.load() ); it += SIMDSIZE;
+ store( i, j+SIMDSIZE*3UL, load(i,j+SIMDSIZE*3UL) - it.load() ); it += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, j, load(i,j) - it.load() );
+ }
+ for( ; remainder && j<jend; ++j, ++it ) {
+ v_[i*nn_+j] -= *it;
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline void CustomMatrix<Type,AF,PF,SO>::subAssign( const DenseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( m_, ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block )
+ {
+ if( IsLower<MT>::value && ii < jj ) break;
+ if( IsUpper<MT>::value && ii > jj ) continue;
+
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( max( ( IsStrictlyUpper<MT>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( min( ( IsStrictlyLower<MT>::value ? i : i+1UL ), n_, jj+block ) )
+ :( min( n_, jj+block ) ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ v_[i*nn_+j] -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,SO>::subAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*nn_+element->index()] -= element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,SO>::subAssign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*nn_+j] -= element->value();
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of CustomMatrix for column-major matrices.
+// \ingroup custom_matrix
+//
+// This specialization of CustomMatrix adapts the class template to the requirements of
+// column-major matrices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+class CustomMatrix<Type,AF,PF,true> : public DenseMatrix< CustomMatrix<Type,AF,PF,true>, true >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef CustomMatrix<Type,AF,PF,true> This; //!< Type of this CustomMatrix instance.
+ typedef DenseMatrix<This,true> BaseType; //!< Base type of this CustomMatrix instance.
+ typedef DynamicMatrix<Type,true> ResultType; //!< Result type for expression template evaluations.
+ typedef DynamicMatrix<Type,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef DynamicMatrix<Type,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Type* Pointer; //!< Pointer to a non-constant matrix value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant matrix value.
+
+ typedef DenseIterator<Type,AF> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,AF> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a CustomMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef CustomMatrix<ET,AF,PF,true> Other; //!< The type of the other CustomMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the element type of the matrix is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline CustomMatrix();
+ explicit inline CustomMatrix( Type* ptr, size_t m, size_t n );
+ explicit inline CustomMatrix( Type* ptr, size_t m, size_t n, size_t mm );
+
+ template< typename Deleter, typename = EnableIf_< IsClass<Deleter> > >
+ explicit inline CustomMatrix( Type* ptr, size_t m, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline CustomMatrix( Type* ptr, size_t m, size_t n, size_t mm, Deleter d );
+
+ inline CustomMatrix( const CustomMatrix& m );
+ inline CustomMatrix( CustomMatrix&& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t j ) noexcept;
+ inline ConstPointer data ( size_t j ) const noexcept;
+ inline Iterator begin ( size_t j ) noexcept;
+ inline ConstIterator begin ( size_t j ) const noexcept;
+ inline ConstIterator cbegin( size_t j ) const noexcept;
+ inline Iterator end ( size_t j ) noexcept;
+ inline ConstIterator end ( size_t j ) const noexcept;
+ inline ConstIterator cend ( size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline CustomMatrix& operator=( const Type& set );
+ inline CustomMatrix& operator=( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other, size_t M, size_t N >
+ inline CustomMatrix& operator=( const Other (&array)[M][N] );
+
+ inline CustomMatrix& operator=( const CustomMatrix& rhs );
+ inline CustomMatrix& operator=( CustomMatrix&& rhs ) noexcept;
+
+ template< typename MT, bool SO > inline CustomMatrix& operator= ( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline CustomMatrix& operator+=( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline CustomMatrix& operator-=( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline CustomMatrix& operator*=( const Matrix<MT,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, CustomMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, CustomMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t j ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t j ) const;
+ inline void reset();
+ inline void reset( size_t j );
+ inline void clear();
+ inline CustomMatrix& transpose();
+ inline CustomMatrix& ctranspose();
+ template< typename Other > inline CustomMatrix& scale( const Other& scalar );
+ inline void swap( CustomMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Resource management functions***************************************************************
+ /*!\name Resource management functions */
+ //@{
+ inline void reset( Type* ptr, size_t m, size_t n );
+ inline void reset( Type* ptr, size_t m, size_t n, size_t mm );
+
+ template< typename Deleter, typename = EnableIf_< IsClass<Deleter> > >
+ inline void reset( Type* ptr, size_t m, size_t n, Deleter d );
+
+ template< typename Deleter >
+ inline void reset( Type* ptr, size_t m, size_t n, size_t mm, Deleter d );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDAdd< Type, ElementType_<MT> >::value &&
+ !IsDiagonal<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDSub< Type, ElementType_<MT> >::value &&
+ !IsDiagonal<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT >
+ inline DisableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT > inline void assign( const DenseMatrix<MT,false>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,false>& rhs );
+
+ template< typename MT >
+ inline DisableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT > inline void addAssign( const DenseMatrix<MT,false>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,false>& rhs );
+
+ template< typename MT >
+ inline DisableIf_<VectorizedSubAssign<MT> > subAssign ( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedSubAssign<MT> > subAssign ( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT > inline void subAssign( const DenseMatrix<MT,false>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t m_; //!< The current number of rows of the matrix.
+ size_t mm_; //!< The number of elements between two columns.
+ size_t n_; //!< The current number of columns of the matrix.
+ boost::shared_array<Type> v_; //!< The dynamically allocated matrix elements.
+ /*!< Access to the matrix elements is gained via the function
+ call operator. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for CustomMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>::CustomMatrix()
+ : m_ ( 0UL ) // The current number of rows of the matrix
+ , mm_( 0UL ) // The number of elements between two columns
+ , n_ ( 0UL ) // The current number of columns of the matrix
+ , v_ ( ) // The matrix elements
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This constructor creates an unpadded custom matrix of size \f$ m \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded custom matrices!
+// \note The custom matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>::CustomMatrix( Type* ptr, size_t m, size_t n )
+ : m_ ( m ) // The current number of rows of the matrix
+ , mm_( m ) // The number of elements between two columns
+ , n_ ( n ) // The current number of columns of the matrix
+ , v_ ( ) // The matrix elements
+{
+ BLAZE_STATIC_ASSERT( PF == unpadded );
+
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && ( !checkAlignment( ptr ) || mm_ % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ v_.reset( ptr, NoDelete() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param mm The total number of elements between two columns.
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This constructor creates a custom matrix of size \f$ m \times n \f$. The construction fails
+// if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a mm is insufficient for the given data type \a Type and the
+// available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The custom matrix does \b NOT take responsibility for the given array of elements!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>::CustomMatrix( Type* ptr, size_t m, size_t n, size_t mm )
+ : m_ ( m ) // The current number of rows of the matrix
+ , mm_( mm ) // The number of elements between two columns
+ , n_ ( n ) // The current number of columns of the matrix
+ , v_ ( ) // The matrix elements
+{
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && ( !checkAlignment( ptr ) || mm_ % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ if( PF && IsVectorizable<Type>::value && ( mm_ < nextMultiple<size_t>( m_, SIMDSIZE ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded matrix" );
+ }
+
+ v_.reset( ptr, NoDelete() );
+
+ if( PF && IsVectorizable<Type>::value ) {
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=m_; i<mm_; ++i ) {
+ v_[i+j*mm_] = Type();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This constructor creates an unpadded custom matrix of size \f$ m \times n \f$. The construction
+// fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded custom matrices!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Deleter // Type of the custom deleter
+ , typename > // Type restriction on the custom deleter
+inline CustomMatrix<Type,AF,PF,true>::CustomMatrix( Type* ptr, size_t m, size_t n, Deleter d )
+ : m_ ( m ) // The current number of rows of the matrix
+ , mm_( m ) // The number of elements between two columns
+ , n_ ( n ) // The current number of columns of the matrix
+ , v_ ( ) // The matrix elements
+{
+ BLAZE_STATIC_ASSERT( PF == unpadded );
+
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && ( !checkAlignment( ptr ) || mm_ % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ v_.reset( ptr, d );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param mm The total number of elements between two columns.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This constructor creates a custom matrix of size \f$ m \times n \f$. The construction fails
+// if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified spacing \a mm is insufficient for the given data type \a Type and the
+// available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Deleter > // Type of the custom deleter
+inline CustomMatrix<Type,AF,PF,true>::CustomMatrix( Type* ptr, size_t m, size_t n, size_t mm, Deleter d )
+ : m_ ( m ) // The current number of rows of the matrix
+ , mm_( mm ) // The number of elements between two columns
+ , n_ ( n ) // The current number of columns of the matrix
+ , v_ ( ) // The matrix elements
+{
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && ( !checkAlignment( ptr ) || mm_ % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ if( PF && IsVectorizable<Type>::value && ( mm_ < nextMultiple<size_t>( m_, SIMDSIZE ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded matrix" );
+ }
+
+ v_.reset( ptr, d );
+
+ if( PF && IsVectorizable<Type>::value ) {
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=m_; i<mm_; ++i ) {
+ v_[i+j*mm_] = Type();
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for CustomMatrix.
+//
+// \param m Matrix to be copied.
+//
+// The copy constructor is explicitly defined due to the required dynamic memory management
+// and in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>::CustomMatrix( const CustomMatrix& m )
+ : m_ ( m.m_ ) // The current number of rows of the matrix
+ , mm_( m.mm_ ) // The number of elements between two columns
+ , n_ ( m.n_ ) // The current number of columns of the matrix
+ , v_ ( m.v_ ) // The matrix elements
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for CustomMatrix.
+//
+// \param m The matrix to be moved into this instance.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>::CustomMatrix( CustomMatrix&& m ) noexcept
+ : m_ ( m.m_ ) // The current number of rows of the matrix
+ , mm_( m.mm_ ) // The number of elements between two columns
+ , n_ ( m.n_ ) // The current number of columns of the matrix
+ , v_ ( std::move( m.v_ ) ) // The matrix elements
+{
+ m.m_ = 0UL;
+ m.mm_ = 0UL;
+ m.n_ = 0UL;
+
+ BLAZE_INTERNAL_ASSERT( m.data() == nullptr, "Invalid data reference detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::Reference
+ CustomMatrix<Type,AF,PF,true>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
+ return v_[i+j*mm_];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::ConstReference
+ CustomMatrix<Type,AF,PF,true>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
+ return v_[i+j*mm_];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::Reference
+ CustomMatrix<Type,AF,PF,true>::at( size_t i, size_t j )
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::ConstReference
+ CustomMatrix<Type,AF,PF,true>::at( size_t i, size_t j ) const
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a column are given by the \c columns() member functions, the total number
+// of elements including padding is given by the \c spacing() member function.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::Pointer
+ CustomMatrix<Type,AF,PF,true>::data() noexcept
+{
+ return v_.get();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a column are given by the \c columns() member functions, the total number
+// of elements including padding is given by the \c spacing() member function.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::ConstPointer
+ CustomMatrix<Type,AF,PF,true>::data() const noexcept
+{
+ return v_.get();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::Pointer
+ CustomMatrix<Type,AF,PF,true>::data( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return v_.get() + j*mm_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::ConstPointer
+ CustomMatrix<Type,AF,PF,true>::data( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return v_.get() + j*mm_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::Iterator
+ CustomMatrix<Type,AF,PF,true>::begin( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return Iterator( v_.get() + j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::ConstIterator
+ CustomMatrix<Type,AF,PF,true>::begin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return ConstIterator( v_.get() + j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::ConstIterator
+ CustomMatrix<Type,AF,PF,true>::cbegin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return ConstIterator( v_.get() + j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::Iterator
+ CustomMatrix<Type,AF,PF,true>::end( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return Iterator( v_.get() + j*mm_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::ConstIterator
+ CustomMatrix<Type,AF,PF,true>::end( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return ConstIterator( v_.get() + j*mm_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline typename CustomMatrix<Type,AF,PF,true>::ConstIterator
+ CustomMatrix<Type,AF,PF,true>::cend( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return ConstIterator( v_.get() + j*mm_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all matrix elements.
+//
+// \param rhs Scalar value to be assigned to all matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>& CustomMatrix<Type,AF,PF,true>::operator=( const Type& rhs )
+{
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*mm_] = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to static matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the matrix
+// by means of an initializer list:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::rowMajor;
+
+ const int array[9] = { 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0 };
+ blaze::CustomMatrix<int,unaligned,unpadded,rowMajor> A( array, 3UL, 3UL );
+ A = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>&
+ CustomMatrix<Type,AF,PF,true>::operator=( initializer_list< initializer_list<Type> > list )
+{
+ if( list.size() != m_ || determineColumns( list ) > n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to custom matrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ v_[i+j*mm_] = element;
+ ++j;
+ }
+ for( ; j<n_; ++j ) {
+ v_[i+j*mm_] = Type();
+ }
+ ++i;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid array size.
+//
+// This assignment operator offers the option to directly set all elements of the matrix:
+
+ \code
+ using blaze::unaligned;
+ using blaze::unpadded;
+ using blaze::columnMajor;
+
+ const int array[9] = { 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0 };
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::CustomMatrix<int,unaligned,unpadded,columnMajor> A( array, 3UL, 3UL );
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the value 6 in the example). Note that the size of the array must
+// match the size of the custom matrix. Otherwise a \a std::invalid_argument exception is thrown.
+// Also note that after the assignment \a array will have the same entries as \a init.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Other // Data type of the initialization array
+ , size_t M // Number of rows of the initialization array
+ , size_t N > // Number of columns of the initialization array
+inline CustomMatrix<Type,AF,PF,true>&
+ CustomMatrix<Type,AF,PF,true>::operator=( const Other (&array)[M][N] )
+{
+ if( m_ != M || n_ != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" );
+ }
+
+ for( size_t j=0UL; j<N; ++j )
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*mm_] = array[i][j];
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for CustomMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// The matrix is initialized as a copy of the given matrix. In case the current sizes of the two
+// matrices don't match, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>&
+ CustomMatrix<Type,AF,PF,true>::operator=( const CustomMatrix& rhs )
+{
+ if( rhs.rows() != m_ || rhs.columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ smpAssign( *this, ~rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for CustomMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>&
+ CustomMatrix<Type,AF,PF,true>::operator=( CustomMatrix&& rhs ) noexcept
+{
+ m_ = rhs.m_;
+ mm_ = rhs.mm_;
+ n_ = rhs.n_;
+ v_ = std::move( rhs.v_ );
+
+ rhs.m_ = 0UL;
+ rhs.mm_ = 0UL;
+ rhs.n_ = 0UL;
+
+ BLAZE_INTERNAL_ASSERT( rhs.data() == nullptr, "Invalid data reference detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// The matrix is initialized as a copy of the given matrix. In case the current sizes of the two
+// matrices don't match, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline CustomMatrix<Type,AF,PF,true>&
+ CustomMatrix<Type,AF,PF,true>::operator=( const Matrix<MT,SO>& rhs )
+{
+ typedef TransExprTrait_<This> TT;
+ typedef CTransExprTrait_<This> CT;
+ typedef InvExprTrait_<This> IT;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( IsSame<MT,TT>::value && (~rhs).isAliased( this ) ) {
+ transpose();
+ }
+ else if( IsSame<MT,CT>::value && (~rhs).isAliased( this ) ) {
+ ctranspose();
+ }
+ else if( !IsSame<MT,IT>::value && (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpAssign( *this, tmp );
+ }
+ else {
+ if( IsSparseMatrix<MT>::value )
+ reset();
+ smpAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline CustomMatrix<Type,AF,PF,true>&
+ CustomMatrix<Type,AF,PF,true>::operator+=( const Matrix<MT,SO>& rhs )
+{
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpAddAssign( *this, tmp );
+ }
+ else {
+ smpAddAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline CustomMatrix<Type,AF,PF,true>&
+ CustomMatrix<Type,AF,PF,true>::operator-=( const Matrix<MT,SO>& rhs )
+{
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpSubAssign( *this, tmp );
+ }
+ else {
+ smpSubAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline CustomMatrix<Type,AF,PF,true>&
+ CustomMatrix<Type,AF,PF,true>::operator*=( const Matrix<MT,SO>& rhs )
+{
+ if( m_ != n_ || (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const MultTrait_< ResultType, ResultType_<MT> > tmp( *this * (~rhs) );
+ smpAssign( *this, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, CustomMatrix<Type,AF,PF,true> >&
+ CustomMatrix<Type,AF,PF,true>::operator*=( Other rhs )
+{
+ smpAssign( *this, (*this) * rhs );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, CustomMatrix<Type,AF,PF,true> >&
+ CustomMatrix<Type,AF,PF,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ smpAssign( *this, (*this) / rhs );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline size_t CustomMatrix<Type,AF,PF,true>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline size_t CustomMatrix<Type,AF,PF,true>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two columns.
+//
+// \return The spacing between the beginning of two columns.
+//
+// This function returns the spacing between the beginning of two column, i.e. the total number
+// of elements of a column.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline size_t CustomMatrix<Type,AF,PF,true>::spacing() const noexcept
+{
+ return mm_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline size_t CustomMatrix<Type,AF,PF,true>::capacity() const noexcept
+{
+ return mm_ * n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified column.
+//
+// \param j The index of the column.
+// \return The current capacity of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline size_t CustomMatrix<Type,AF,PF,true>::capacity( size_t j ) const noexcept
+{
+ UNUSED_PARAMETER( j );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return mm_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the dense matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline size_t CustomMatrix<Type,AF,PF,true>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ if( !isDefault( v_[i+j*mm_] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified column.
+//
+// \param j The index of the column.
+// \return The number of non-zero elements of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline size_t CustomMatrix<Type,AF,PF,true>::nonZeros( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t iend( j*mm_ + m_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=j*mm_; i<iend; ++i )
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline void CustomMatrix<Type,AF,PF,true>::reset()
+{
+ using blaze::clear;
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ clear( v_[i+j*mm_] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified column to the default initial values.
+//
+// \param j The index of the column.
+// \return void
+//
+// This function reset the values in the specified column to their default value. Note that
+// the capacity of the column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline void CustomMatrix<Type,AF,PF,true>::reset( size_t j )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ for( size_t i=0UL; i<m_; ++i )
+ clear( v_[i+j*mm_] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the \f$ M \times N \f$ matrix.
+//
+// \return void
+//
+// After the clear() function, the size of the matrix is 0.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline void CustomMatrix<Type,AF,PF,true>::clear()
+{
+ m_ = 0UL;
+ mm_ = 0UL;
+ n_ = 0UL;
+ v_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::logic_error Impossible transpose operation.
+//
+// In case the matrix is not a square matrix, a \a std::logic_error exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>& CustomMatrix<Type,AF,PF,true>::transpose()
+{
+ using std::swap;
+
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
+ }
+
+ for( size_t j=1UL; j<n_; ++j )
+ for( size_t i=0UL; i<j; ++i )
+ swap( v_[i+j*mm_], v_[j+i*mm_] );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::logic_error Impossible transpose operation.
+//
+// In case the matrix is not a square matrix, a \a std::logic_error exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline CustomMatrix<Type,AF,PF,true>& CustomMatrix<Type,AF,PF,true>::ctranspose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
+ }
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ cswap( v_[i+j*mm_], v_[j+i*mm_] );
+ }
+ conjugate( v_[j+j*mm_] );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Other > // Data type of the scalar value
+inline CustomMatrix<Type,AF,PF,true>& CustomMatrix<Type,AF,PF,true>::scale( const Other& scalar )
+{
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*mm_] *= scalar;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline void CustomMatrix<Type,AF,PF,true>::swap( CustomMatrix& m ) noexcept
+{
+ using std::swap;
+
+ swap( m_ , m.m_ );
+ swap( mm_, m.mm_ );
+ swap( n_ , m.n_ );
+ swap( v_ , m.v_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RESOURCE MANAGEMENT FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resets the custom matrix and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This function resets the custom matrix to the given array of elements of size \f$ m \times n \f$.
+// The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This function is \b NOT available for padded custom matrices!
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom matrix referencing the array goes out of scope.
+// \note The custom matrix does NOT take responsibility for the new array of elements!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline void CustomMatrix<Type,AF,PF,true>::reset( Type* ptr, size_t m, size_t n )
+{
+ BLAZE_STATIC_ASSERT( PF == unpadded );
+
+ CustomMatrix tmp( ptr, m, n );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resets the custom matrix and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param mm The total number of elements between two columns.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This function resets the custom matrix to the given array of elements of size \f$ m \times n \f$.
+// The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom matrix referencing the array goes out of scope.
+// \note The custom matrix does NOT take responsibility for the new array of elements!
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline void CustomMatrix<Type,AF,PF,true>::reset( Type* ptr, size_t m, size_t n, size_t mm )
+{
+ CustomMatrix tmp( ptr, m, n, mm );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resets the custom matrix and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param d The deleter to destroy the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This function resets the custom matrix to the given array of elements of size \f$ m \times n \f$.
+// The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This function is \b NOT available for padded custom matrices!
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom matrix referencing the array goes out of scope.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Deleter // Type of the custom deleter
+ , typename > // Type restriction on the custom deleter
+inline void CustomMatrix<Type,AF,PF,true>::reset( Type* ptr, size_t m, size_t n, Deleter d )
+{
+ BLAZE_STATIC_ASSERT( !IsClass<Deleter>::value || PF == unpadded );
+
+ CustomMatrix tmp( ptr, m, n, d );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resets the custom matrix and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the matrix.
+// \param m The number of rows of the array of elements.
+// \param n The number of columns of the array of elements.
+// \param mm The total number of elements between two columns.
+// \param d The deleter to destroy the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom matrix.
+//
+// This function resets the custom matrix to the given array of elements of size \f$ m \times n \f$.
+// The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom matrix referencing the array goes out of scope.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Deleter > // Type of the custom deleter
+inline void CustomMatrix<Type,AF,PF,true>::reset( Type* ptr, size_t m, size_t n, size_t mm, Deleter d )
+{
+ CustomMatrix tmp( ptr, m, n, mm, d );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Other > // Data type of the foreign expression
+inline bool CustomMatrix<Type,AF,PF,true>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename Other > // Data type of the foreign expression
+inline bool CustomMatrix<Type,AF,PF,true>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each column of the matrix are guaranteed to conform to
+// the alignment restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline bool CustomMatrix<Type,AF,PF,true>::isAligned() const noexcept
+{
+ return ( AF || ( checkAlignment( v_.get() ) && rows() % SIMDSIZE == 0UL ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+inline bool CustomMatrix<Type,AF,PF,true>::canSMPAssign() const noexcept
+{
+ return ( columns() > SMP_DMATASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the row index must be a multiple of the number of values inside
+// the SIMD element. This function must \b NOT be called explicitly! It is used internally
+// for the performance optimized evaluation of expression templates. Calling this function
+// explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+BLAZE_ALWAYS_INLINE typename CustomMatrix<Type,AF,PF,true>::SIMDType
+ CustomMatrix<Type,AF,PF,true>::load( size_t i, size_t j ) const noexcept
+{
+ if( AF && PF )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+BLAZE_ALWAYS_INLINE typename CustomMatrix<Type,AF,PF,true>::SIMDType
+ CustomMatrix<Type,AF,PF,true>::loada( size_t i, size_t j ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= ( PF ? mm_ : m_ ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !PF || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+i+j*mm_ ), "Invalid alignment detected" );
+
+ return loada( v_.get()+i+j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+BLAZE_ALWAYS_INLINE typename CustomMatrix<Type,AF,PF,true>::SIMDType
+ CustomMatrix<Type,AF,PF,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= ( PF ? mm_ : m_ ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+
+ return loadu( v_.get()+i+j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller then the number
+// of columns. Additionally, the row index must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+BLAZE_ALWAYS_INLINE void
+ CustomMatrix<Type,AF,PF,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( AF && PF )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+BLAZE_ALWAYS_INLINE void
+ CustomMatrix<Type,AF,PF,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= ( PF ? mm_ : m_ ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !PF || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+i+j*mm_ ), "Invalid alignment detected" );
+
+ storea( v_.get()+i+j*mm_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+BLAZE_ALWAYS_INLINE void
+ CustomMatrix<Type,AF,PF,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= ( PF ? mm_ : m_ ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+
+ storeu( v_.get()+i+j*mm_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the row index must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+BLAZE_ALWAYS_INLINE void
+ CustomMatrix<Type,AF,PF,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= ( PF ? mm_ : m_ ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !PF || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+i+j*mm_ ), "Invalid alignment detected" );
+
+ stream( v_.get()+i+j*mm_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename CustomMatrix<Type,AF,PF,true>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ CustomMatrix<Type,AF,PF,true>::assign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i +j*mm_] = (~rhs)(i ,j);
+ v_[i+1UL+j*mm_] = (~rhs)(i+1UL,j);
+ }
+ if( ipos < m_ ) {
+ v_[ipos+j*mm_] = (~rhs)(ipos,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename CustomMatrix<Type,AF,PF,true>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ CustomMatrix<Type,AF,PF,true>::assign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !PF || !IsPadded<MT>::value );
+
+ const size_t ipos( ( remainder )?( m_ & size_t(-SIMDSIZE) ):( m_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ if( AF && PF && useStreaming &&
+ ( m_*n_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) && !(~rhs).isAliased( this ) )
+ {
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ stream( i, j, (~rhs).load(i,j) );
+ }
+ for( ; remainder && i<m_; ++i ) {
+ v_[i+j*mm_] = (~rhs)(i,j);
+ }
+ }
+ }
+ else
+ {
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+ ConstIterator_<MT> it( (~rhs).begin(j) );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ store( i , j, it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , j, it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, j, it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, j, it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, j, it.load() );
+ }
+ for( ; remainder && i<m_; ++i, ++it ) {
+ v_[i+j*mm_] = *it;
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline void CustomMatrix<Type,AF,PF,true>::assign( const DenseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( n_, jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( m_, ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ v_[i+j*mm_] = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,true>::assign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*mm_] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,true>::assign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*mm_] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename CustomMatrix<Type,AF,PF,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ CustomMatrix<Type,AF,PF,true>::addAssign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[j+j*mm_] += (~rhs)(j,j);
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ size_t i( ibegin );
+
+ for( ; (i+2UL) <= iend; i+=2UL ) {
+ v_[i +j*mm_] += (~rhs)(i ,j);
+ v_[i+1UL+j*mm_] += (~rhs)(i+1UL,j);
+ }
+ if( i < iend ) {
+ v_[i+j*mm_] += (~rhs)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename CustomMatrix<Type,AF,PF,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ CustomMatrix<Type,AF,PF,true>::addAssign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !PF || !IsPadded<MT>::value );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+ ConstIterator_<MT> it( (~rhs).begin(j) + ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ store( i , j, load(i ,j) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , j, load(i+SIMDSIZE ,j) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, j, load(i+SIMDSIZE*2UL,j) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, j, load(i+SIMDSIZE*3UL,j) + it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, j, load(i,j) + it.load() );
+ }
+ for( ; remainder && i<iend; ++i, ++it ) {
+ v_[i+j*mm_] += *it;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline void CustomMatrix<Type,AF,PF,true>::addAssign( const DenseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( n_, jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block )
+ {
+ if( IsLower<MT>::value && ii < jj ) continue;
+ if( IsUpper<MT>::value && ii > jj ) break;
+
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( max( ( IsStrictlyLower<MT>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( min( ( IsStrictlyUpper<MT>::value ? j : j+1UL ), m_, ii+block ) )
+ :( min( m_, ii+block ) ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ v_[i+j*mm_] += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,true>::addAssign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*mm_] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,true>::addAssign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*mm_] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename CustomMatrix<Type,AF,PF,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ CustomMatrix<Type,AF,PF,true>::subAssign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[j+j*mm_] -= (~rhs)(j,j);
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ size_t i( ibegin );
+
+ for( ; (i+2UL) <= iend; i+=2UL ) {
+ v_[i +j*mm_] -= (~rhs)(i ,j);
+ v_[i+1+j*mm_] -= (~rhs)(i+1,j);
+ }
+ if( i < iend ) {
+ v_[i+j*mm_] -= (~rhs)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a column-major
+// dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename CustomMatrix<Type,AF,PF,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ CustomMatrix<Type,AF,PF,true>::subAssign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !PF || !IsPadded<MT>::value );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+ ConstIterator_<MT> it( (~rhs).begin(j) + ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ store( i , j, load(i ,j) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , j, load(i+SIMDSIZE ,j) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, j, load(i+SIMDSIZE*2UL,j) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, j, load(i+SIMDSIZE*3UL,j) - it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, j, load(i,j) - it.load() );
+ }
+ for( ; remainder && i<iend; ++i, ++it ) {
+ v_[i+j*mm_] -= *it;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side dense matrix
+inline void CustomMatrix<Type,AF,PF,true>::subAssign( const DenseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( n_, jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block )
+ {
+ if( IsLower<MT>::value && ii < jj ) continue;
+ if( IsUpper<MT>::value && ii > jj ) break;
+
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( max( ( IsStrictlyLower<MT>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( min( ( IsStrictlyUpper<MT>::value ? j : j+1UL ), m_, ii+block ) )
+ :( min( m_, ii+block ) ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ v_[i+j*mm_] -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,true>::subAssign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*mm_] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF > // Padding flag
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CustomMatrix<Type,AF,PF,true>::subAssign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*mm_] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CUSTOMMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name CustomMatrix operators */
+//@{
+template< typename Type, bool AF, bool PF, bool SO >
+inline void reset( CustomMatrix<Type,AF,PF,SO>& m );
+
+template< typename Type, bool AF, bool PF, bool SO >
+inline void reset( CustomMatrix<Type,AF,PF,SO>& m, size_t i );
+
+template< typename Type, bool AF, bool PF, bool SO >
+inline void clear( CustomMatrix<Type,AF,PF,SO>& m );
+
+template< typename Type, bool AF, bool PF, bool SO >
+inline bool isDefault( const CustomMatrix<Type,AF,PF,SO>& m );
+
+template< typename Type, bool AF, bool PF, bool SO >
+inline bool isIntact( const CustomMatrix<Type,AF,PF,SO>& m );
+
+template< typename Type, bool AF, bool PF, bool SO >
+inline void swap( CustomMatrix<Type,AF,PF,SO>& a, CustomMatrix<Type,AF,PF,SO>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given custom matrix.
+// \ingroup custom_matrix
+//
+// \param m The matrix to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void reset( CustomMatrix<Type,AF,PF,SO>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column of the given custom matrix.
+// \ingroup custom_matrix
+//
+// \param m The matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given custom matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void reset( CustomMatrix<Type,AF,PF,SO>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given custom matrix.
+// \ingroup custom_matrix
+//
+// \param m The matrix to be cleared.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void clear( CustomMatrix<Type,AF,PF,SO>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given custom matrix is in default state.
+// \ingroup custom_matrix
+//
+// \param m The matrix to be tested for its default state.
+// \return \a true in case the given matrix's rows and columns are zero, \a false otherwise.
+//
+// This function checks whether the custom matrix is in default (constructed) state, i.e. if
+// it's number of rows and columns is 0. In case it is in default state, the function returns
+// \a true, else it will return \a false. The following example demonstrates the use of the
+// \a isDefault() function:
+
+ \code
+ using blaze::aligned;
+ using blaze::padded;
+
+ blaze::CustomMatrix<int,aligned,padded> A( ... );
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline bool isDefault( const CustomMatrix<Type,AF,PF,SO>& m )
+{
+ return ( m.rows() == 0UL && m.columns() == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given custom matrix are intact.
+// \ingroup custom_matrix
+//
+// \param m The custom matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the custom matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::aligned;
+ using blaze::padded;
+
+ blaze::CustomMatrix<int,aligned,padded> A( ... );
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline bool isIntact( const CustomMatrix<Type,AF,PF,SO>& m )
+{
+ return ( m.rows() * m.columns() <= m.capacity() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two custom matrices.
+// \ingroup custom_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool SO > // Storage order
+inline void swap( CustomMatrix<Type,AF,PF,SO>& a, CustomMatrix<Type,AF,PF,SO>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool AF, bool PF, bool SO >
+struct HasConstDataAccess< CustomMatrix<T,AF,PF,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool AF, bool PF, bool SO >
+struct HasMutableDataAccess< CustomMatrix<T,AF,PF,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISCUSTOM SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool AF, bool PF, bool SO >
+struct IsCustom< CustomMatrix<T,AF,PF,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool PF, bool SO >
+struct IsAligned< CustomMatrix<T,aligned,PF,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool AF, bool SO >
+struct IsPadded< CustomMatrix<T,AF,padded,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t M, size_t N >
+struct AddTrait< CustomMatrix<T1,AF,PF,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct AddTrait< CustomMatrix<T1,AF,PF,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF >
+struct AddTrait< StaticMatrix<T1,M,N,SO>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct AddTrait< StaticMatrix<T1,M,N,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t M, size_t N >
+struct AddTrait< CustomMatrix<T1,AF,PF,SO>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct AddTrait< CustomMatrix<T1,AF,PF,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF >
+struct AddTrait< HybridMatrix<T1,M,N,SO>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct AddTrait< HybridMatrix<T1,M,N,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2 >
+struct AddTrait< CustomMatrix<T1,AF,PF,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
+struct AddTrait< CustomMatrix<T1,AF,PF,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool SO, typename T2, bool AF, bool PF >
+struct AddTrait< DynamicMatrix<T1,SO>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct AddTrait< DynamicMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool SO, typename T2, bool AF2, bool PF2 >
+struct AddTrait< CustomMatrix<T1,AF1,PF1,SO>, CustomMatrix<T2,AF2,PF2,SO> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool SO1, typename T2, bool AF2, bool PF2, bool SO2 >
+struct AddTrait< CustomMatrix<T1,AF1,PF1,SO1>, CustomMatrix<T2,AF2,PF2,SO2> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t M, size_t N >
+struct SubTrait< CustomMatrix<T1,AF,PF,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct SubTrait< CustomMatrix<T1,AF,PF,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF >
+struct SubTrait< StaticMatrix<T1,M,N,SO>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct SubTrait< StaticMatrix<T1,M,N,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t M, size_t N >
+struct SubTrait< CustomMatrix<T1,AF,PF,SO>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct SubTrait< CustomMatrix<T1,AF,PF,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF >
+struct SubTrait< HybridMatrix<T1,M,N,SO>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct SubTrait< HybridMatrix<T1,M,N,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2 >
+struct SubTrait< CustomMatrix<T1,AF,PF,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
+struct SubTrait< CustomMatrix<T1,AF,PF,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool SO, typename T2, bool AF, bool PF >
+struct SubTrait< DynamicMatrix<T1,SO>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct SubTrait< DynamicMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool SO, typename T2, bool AF2, bool PF2 >
+struct SubTrait< CustomMatrix<T1,AF1,PF1,SO>, CustomMatrix<T2,AF2,PF2,SO> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool SO1, typename T2, bool AF2, bool PF2, bool SO2 >
+struct SubTrait< CustomMatrix<T1,AF1,PF1,SO1>, CustomMatrix<T2,AF2,PF2,SO2> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool SO, typename T2 >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, typename T2, bool AF, bool PF, bool SO >
+struct MultTrait< T1, CustomMatrix<T2,AF,PF,SO>, EnableIf_<IsNumeric<T1> > >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t N >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO>, StaticVector<T2,N,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2, bool AF, bool PF, bool SO >
+struct MultTrait< StaticVector<T1,N,true>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t N >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO>, HybridVector<T2,N,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2, bool AF, bool PF, bool SO >
+struct MultTrait< HybridVector<T1,N,true>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2 >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO>, DynamicVector<T2,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, bool AF, bool PF, bool SO >
+struct MultTrait< DynamicVector<T1,true>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool SO, typename T2, bool AF2, bool PF2 >
+struct MultTrait< CustomMatrix<T1,AF1,PF1,SO>, CustomVector<T2,AF2,PF2,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF1, bool PF1, typename T2, bool AF2, bool PF2, bool SO >
+struct MultTrait< CustomVector<T1,AF1,PF1,true>, CustomMatrix<T2,AF2,PF2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2 >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO>, CompressedVector<T2,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, bool AF, bool PF, bool SO >
+struct MultTrait< CompressedVector<T1,true>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct MultTrait< StaticMatrix<T1,M,N,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct MultTrait< HybridMatrix<T1,M,N,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct MultTrait< DynamicMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool SO1, typename T2, bool AF2, bool PF2, bool SO2 >
+struct MultTrait< CustomMatrix<T1,AF1,PF1,SO1>, CustomMatrix<T2,AF2,PF2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool SO, typename T2 >
+struct DivTrait< CustomMatrix<T1,AF,PF,SO>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = DynamicMatrix< DivTrait_<T1,T2>, SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool SO >
+struct SubmatrixTrait< CustomMatrix<T1,AF,PF,SO> >
+{
+ using Type = DynamicMatrix<T1,SO>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool SO >
+struct RowTrait< CustomMatrix<T1,AF,PF,SO> >
+{
+ using Type = DynamicVector<T1,true>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool SO >
+struct ColumnTrait< CustomMatrix<T1,AF,PF,SO> >
+{
+ using Type = DynamicVector<T1,false>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/CustomVector.h b/src/cpu/blaze/math/dense/CustomVector.h
new file mode 100644
index 00000000..495c3166
--- /dev/null
+++ b/src/cpu/blaze/math/dense/CustomVector.h
@@ -0,0 +1,5654 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/CustomVector.h
+// \brief Header file for the implementation of a customizable vector
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_CUSTOMVECTOR_H_
+#define _BLAZE_MATH_DENSE_CUSTOMVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <boost/smart_ptr/shared_array.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/dense/DenseIterator.h>
+#include <blaze/math/dense/DynamicVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/PaddingFlag.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsCustom.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/system/CacheSize.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/system/TransposeFlag.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/policies/NoDelete.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/AlignmentOf.h>
+#include <blaze/util/typetraits/IsClass.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup custom_vector CustomVector
+// \ingroup dense_vector
+*/
+/*!\brief Efficient implementation of a customizable vector.
+// \ingroup custom_vector
+//
+// \section customvector_general General
+//
+// The CustomVector class template provides the functionality to represent an external array of
+// elements of arbitrary type and a fixed size as a native \b Blaze dense vector data structure.
+// Thus in contrast to all other dense vector types a custom vector does not perform any kind
+// of memory allocation by itself, but it is provided with an existing array of element during
+// construction. A custom vector can therefore be considered an alias to the existing array.
+//
+// The type of the elements, the properties of the given array of elements and the transpose
+// flag of the vector can be specified via the following four template parameters:
+
+ \code
+ template< typename Type, bool AF, bool PF, bool TF >
+ class CustomVector;
+ \endcode
+
+// - Type: specifies the type of the vector elements. CustomVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - AF : specifies whether the represented, external arrays are properly aligned with
+// respect to the available instruction set (SSE, AVX, ...) or not.
+// - PF : specified whether the represented, external arrays are properly padded with
+// respect to the available instruction set (SSE, AVX, ...) or not.
+// - TF : specifies whether the vector is a row vector (\a blaze::rowVector) or a column
+// vector (\a blaze::columnVector). The default value is \a blaze::columnVector.
+//
+// The following examples give an impression of several possible types of custom vectors:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+
+ // Definition of a custom column vector for unaligned, unpadded integer arrays
+ typedef CustomVector<int,unaligned,unpadded,columnVector> UnalignedUnpadded;
+
+ // Definition of a custom column vector for unaligned but padded 'float' arrays
+ typedef CustomVector<float,unaligned,padded,columnVector> UnalignedPadded;
+
+ // Definition of a custom row vector for aligned, unpadded 'double' arrays
+ typedef CustomVector<double,aligned,unpadded,rowVector> AlignedUnpadded;
+
+ // Definition of a custom row vector for aligned, padded 'complex<double>' arrays
+ typedef CustomVector<complex<double>,aligned,padded,rowVector> AlignedPadded;
+ \endcode
+
+// \n \section customvector_special_properties Special Properties of Custom Vectors
+//
+// In comparison with the remaining \b Blaze dense vector types CustomVector has several special
+// characteristics. All of these result from the fact that a custom vector is not performing any
+// kind of memory allocation, but instead is given an existing array of elements. The following
+// sections discuss all of these characteristics:
+//
+// -# <b>\ref customvector_memory_management</b>
+// -# <b>\ref customvector_copy_operations</b>
+// -# <b>\ref customvector_alignment</b>
+// -# <b>\ref customvector_padding</b>
+//
+// \n \subsection customvector_memory_management Memory Management
+//
+// The CustomVector class template acts as an adaptor for an existing array of elements. As such
+// it provides everything that is required to use the array just like a native \b Blaze dense
+// vector data structure. However, this flexibility comes with the price that the user of a custom
+// vector is responsible for the resource management.
+//
+// When constructing a custom vector there are two choices: Either a user manually manages the
+// array of elements outside the custom vector, or alternatively passes the responsibility for
+// the memory management to an instance of CustomVector. In the second case the CustomVector
+// class employs shared ownership between all copies of the custom vector, which reference the
+// same array.
+//
+// The following examples give an impression of several possible types of custom vectors:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::ArrayDelete;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ // Definition of a 3-dimensional custom vector with unaligned, unpadded and externally
+ // managed integer array. Note that the std::vector must be guaranteed to outlive the
+ // custom vector!
+ std::vector<int> vec( 3UL );
+ CustomVector<int,unaligned,unpadded> a( &vec[0], 3UL );
+
+ // Definition of a custom row vector with size 3 for unaligned, unpadded integer arrays.
+ // The responsibility for the memory management is passed to the custom vector by
+ // providing a deleter of type 'blaze::ArrayDelete' that is used during the destruction
+ // of the custom vector.
+ CustomVector<int,unaligned,unpadded,rowVector> b( new int[3], 3UL, ArrayDelete() );
+
+ // Definition of a custom vector with size 3 and capacity 16 with aligned and padded
+ // integer array. The memory management is passed to the custom vector by providing a
+ // deleter of type 'blaze::Deallocate'.
+ CustomVector<int,aligned,padded> c( allocate<int>( 16UL ), 3UL, 16UL, Deallocate() );
+ \endcode
+
+// It is possible to pass any type of deleter to the constructor. The deleter is only required
+// to provide a function call operator that can be passed the pointer to the managed array. As
+// an example the following code snipped shows the implementation of two native \b Blaze deleters
+// blaze::ArrayDelete and blaze::Deallocate:
+
+ \code
+ namespace blaze {
+
+ struct ArrayDelete
+ {
+ template< typename Type >
+ inline void operator()( Type ptr ) const { boost::checked_array_delete( ptr ); }
+ };
+
+ struct Deallocate
+ {
+ template< typename Type >
+ inline void operator()( Type ptr ) const { deallocate( ptr ); }
+ };
+
+ } // namespace blaze
+ \endcode
+
+// \n \subsection customvector_copy_operations Copy Operations
+//
+// As with all dense vectors it is possible to copy construct a custom vector:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::unaligned;
+ using blaze::unpadded;
+
+ typedef CustomVector<int,unaligned,unpadded> CustomType;
+
+ std::vector<int> vec( 5UL, 10 ); // Vector of 5 integers of the value 10
+ CustomType a( &vec[0], 5UL ); // Represent the std::vector as Blaze dense vector
+ a[1] = 20; // Also modifies the std::vector
+
+ CustomType b( a ); // Creating a copy of vector a
+ b[2] = 20; // Also affect vector a and the std::vector
+ \endcode
+
+// It is important to note that a custom vector acts as a reference to the specified array. Thus
+// the result of the copy constructor is a new custom vector that is referencing and representing
+// the same array as the original custom vector. In case a deleter has been provided to the first
+// custom vector, both vectors share the responsibility to destroy the array when the last vector
+// goes out of scope.
+//
+// In contrast to copy construction, just as with references, copy assignment does not change
+// which array is referenced by the custom vector, but modifies the values of the array:
+
+ \code
+ std::vector<int> vec2( 5UL, 4 ); // Vector of 5 integers of the value 4
+ CustomType c( &vec2[0], 5UL ); // Represent the std::vector as Blaze dense vector
+
+ a = c; // Copy assignment: Set all values of vector a and b to 4.
+ \endcode
+
+// \n \subsection customvector_alignment Alignment
+//
+// In case the custom vector is specified as \a aligned the passed array must be guaranteed to
+// be aligned according to the requirements of the used instruction set (SSE, AVX, ...). For
+// instance, if AVX is active an array of integers must be 32-bit aligned:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::Deallocate;
+ using blaze::aligned;
+ using blaze::unpadded;
+
+ int* array = blaze::allocate<int>( 5UL ); // Needs to be 32-bit aligned
+ CustomVector<int,aligned,unpadded> a( array, 5UL, Deallocate() );
+ \endcode
+
+// In case the alignment requirements are violated, a \a std::invalid_argument exception is
+// thrown.
+//
+// \n \subsection customvector_padding Padding
+//
+// Adding padding elements to the end of an array can have a significant impact on performance.
+// For instance, assuming that AVX is available, then two aligned, padded, 3-dimensional vectors
+// of double precision values can be added via a single SIMD addition operations:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::padded;
+
+ typedef CustomVector<double,aligned,padded> CustomType;
+
+ // Creating padded custom vectors of size 3 and a capacity of 4
+ CustomType a( allocate<double>( 4UL ), 3UL, 4UL, Deallocate() );
+ CustomType b( allocate<double>( 4UL ), 3UL, 4UL, Deallocate() );
+ CustomType c( allocate<double>( 4UL ), 3UL, 4UL, Deallocate() );
+
+ // ... Initialization
+
+ c = a + b; // AVX-based vector addition
+ \endcode
+
+// In this example, maximum performance is possible. However, in case no padding elements are
+// inserted, a scalar addition has to be used:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unpadded;
+
+ typedef CustomVector<double,aligned,unpadded> CustomType;
+
+ // Creating unpadded custom vector of size 3
+ CustomType a( allocate<double>( 3UL ), 3UL, Deallocate() );
+ CustomType b( allocate<double>( 3UL ), 3UL, Deallocate() );
+ CustomType c( allocate<double>( 3UL ), 3UL, Deallocate() );
+
+ // ... Initialization
+
+ c = a + b; // Scalar vector addition
+ \endcode
+
+// Note the different number of constructor parameters for unpadded and padded custom vectors:
+// In contrast to unpadded vectors, where during the construction only the size of the array
+// has to be specified, during the construction of a padded custom vector it is additionally
+// necessary to explicitly specify the capacity of the array.
+//
+// The number of padding elements is required to be sufficient with respect to the available
+// instruction set: In case of an aligned padded custom vector the added padding elements must
+// guarantee that the capacity is greater or equal than the size and a multiple of the SIMD vector
+// width. In case of unaligned padded vectors the number of padding elements can be greater or
+// equal the number of padding elements of an aligned padded custom vector. In case the padding
+// is insufficient with respect to the available instruction set, a \a std::invalid_argument
+// exception is thrown.
+//
+// Please also note that \b Blaze will zero initialize the padding elements in order to achieve
+// maximum performance!
+//
+//
+// \n \section customvector_arithmetic_operations Arithmetic Operations
+//
+// The use of custom vectors in arithmetic operations is designed to be as natural and intuitive
+// as possible. All operations (addition, subtraction, multiplication, scaling, ...) can be
+// expressed similar to a text book representation. Also, custom vectors can be combined with all
+// other dense and sparse vectors and matrices. The following example gives an impression of the
+// use of CustomVector:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::CompressedVector;
+ using blaze::DynamicMatrix;
+ using blaze::ArrayDelete;
+ using blaze::Deallocate;
+ using blaze::allocate;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+
+ // Non-initialized custom column vector of size 2. All given arrays are considered to be
+ // unaligned and unpadded. The memory is managed via 'ArrayDelete'.
+ CustomVector<double,unaligned,unpadded> a( new double[2], 2UL, ArrayDelete() );
+
+ a[0] = 1.0; // Initialization of the first element
+ a[1] = 2.0; // Initialization of the second element
+
+ // Non-initialized custom column vector of size 2 and capacity 4. All given arrays are required
+ // to be properly aligned and padded. The memory is managed via 'Deallocate'.
+ CustomVector<double,aligned,padded> b( allocate<double>( 4UL ), 2UL, 4UL, Deallocate() );
+
+ b = 2.0; // Homogeneous initialization of all elements
+
+ CompressedVector<float> c( 2 ); // Empty sparse single precision vector
+ DynamicVector<double> d; // Default constructed dynamic vector
+ DynamicMatrix<double> A; // Default constructed row-major matrix
+
+ d = a + b; // Vector addition between custom vectors of equal element type
+ d = a - c; // Vector subtraction between a dense and sparse vector with different element types
+ d = a * b; // Component-wise vector multiplication
+
+ a *= 2.0; // In-place scaling of vector
+ d = a * 2.0; // Scaling of vector a
+ d = 2.0 * a; // Scaling of vector a
+
+ d += a - b; // Addition assignment
+ d -= a + c; // Subtraction assignment
+ d *= a * b; // Multiplication assignment
+
+ double scalar = trans( a ) * b; // Scalar/dot/inner product between two vectors
+
+ A = a * trans( b ); // Outer product between two vectors
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF = defaultTransposeFlag > // Transpose flag
+class CustomVector : public DenseVector< CustomVector<Type,AF,PF,TF>, TF >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef CustomVector<Type,AF,PF,TF> This; //!< Type of this CustomVector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this CustomVector instance.
+ typedef DynamicVector<Type,TF> ResultType; //!< Result type for expression template evaluations.
+ typedef DynamicVector<Type,!TF> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the vector elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the vector elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations
+ typedef const CustomVector& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant vector value.
+ typedef const Type& ConstReference; //!< Reference to a constant vector value.
+ typedef Type* Pointer; //!< Pointer to a non-constant vector value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant vector value.
+
+ typedef DenseIterator<Type,AF> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,AF> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a CustomVector with different data/element type.
+ */
+ template< typename ET > // Data type of the other vector
+ struct Rebind {
+ typedef CustomVector<ET,AF,PF,TF> Other; //!< The type of the other CustomVector.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
+ in can be optimized via SIMD operations. In case the element type of the vector is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline CustomVector();
+ explicit inline CustomVector( Type* ptr, size_t n );
+ explicit inline CustomVector( Type* ptr, size_t n, size_t nn );
+
+ template< typename Deleter, typename = EnableIf_<IsClass<Deleter> > >
+ explicit inline CustomVector( Type* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ explicit inline CustomVector( Type* ptr, size_t n, size_t nn, Deleter d );
+
+ inline CustomVector( const CustomVector& v );
+ inline CustomVector( CustomVector&& v ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) noexcept;
+ inline ConstReference operator[]( size_t index ) const noexcept;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin () noexcept;
+ inline ConstIterator begin () const noexcept;
+ inline ConstIterator cbegin() const noexcept;
+ inline Iterator end () noexcept;
+ inline ConstIterator end () const noexcept;
+ inline ConstIterator cend () const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline CustomVector& operator=( const Type& rhs );
+ inline CustomVector& operator=( initializer_list<Type> list );
+
+ template< typename Other, size_t N >
+ inline CustomVector& operator=( const Other (&array)[N] );
+
+ inline CustomVector& operator=( const CustomVector& rhs );
+ inline CustomVector& operator=( CustomVector&& rhs ) noexcept;
+
+ template< typename VT > inline CustomVector& operator= ( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CustomVector& operator+=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CustomVector& operator-=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CustomVector& operator*=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CustomVector& operator/=( const DenseVector<VT,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, CustomVector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, CustomVector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline void clear();
+ template< typename Other > inline CustomVector& scale( const Other& scalar );
+ inline void swap( CustomVector& v ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Resource management functions***************************************************************
+ /*!\name Resource management functions */
+ //@{
+ inline void reset( Type* ptr, size_t n );
+ inline void reset( Type* ptr, size_t n, size_t nn );
+
+ template< typename Deleter, typename = EnableIf_<IsClass<Deleter> > >
+ inline void reset( Type* ptr, size_t n, Deleter d );
+
+ template< typename Deleter >
+ inline void reset( Type* ptr, size_t n, size_t nn, Deleter d );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDAdd< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDSub< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDMult< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDDiv< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t size_; //!< The size/dimension of the custom vector.
+ boost::shared_array<Type> v_; //!< The custom array of elements.
+ /*!< Access to the array of elements is gained via the
+ subscript operator. The order of the elements is
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right)\f] */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for CustomVector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>::CustomVector()
+ : size_( 0UL ) // The size/dimension of the vector
+ , v_ ( ) // The custom array of elements
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for an unpadded custom vector of size \a n.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This constructor creates an unpadded custom vector of size \a n. The construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded custom vectors!
+// \note The custom vector does \b NOT take responsibility for the given array of elements!
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>::CustomVector( Type* ptr, size_t n )
+ : size_( n ) // The size/dimension of the vector
+ , v_ ( ) // The custom array of elements
+{
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && !checkAlignment( ptr ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ v_.reset( ptr, NoDelete() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a padded custom vector of size \a n and capacity \a nn.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param nn The maximum size of the given array.
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This constructor creates a padded custom vector of size \a n and capacity \a nn. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified capacity \a nn is insufficient for the given data type \a Type and the
+// available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for unpadded custom vectors!
+// \note The custom vector does \b NOT take responsibility for the given array of elements!
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>::CustomVector( Type* ptr, size_t n, size_t nn )
+ : size_( 0UL ) // The size/dimension of the vector
+ , v_ ( ) // The custom array of elements
+{
+ BLAZE_STATIC_ASSERT( PF == padded );
+
+ UNUSED_PARAMETER( ptr, n, nn );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for an unpadded custom vector of size \a n.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This constructor creates an unpadded custom vector of size \a n. The construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for padded custom vectors!
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Deleter // Type of the custom deleter
+ , typename > // Type restriction on the custom deleter
+inline CustomVector<Type,AF,PF,TF>::CustomVector( Type* ptr, size_t n, Deleter d )
+ : size_( n ) // The size/dimension of the vector
+ , v_ ( ) // The custom array of elements
+{
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && !checkAlignment( ptr ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ v_.reset( ptr, d );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a padded custom vector of size \a n and capacity \a nn.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param nn The maximum size of the given array.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This constructor creates a padded custom vector of size \a n and capacity \a nn. The
+// construction fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified capacity \a nn is insufficient for the given data type \a Type and the
+// available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This constructor is \b NOT available for unpadded custom vectors!
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Deleter > // Type of the custom deleter
+inline CustomVector<Type,AF,PF,TF>::CustomVector( Type* ptr, size_t n, size_t nn, Deleter d )
+ : size_( 0UL ) // The size/dimension of the vector
+ , v_ ( ) // The custom array of elements
+{
+ BLAZE_STATIC_ASSERT( PF == padded );
+
+ UNUSED_PARAMETER( ptr, n, nn, d );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for CustomVector.
+//
+// \param v Vector to be copied.
+//
+// The copy constructor initializes the custom vector as an exact copy of the given custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>::CustomVector( const CustomVector& v )
+ : size_( v.size_ ) // The size/dimension of the vector
+ , v_ ( v.v_ ) // The custom array of elements
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The move constructor for CustomVector.
+//
+// \param v The vector to be moved into this instance.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>::CustomVector( CustomVector&& v ) noexcept
+ : size_( v.size_ ) // The size/dimension of the vector
+ , v_ ( std::move( v.v_ ) ) // The custom array of elements
+{
+ v.size_ = 0UL;
+
+ BLAZE_INTERNAL_ASSERT( v.data() == nullptr, "Invalid data reference detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::Reference
+ CustomVector<Type,AF,PF,TF>::operator[]( size_t index ) noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::ConstReference
+ CustomVector<Type,AF,PF,TF>::operator[]( size_t index ) const noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::Reference
+ CustomVector<Type,AF,PF,TF>::at( size_t index )
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::ConstReference
+ CustomVector<Type,AF,PF,TF>::at( size_t index ) const
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::Pointer
+ CustomVector<Type,AF,PF,TF>::data() noexcept
+{
+ return v_.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::ConstPointer
+ CustomVector<Type,AF,PF,TF>::data() const noexcept
+{
+ return v_.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the custom vector.
+//
+// \return Iterator to the first element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::Iterator
+ CustomVector<Type,AF,PF,TF>::begin() noexcept
+{
+ return Iterator( v_.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the custom vector.
+//
+// \return Iterator to the first element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::ConstIterator
+ CustomVector<Type,AF,PF,TF>::begin() const noexcept
+{
+ return ConstIterator( v_.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the custom vector.
+//
+// \return Iterator to the first element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::ConstIterator
+ CustomVector<Type,AF,PF,TF>::cbegin() const noexcept
+{
+ return ConstIterator( v_.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the custom vector.
+//
+// \return Iterator just past the last element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::Iterator
+ CustomVector<Type,AF,PF,TF>::end() noexcept
+{
+ return Iterator( v_.get() + size_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the custom vector.
+//
+// \return Iterator just past the last element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::ConstIterator
+ CustomVector<Type,AF,PF,TF>::end() const noexcept
+{
+ return ConstIterator( v_.get() + size_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the custom vector.
+//
+// \return Iterator just past the last element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,PF,TF>::ConstIterator
+ CustomVector<Type,AF,PF,TF>::cend() const noexcept
+{
+ return ConstIterator( v_.get() + size_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Homogenous assignment to all vector elements.
+//
+// \param rhs Scalar value to be assigned to all vector elements.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::operator=( const Type& rhs )
+{
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] = rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List assignment to all vector elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to custom vector.
+//
+// This assignment operator offers the option to directly assign to all elements of the vector
+// by means of an initializer list:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::unaliged;
+ using blaze::unpadded;
+
+ const int array[4] = { 1, 2, 3, 4 };
+
+ CustomVector<double,unaligned,unpadded> v( array, 4UL );
+ v = { 5, 6, 7 };
+ \endcode
+
+// The vector elements are assigned the values from the given initializer list. Missing values
+// are reset to their default state. Note that in case the size of the initializer list exceeds
+// the size of the vector, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::operator=( initializer_list<Type> list )
+{
+ if( list.size() > size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to custom vector" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), v_.get() ), v_.get()+size_, Type() );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array assignment to all vector elements.
+//
+// \param array N-dimensional array for the assignment.
+// \return Reference to the assigned vector.
+// \exception std::invalid_argument Invalid array size.
+//
+// This assignment operator offers the option to directly set all elements of the vector. The
+// following example demonstrates this by means of an unaligned, unpadded custom vector:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::unaliged;
+ using blaze::unpadded;
+
+ const int array[4] = { 1, 2, 3, 4 };
+ const int init[4] = { 5, 6, 7 };
+
+ CustomVector<double,unaligned,unpadded> v( array, 4UL );
+ v = init;
+ \endcode
+
+// The vector is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the fourth element in the example). Note that the size of the array
+// must match the size of the custom vector. Otherwise a \a std::invalid_argument exception is
+// thrown. Also note that after the assignment \a array will have the same entries as \a init.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Other // Data type of the initialization array
+ , size_t N > // Dimension of the initialization array
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::operator=( const Other (&array)[N] )
+{
+ if( size_ != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" );
+ }
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = array[i];
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for CustomVector.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// The vector is initialized as a copy of the given vector. In case the current sizes of the two
+// vectors don't match, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::operator=( const CustomVector& rhs )
+{
+ if( rhs.size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ smpAssign( *this, ~rhs );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Move assignment operator for CustomVector.
+//
+// \param rhs The vector to be moved into this instance.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,PF,TF>&
+ CustomVector<Type,AF,PF,TF>::operator=( CustomVector&& rhs ) noexcept
+{
+ size_ = rhs.size_;
+ v_ = std::move( rhs.v_ );
+
+ rhs.size_ = 0UL;
+
+ BLAZE_INTERNAL_ASSERT( rhs.data() == nullptr, "Invalid data reference detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// The vector is initialized as a copy of the given vector. In case the current sizes of the two
+// vectors don't match, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::operator=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ smpAssign( *this, tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::operator+=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ smpAddAssign( *this, tmp );
+ }
+ else {
+ smpAddAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::operator-=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ smpSubAssign( *this, tmp );
+ }
+ else {
+ smpSubAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::operator*=( const Vector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( MultType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( IsSparseVector<VT>::value || (~rhs).canAlias( this ) ) {
+ const MultType tmp( *this * (~rhs) );
+ this->operator=( tmp );
+ }
+ else {
+ smpMultAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,PF,TF>&
+ CustomVector<Type,AF,PF,TF>::operator/=( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( DivType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const DivType tmp( *this / (~rhs) );
+ this->operator=( tmp );
+ }
+ else {
+ smpDivAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a vector and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, CustomVector<Type,AF,PF,TF> >&
+ CustomVector<Type,AF,PF,TF>::operator*=( Other rhs )
+{
+ smpAssign( *this, (*this) * rhs );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a vector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, CustomVector<Type,AF,PF,TF> >&
+ CustomVector<Type,AF,PF,TF>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ smpAssign( *this, (*this) / rhs );
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the size/dimension of the vector.
+//
+// \return The size of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline size_t CustomVector<Type,AF,PF,TF>::size() const noexcept
+{
+ return size_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the vector.
+//
+// \return The capacity of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline size_t CustomVector<Type,AF,PF,TF>::capacity() const noexcept
+{
+ return size_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the vector.
+//
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline size_t CustomVector<Type,AF,PF,TF>::nonZeros() const
+{
+ size_t nonzeros( 0 );
+
+ for( size_t i=0UL; i<size_; ++i ) {
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+ }
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,PF,TF>::reset()
+{
+ using blaze::clear;
+ for( size_t i=0UL; i<size_; ++i )
+ clear( v_[i] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the vector to its default state.
+//
+// \return void
+//
+// This function clears the vector to its default state. In case the vector has been passed the
+// responsibility to manage the given array, it disposes the resource via the specified deleter.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,PF,TF>::clear()
+{
+ size_ = 0UL;
+ v_.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the vector scaling.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline CustomVector<Type,AF,PF,TF>& CustomVector<Type,AF,PF,TF>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] *= scalar;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two vectors.
+//
+// \param v The vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,PF,TF>::swap( CustomVector& v ) noexcept
+{
+ using std::swap;
+
+ swap( size_, v.size_ );
+ swap( v_, v.v_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RESOURCE MANAGEMENT FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Resets the custom vector and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This function resets the custom vector to the given array of elements of size \a n. The
+// function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This function is \b NOT available for padded custom vectors!
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom vector referencing the array goes out of scope.
+// \note The custom vector does NOT take responsibility for the new array of elements!
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,PF,TF>::reset( Type* ptr, size_t n )
+{
+ CustomVector tmp( ptr, n );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resets the custom vector and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param nn The maximum size of the given array.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This function resets the custom vector to the given array of elements of size \a n and
+// capacity \a nn. The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified capacity \a nn is insufficient for the given data type \a Type and
+// the available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This function is \a NOT available for unpadded custom vectors!
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom vector referencing the array goes out of scope.
+// \note The custom vector does NOT take responsibility for the new array of elements!
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,PF,TF>::reset( Type* ptr, size_t n, size_t nn )
+{
+ BLAZE_STATIC_ASSERT( PF == padded );
+
+ UNUSED_PARAMETER( ptr, n, nn );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resets the custom vector and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param d The deleter to destroy the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This function resets the custom vector to the given array of elements of size \a n. The
+// function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...).
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This function is \b NOT available for padded custom vectors!
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom vector referencing the array goes out of scope.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Deleter // Type of the custom deleter
+ , typename > // Type restriction on the custom deleter
+inline void CustomVector<Type,AF,PF,TF>::reset( Type* ptr, size_t n, Deleter d )
+{
+ CustomVector tmp( ptr, n, d );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resets the custom vector and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param nn The maximum size of the given array.
+// \param d The deleter to destroy the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This function resets the custom vector to the given array of elements of size \a n and
+// capacity \a nn. The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified capacity \a nn is insufficient for the given data type \a Type and
+// the available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note This function is \a NOT available for unpadded custom vectors!
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom vector referencing the array goes out of scope.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Deleter > // Type of the custom deleter
+inline void CustomVector<Type,AF,PF,TF>::reset( Type* ptr, size_t n, size_t nn, Deleter d )
+{
+ BLAZE_STATIC_ASSERT( PF == padded );
+
+ UNUSED_PARAMETER( ptr, n, nn, d );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address can alias with the vector. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool CustomVector<Type,AF,PF,TF>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address is aliased with the vector. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool CustomVector<Type,AF,PF,TF>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is properly aligned in memory.
+//
+// \return \a true in case the vector is aligned, \a false if not.
+//
+// This function returns whether the vector is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of the vector are guaranteed to conform to the alignment
+// restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline bool CustomVector<Type,AF,PF,TF>::isAligned() const noexcept
+{
+ return ( AF || checkAlignment( v_.get() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector can be used in SMP assignments.
+//
+// \return \a true in case the vector can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the vector can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current size of the
+// vector).
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline bool CustomVector<Type,AF,PF,TF>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,PF,TF>::SIMDType
+ CustomVector<Type,AF,PF,TF>::load( size_t index ) const noexcept
+{
+ if( AF )
+ return loada( index );
+ else
+ return loadu( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,PF,TF>::SIMDType
+ CustomVector<Type,AF,PF,TF>::loada( size_t index ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+index ), "Invalid vector access index" );
+
+ return loada( v_.get()+index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,PF,TF>::SIMDType
+ CustomVector<Type,AF,PF,TF>::loadu( size_t index ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index< size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
+
+ return loadu( v_.get()+index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void CustomVector<Type,AF,PF,TF>::store( size_t index, const SIMDType& value ) noexcept
+{
+ if( AF )
+ storea( index, value );
+ else
+ storeu( index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void CustomVector<Type,AF,PF,TF>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+index ), "Invalid vector access index" );
+
+ storea( v_.get()+index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense vector.
+// The index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void CustomVector<Type,AF,PF,TF>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
+
+ storeu( v_.get()+index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense vector. The index must be smaller than the number of vector elements and it must be
+// a multiple of the number of values inside the SIMD element. This function must \b NOT be
+// called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void CustomVector<Type,AF,PF,TF>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+index ), "Invalid vector access index" );
+
+ stream( v_.get()+index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] = (~rhs)[i ];
+ v_[i+1UL] = (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] = (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ if( AF && useStreaming && size_ > ( cacheSize/( sizeof(Type) * 3UL ) ) && !(~rhs).isAliased( this ) )
+ {
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ stream( i, (~rhs).load(i) );
+ }
+ for( ; i<size_; ++i ) {
+ v_[i] = (~rhs)[i];
+ }
+ }
+ else
+ {
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, it.load() );
+ }
+ for( ; i<size_; ++i, ++it ) {
+ v_[i] = *it;
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CustomVector<Type,AF,PF,TF>::assign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] += (~rhs)[i ];
+ v_[i+1UL] += (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] += (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , load(i ) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , load(i+SIMDSIZE ) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) + it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, load(i) + it.load() );
+ }
+ for( ; i<size_; ++i, ++it ) {
+ v_[i] += *it;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CustomVector<Type,AF,PF,TF>::addAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] -= (~rhs)[i ];
+ v_[i+1UL] -= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] -= (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , load(i ) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , load(i+SIMDSIZE ) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) - it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, load(i) - it.load() );
+ }
+ for( ; i<size_; ++i, ++it ) {
+ v_[i] -= *it;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CustomVector<Type,AF,PF,TF>::subAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] -= element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] *= (~rhs)[i ];
+ v_[i+1UL] *= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] *= (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , load(i ) * it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , load(i+SIMDSIZE ) * it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) * it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) * it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, load(i) * it.load() );
+ }
+ for( ; i<size_; ++i, ++it ) {
+ v_[i] *= *it;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CustomVector<Type,AF,PF,TF>::multAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const DynamicVector<Type,TF> tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = tmp[element->index()] * element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] /= (~rhs)[i ];
+ v_[i+1UL] /= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] /= (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,PF,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ CustomVector<Type,AF,PF,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , load(i ) / it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , load(i+SIMDSIZE ) / it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) / it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) / it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, load(i) / it.load() );
+ }
+ for( ; i<size_; ++i, ++it ) {
+ v_[i] /= *it;
+ }
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR PADDED VECTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of CustomVector for padded vectors.
+// \ingroup custom_vector
+//
+// This specialization of CustomVector adapts the class template to the requirements of padded
+// vectors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+class CustomVector<Type,AF,padded,TF>
+ : public DenseVector< CustomVector<Type,AF,padded,TF>, TF >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef CustomVector<Type,AF,padded,TF> This; //!< Type of this CustomVector instance.
+ typedef DynamicVector<Type,TF> ResultType; //!< Result type for expression template evaluations.
+ typedef DynamicVector<Type,!TF> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the vector elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the vector elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations
+ typedef const CustomVector& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant vector value.
+ typedef const Type& ConstReference; //!< Reference to a constant vector value.
+ typedef Type* Pointer; //!< Pointer to a non-constant vector value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant vector value.
+
+ typedef DenseIterator<Type,AF> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,AF> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a CustomVector with different data/element type.
+ */
+ template< typename ET > // Data type of the other vector
+ struct Rebind {
+ typedef CustomVector<ET,AF,padded,TF> Other; //!< The type of the other CustomVector.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
+ in can be optimized via SIMD operations. In case the element type of the vector is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline CustomVector();
+ explicit inline CustomVector( Type* ptr, size_t n, size_t nn );
+
+ template< typename Deleter >
+ explicit inline CustomVector( Type* ptr, size_t n, size_t nn, Deleter d );
+
+ inline CustomVector( const CustomVector& v );
+ inline CustomVector( CustomVector&& v ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) noexcept;
+ inline ConstReference operator[]( size_t index ) const noexcept;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin () noexcept;
+ inline ConstIterator begin () const noexcept;
+ inline ConstIterator cbegin() const noexcept;
+ inline Iterator end () noexcept;
+ inline ConstIterator end () const noexcept;
+ inline ConstIterator cend () const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline CustomVector& operator=( const Type& rhs );
+ inline CustomVector& operator=( initializer_list<Type> list );
+
+ template< typename Other, size_t N >
+ inline CustomVector& operator=( const Other (&array)[N] );
+
+ inline CustomVector& operator=( const CustomVector& rhs );
+ inline CustomVector& operator=( CustomVector&& rhs ) noexcept;
+
+ template< typename VT > inline CustomVector& operator= ( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CustomVector& operator+=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CustomVector& operator-=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CustomVector& operator*=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CustomVector& operator/=( const DenseVector<VT,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, CustomVector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, CustomVector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline void clear();
+ template< typename Other > inline CustomVector& scale( const Other& scalar );
+ inline void swap( CustomVector& v ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Resource management functions***************************************************************
+ /*!\name Resource management functions */
+ //@{
+ inline void reset( Type* ptr, size_t n, size_t nn );
+ template< typename Deleter > inline void reset( Type* ptr, size_t n, size_t nn, Deleter d );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDAdd< Type, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDSub< Type, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDMult< Type, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDDiv< Type, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t size_; //!< The size/dimension of the custom vector.
+ size_t capacity_; //!< The maximum capacity of the custom vector.
+ boost::shared_array<Type> v_; //!< The custom array of elements.
+ /*!< Access to the array of elements is gained via the
+ subscript operator. The order of the elements is
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right)\f] */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for CustomVector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,padded,TF>::CustomVector()
+ : size_ ( 0UL ) // The size/dimension of the vector
+ , capacity_( 0UL ) // The maximum capacity of the vector
+ , v_ ( ) // The custom array of elements
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a padded custom vector of size \a n and capacity \a nn.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param nn The maximum size of the given array.
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This constructor creates a padded custom vector of size \a n and capacity \a nn. The
+// construction of the vector fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified capacity \a nn is insufficient for the given data type \a Type and
+// the available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note The custom vector does NOT take responsibility for the given array of elements!
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,padded,TF>::CustomVector( Type* ptr, size_t n, size_t nn )
+ : size_ ( n ) // The size/dimension of the vector
+ , capacity_( nn ) // The maximum capacity of the vector
+ , v_ ( ) // The custom array of elements
+{
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && !checkAlignment( ptr ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ if( IsVectorizable<Type>::value && capacity_ < nextMultiple<size_t>( size_, SIMDSIZE ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded vector" );
+ }
+
+ v_.reset( ptr, NoDelete() );
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=size_; i<capacity_; ++i )
+ v_[i] = Type();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a padded custom vector of size \a n and capacity \a nn.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param nn The maximum size of the given array.
+// \param d The deleter to destroy the array of elements.
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This constructor creates a padded custom vector of size \a n and capacity \a nn. The
+// construction of the vector fails if ...
+//
+// - ... the passes pointer is \c nullptr;
+// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
+// aligned according to the available instruction set (SSE, AVX, ...);
+// - ... the specified capacity \a nn is insufficient for the given data type \a Type and
+// the available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Deleter > // Type of the custom deleter
+inline CustomVector<Type,AF,padded,TF>::CustomVector( Type* ptr, size_t n, size_t nn, Deleter d )
+ : size_ ( n ) // The custom array of elements
+ , capacity_( nn ) // The maximum capacity of the vector
+ , v_ ( ) // The custom array of elements
+{
+ if( ptr == nullptr ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
+ }
+
+ if( AF && !checkAlignment( ptr ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
+ }
+
+ if( IsVectorizable<Type>::value && capacity_ < nextMultiple<size_t>( size_, SIMDSIZE ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded vector" );
+ }
+
+ v_.reset( ptr, d );
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=size_; i<capacity_; ++i )
+ v_[i] = Type();
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for CustomVector.
+//
+// \param v Vector to be copied.
+//
+// The copy constructor initializes the custom vector as an exact copy of the given custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,padded,TF>::CustomVector( const CustomVector& v )
+ : size_ ( v.size_ ) // The size/dimension of the vector
+ , capacity_( v.capacity_ ) // The maximum capacity of the vector
+ , v_ ( v.v_ ) // The custom array of elements
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for CustomVector.
+//
+// \param v The vector to be moved into this instance.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,padded,TF>::CustomVector( CustomVector&& v ) noexcept
+ : size_ ( v.size_ ) // The size/dimension of the vector
+ , capacity_( v.capacity_ ) // The maximum capacity of the vector
+ , v_ ( std::move( v.v_ ) ) // The custom array of elements
+{
+ v.size_ = 0UL;
+ v.capacity_ = 0UL;
+
+ BLAZE_INTERNAL_ASSERT( v.data() == nullptr, "Invalid data reference detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::Reference
+ CustomVector<Type,AF,padded,TF>::operator[]( size_t index ) noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
+ return v_[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::ConstReference
+ CustomVector<Type,AF,padded,TF>::operator[]( size_t index ) const noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
+ return v_[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::Reference
+ CustomVector<Type,AF,padded,TF>::at( size_t index )
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::ConstReference
+ CustomVector<Type,AF,padded,TF>::at( size_t index ) const
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::Pointer
+ CustomVector<Type,AF,padded,TF>::data() noexcept
+{
+ return v_.get();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::ConstPointer
+ CustomVector<Type,AF,padded,TF>::data() const noexcept
+{
+ return v_.get();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the custom vector.
+//
+// \return Iterator to the first element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::Iterator
+ CustomVector<Type,AF,padded,TF>::begin() noexcept
+{
+ return Iterator( v_.get() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the custom vector.
+//
+// \return Iterator to the first element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::ConstIterator
+ CustomVector<Type,AF,padded,TF>::begin() const noexcept
+{
+ return ConstIterator( v_.get() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the custom vector.
+//
+// \return Iterator to the first element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::ConstIterator
+ CustomVector<Type,AF,padded,TF>::cbegin() const noexcept
+{
+ return ConstIterator( v_.get() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the custom vector.
+//
+// \return Iterator just past the last element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::Iterator
+ CustomVector<Type,AF,padded,TF>::end() noexcept
+{
+ return Iterator( v_.get() + size_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the custom vector.
+//
+// \return Iterator just past the last element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::ConstIterator
+ CustomVector<Type,AF,padded,TF>::end() const noexcept
+{
+ return ConstIterator( v_.get() + size_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the custom vector.
+//
+// \return Iterator just past the last element of the custom vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename CustomVector<Type,AF,padded,TF>::ConstIterator
+ CustomVector<Type,AF,padded,TF>::cend() const noexcept
+{
+ return ConstIterator( v_.get() + size_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all vector elements.
+//
+// \param rhs Scalar value to be assigned to all vector elements.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator=( const Type& rhs )
+{
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] = rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all vector elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to custom vector.
+//
+// This assignment operator offers the option to directly assign to all elements of the vector
+// by means of an initializer list:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::unaliged;
+ using blaze::padded;
+
+ const int array[4] = { 1, 2, 3, 4 };
+
+ CustomVector<double,unaligned,padded> v( array, 4UL, 8UL );
+ v = { 5, 6, 7 };
+ \endcode
+
+// The vector elements are assigned the values from the given initializer list. Missing values
+// are reset to their default state. Note that in case the size of the initializer list exceeds
+// the size of the vector, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator=( initializer_list<Type> list )
+{
+ if( list.size() > size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to custom vector" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), v_.get() ), v_.get()+capacity_, Type() );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all vector elements.
+//
+// \param array N-dimensional array for the assignment.
+// \return Reference to the assigned vector.
+// \exception std::invalid_argument Invalid array size.
+//
+// This assignment operator offers the option to directly set all elements of the vector. The
+// following example demonstrates this by means of an unaligned, padded custom vector:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::unaliged;
+ using blaze::padded;
+
+ const int array[8] = { 1, 2, 3, 4, 0, 0, 0, 0 };
+ const int init[4] = { 5, 6, 7 };
+
+ CustomVector<double,unaligned,padded> v( array, 4UL, 8UL );
+ v = init;
+ \endcode
+
+// The vector is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the fourth element in the example). Note that the size of the array
+// must match the size of the custom vector. Otherwise a \a std::invalid_argument exception is
+// thrown. Also note that after the assignment \a array will have the same entries as \a init.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other // Data type of the initialization array
+ , size_t N > // Dimension of the initialization array
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator=( const Other (&array)[N] )
+{
+ if( size_ != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" );
+ }
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = array[i];
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for CustomVector.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// The vector is initialized as a copy of the given vector. In case the current sizes of the two
+// vectors don't match, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator=( const CustomVector& rhs )
+{
+ if( rhs.size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ smpAssign( *this, ~rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for CustomVector.
+//
+// \param rhs The vector to be moved into this instance.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator=( CustomVector&& rhs ) noexcept
+{
+ size_ = rhs.size_;
+ capacity_ = rhs.capacity_;
+ v_ = std::move( rhs.v_ );
+
+ rhs.size_ = 0UL;
+ rhs.capacity_ = 0UL;
+
+ BLAZE_INTERNAL_ASSERT( rhs.data() == nullptr, "Invalid data reference detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// The vector is initialized as a copy of the given vector. In case the current sizes of the two
+// vectors don't match, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ smpAssign( *this, tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator+=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ smpAddAssign( *this, tmp );
+ }
+ else {
+ smpAddAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator-=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ smpSubAssign( *this, tmp );
+ }
+ else {
+ smpSubAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator*=( const Vector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( MultType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( IsSparseVector<VT>::value || (~rhs).canAlias( this ) ) {
+ const MultType tmp( *this * (~rhs) );
+ this->operator=( tmp );
+ }
+ else {
+ smpMultAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::operator/=( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( DivType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const DivType tmp( *this / (~rhs) );
+ this->operator=( tmp );
+ }
+ else {
+ smpDivAssign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a vector and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, CustomVector<Type,AF,padded,TF> >&
+ CustomVector<Type,AF,padded,TF>::operator*=( Other rhs )
+{
+ smpAssign( *this, (*this) * rhs );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a vector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, CustomVector<Type,AF,padded,TF> >&
+ CustomVector<Type,AF,padded,TF>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ smpAssign( *this, (*this) / rhs );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the size/dimension of the vector.
+//
+// \return The size of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline size_t CustomVector<Type,AF,padded,TF>::size() const noexcept
+{
+ return size_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the vector.
+//
+// \return The capacity of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline size_t CustomVector<Type,AF,padded,TF>::capacity() const noexcept
+{
+ return capacity_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the vector.
+//
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline size_t CustomVector<Type,AF,padded,TF>::nonZeros() const
+{
+ size_t nonzeros( 0 );
+
+ for( size_t i=0UL; i<size_; ++i ) {
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+ }
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,padded,TF>::reset()
+{
+ using blaze::clear;
+ for( size_t i=0UL; i<size_; ++i )
+ clear( v_[i] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the vector to its default state.
+//
+// \return void
+//
+// This function clears the vector to its default state. In case the vector has been passed the
+// responsibility to manage the given array, it disposes the resource via the specified deleter.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,padded,TF>::clear()
+{
+ size_ = 0UL;
+ capacity_ = 0UL;
+ v_.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the vector scaling.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline CustomVector<Type,AF,padded,TF>&
+ CustomVector<Type,AF,padded,TF>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two vectors.
+//
+// \param v The vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,padded,TF>::swap( CustomVector& v ) noexcept
+{
+ using std::swap;
+
+ swap( size_, v.size_ );
+ swap( capacity_, v.capacity_ );
+ swap( v_, v.v_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RESOURCE MANAGEMENT FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resets the custom vector and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param nn The maximum size of the given array.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This function resets the custom vector to the given array of elements of size \a n and capacity
+// \a nn. The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the specified capacity \a nn is insufficient for the given data type \a Type and
+// the available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom vector referencing the array goes out of scope.
+// \note The custom vector does NOT take responsibility for the new array of elements!
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void CustomVector<Type,AF,padded,TF>::reset( Type* ptr, size_t n, size_t nn )
+{
+ CustomVector tmp( ptr, n, nn );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resets the custom vector and replaces the array of elements with the given array.
+//
+// \param ptr The array of elements to be used by the vector.
+// \param n The number of array elements to be used by the custom vector.
+// \param nn The maximum size of the given array.
+// \param d The deleter to destroy the array of elements.
+// \return void
+// \exception std::invalid_argument Invalid setup of custom vector.
+//
+// This function resets the custom vector to the given array of elements of size \a n and capacity
+// \a nn. The function fails if ...
+//
+// - ... the passed pointer is \c nullptr;
+// - ... the specified capacity \a nn is insufficient for the given data type \a Type and
+// the available instruction set.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// \note In case a deleter was specified, the previously referenced array will only be destroyed
+// when the last custom vector referencing the array goes out of scope.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Deleter > // Type of the custom deleter
+inline void CustomVector<Type,AF,padded,TF>::reset( Type* ptr, size_t n, size_t nn, Deleter d )
+{
+ CustomVector tmp( ptr, n, nn, d );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the vector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address can alias with the vector. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool CustomVector<Type,AF,padded,TF>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the vector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address is aliased with the vector. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool CustomVector<Type,AF,padded,TF>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the vector is properly aligned in memory.
+//
+// \return \a true in case the vector is aligned, \a false if not.
+//
+// This function returns whether the vector is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of the vector are guaranteed to conform to the alignment
+// restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline bool CustomVector<Type,AF,padded,TF>::isAligned() const noexcept
+{
+ return ( AF || checkAlignment( v_.get() ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the vector can be used in SMP assignments.
+//
+// \return \a true in case the vector can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the vector can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current size of the
+// vector).
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline bool CustomVector<Type,AF,padded,TF>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,padded,TF>::SIMDType
+ CustomVector<Type,AF,padded,TF>::load( size_t index ) const noexcept
+{
+ if( AF )
+ return loada( index );
+ else
+ return loadu( index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,padded,TF>::SIMDType
+ CustomVector<Type,AF,padded,TF>::loada( size_t index ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+index ), "Invalid vector access index" );
+
+ return loada( v_.get()+index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,padded,TF>::SIMDType
+ CustomVector<Type,AF,padded,TF>::loadu( size_t index ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+
+ return loadu( v_.get()+index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ CustomVector<Type,AF,padded,TF>::store( size_t index, const SIMDType& value ) noexcept
+{
+ if( AF )
+ storea( index, value );
+ else
+ storeu( index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ CustomVector<Type,AF,padded,TF>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+index ), "Invalid vector access index" );
+
+ storea( v_.get()+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense vector.
+// The index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ CustomVector<Type,AF,padded,TF>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+
+ storeu( v_.get()+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense vector. The index must be smaller than the number of vector elements and it must be
+// a multiple of the number of values inside the SIMD element. This function must \b NOT be
+// called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ CustomVector<Type,AF,padded,TF>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_.get()+index ), "Invalid vector access index" );
+
+ stream( v_.get()+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] = (~rhs)[i ];
+ v_[i+1UL] = (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] = (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ if( AF && useStreaming && size_ > ( cacheSize/( sizeof(Type) * 3UL ) ) && !(~rhs).isAliased( this ) )
+ {
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ stream( i, (~rhs).load(i) );
+ }
+ for( ; remainder && i<size_; ++i ) {
+ v_[i] = (~rhs)[i];
+ }
+ }
+ else
+ {
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, it.load() );
+ }
+ for( ; remainder && i<size_; ++i, ++it ) {
+ v_[i] = *it;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CustomVector<Type,AF,padded,TF>::assign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] += (~rhs)[i ];
+ v_[i+1UL] += (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] += (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , load(i ) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , load(i+SIMDSIZE ) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) + it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) + it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, load(i) + it.load() );
+ }
+ for( ; remainder && i<size_; ++i, ++it ) {
+ v_[i] += *it;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CustomVector<Type,AF,padded,TF>::addAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] -= (~rhs)[i ];
+ v_[i+1UL] -= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] -= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , load(i ) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , load(i+SIMDSIZE ) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) - it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) - it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, load(i) - it.load() );
+ }
+ for( ; remainder && i<size_; ++i, ++it ) {
+ v_[i] -= *it;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CustomVector<Type,AF,padded,TF>::subAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] *= (~rhs)[i ];
+ v_[i+1UL] *= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] *= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , load(i ) * it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , load(i+SIMDSIZE ) * it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) * it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) * it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, load(i) * it.load() );
+ }
+ for( ; remainder && i<size_; ++i, ++it ) {
+ v_[i] *= *it;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CustomVector<Type,AF,padded,TF>::multAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const DynamicVector<Type,TF> tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] /= (~rhs)[i ];
+ v_[i+1UL] /= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] /= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename CustomVector<Type,AF,padded,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ CustomVector<Type,AF,padded,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const size_t i4way( size_ & size_t(-SIMDSIZE*4) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE*4UL) ) ) == i4way, "Invalid end calculation" );
+ BLAZE_INTERNAL_ASSERT( i4way <= ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ ConstIterator_<VT> it( (~rhs).begin() );
+
+ for( ; i<i4way; i+=SIMDSIZE*4UL ) {
+ store( i , load(i ) / it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE , load(i+SIMDSIZE ) / it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) / it.load() ); it += SIMDSIZE;
+ store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) / it.load() ); it += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
+ store( i, load(i) / it.load() );
+ }
+ for( ; i<size_; ++i, ++it ) {
+ v_[i] /= *it;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CUSTOMVECTOR OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name CustomVector operators */
+//@{
+template< typename Type, bool AF, bool PF, bool TF >
+inline void reset( CustomVector<Type,AF,PF,TF>& v );
+
+template< typename Type, bool AF, bool PF, bool TF >
+inline void clear( CustomVector<Type,AF,PF,TF>& v );
+
+template< typename Type, bool AF, bool PF, bool TF >
+inline bool isDefault( const CustomVector<Type,AF,PF,TF>& v );
+
+template< typename Type, bool AF, bool PF, bool TF >
+inline bool isIntact( const CustomVector<Type,AF,PF,TF>& v ) noexcept;
+
+template< typename Type, bool AF, bool PF, bool TF >
+inline void swap( CustomVector<Type,AF,PF,TF>& a, CustomVector<Type,AF,PF,TF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given custom vector.
+// \ingroup custom_vector
+//
+// \param v The custom vector to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void reset( CustomVector<Type,AF,PF,TF>& v )
+{
+ v.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given custom vector.
+// \ingroup custom_vector
+//
+// \param v The custom vector to be cleared.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void clear( CustomVector<Type,AF,PF,TF>& v )
+{
+ v.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given custom vector is in default state.
+// \ingroup custom_vector
+//
+// \param v The custom vector to be tested for its default state.
+// \return \a true in case the given vector is component-wise zero, \a false otherwise.
+//
+// This function checks whether the custom vector is in default state. For instance, in case
+// the static vector is instantiated for a built-in integral or floating point data type, the
+// function returns \a true in case all vector elements are 0 and \a false in case any vector
+// element is not 0. Following example demonstrates the use of the \a isDefault function:
+
+ \code
+ using blaze::aligned;
+ using blaze::padded;
+
+ blaze::CustomVector<int,aligned,padded> a( ... );
+ // ... Resizing and initialization
+ if( isDefault( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline bool isDefault( const CustomVector<Type,AF,PF,TF>& v )
+{
+ return ( v.size() == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given custom vector are intact.
+// \ingroup custom_vector
+//
+// \param v The custom vector to be tested.
+// \return \a true in case the given vector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the custom vector are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ using blaze::aligned;
+ using blaze::padded;
+
+ blaze::CustomVector<int,aligned,padded> a( ... );
+ // ... Resizing and initialization
+ if( isIntact( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline bool isIntact( const CustomVector<Type,AF,PF,TF>& v ) noexcept
+{
+ return ( v.size() <= v.capacity() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two vectors.
+// \ingroup custom_vector
+//
+// \param a The first vector to be swapped.
+// \param b The second vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool AF // Alignment flag
+ , bool PF // Padding flag
+ , bool TF > // Transpose flag
+inline void swap( CustomVector<Type,AF,PF,TF>& a, CustomVector<Type,AF,PF,TF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool AF, bool PF, bool TF >
+struct HasConstDataAccess< CustomVector<T,AF,PF,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool AF, bool PF, bool TF >
+struct HasMutableDataAccess< CustomVector<T,AF,PF,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISCUSTOM SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool AF, bool PF, bool TF >
+struct IsCustom< CustomVector<T,AF,PF,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool PF, bool TF >
+struct IsAligned< CustomVector<T,aligned,PF,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool AF, bool TF >
+struct IsPadded< CustomVector<T,AF,padded,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct AddTrait< CustomVector<T1,AF,PF,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct AddTrait< StaticVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct AddTrait< CustomVector<T1,AF,PF,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct AddTrait< HybridVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = HybridVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct AddTrait< CustomVector<T1,AF,PF,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< AddTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct AddTrait< DynamicVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = DynamicVector< AddTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 >
+struct AddTrait< CustomVector<T1,AF1,PF1,TF>, CustomVector<T2,AF2,PF2,TF> >
+{
+ using Type = DynamicVector< AddTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct SubTrait< CustomVector<T1,AF,PF,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct SubTrait< StaticVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct SubTrait< CustomVector<T1,AF,PF,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct SubTrait< HybridVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = HybridVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct SubTrait< CustomVector<T1,AF,PF,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< SubTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct SubTrait< DynamicVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = DynamicVector< SubTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 >
+struct SubTrait< CustomVector<T1,AF1,PF1,TF>, CustomVector<T2,AF2,PF2,TF> >
+{
+ using Type = DynamicVector< SubTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct MultTrait< CustomVector<T1,AF,PF,TF>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2, bool AF, bool PF, bool TF >
+struct MultTrait< T1, CustomVector<T2,AF,PF,TF>, EnableIf_<IsNumeric<T1> > >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct MultTrait< CustomVector<T1,AF,PF,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2, size_t N >
+struct MultTrait< CustomVector<T1,AF,PF,false>, StaticVector<T2,N,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2, size_t N >
+struct MultTrait< CustomVector<T1,AF,PF,true>, StaticVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct MultTrait< StaticVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, typename T2, bool AF, bool PF >
+struct MultTrait< StaticVector<T1,N,false>, CustomVector<T2,AF,PF,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2, bool AF, bool PF >
+struct MultTrait< StaticVector<T1,N,true>, CustomVector<T2,AF,PF,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct MultTrait< CustomVector<T1,AF,PF,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2, size_t N >
+struct MultTrait< CustomVector<T1,AF,PF,false>, HybridVector<T2,N,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2, size_t N >
+struct MultTrait< CustomVector<T1,AF,PF,true>, HybridVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct MultTrait< HybridVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, typename T2, bool AF, bool PF >
+struct MultTrait< HybridVector<T1,N,false>, CustomVector<T2,AF,PF,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2, bool AF, bool PF >
+struct MultTrait< HybridVector<T1,N,true>, CustomVector<T2,AF,PF,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct MultTrait< CustomVector<T1,AF,PF,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2 >
+struct MultTrait< CustomVector<T1,AF,PF,false>, DynamicVector<T2,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2 >
+struct MultTrait< CustomVector<T1,AF,PF,true>, DynamicVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct MultTrait< DynamicVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2, bool AF, bool PF >
+struct MultTrait< DynamicVector<T1,false>, CustomVector<T2,AF,PF,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, bool AF, bool PF >
+struct MultTrait< DynamicVector<T1,true>, CustomVector<T2,AF,PF,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 >
+struct MultTrait< CustomVector<T1,AF1,PF1,TF>, CustomVector<T2,AF2,PF2,TF> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF1, bool PF1, typename T2, bool AF2, bool PF2 >
+struct MultTrait< CustomVector<T1,AF1,PF1,false>, CustomVector<T2,AF2,PF2,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF1, bool PF1, typename T2, bool AF2, bool PF2 >
+struct MultTrait< CustomVector<T1,AF1,PF1,true>, CustomVector<T2,AF2,PF2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CROSSTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct CrossTrait< CustomVector<T1,AF,PF,TF>, StaticVector<T2,3UL,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct CrossTrait< StaticVector<T1,3UL,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct CrossTrait< CustomVector<T1,AF,PF,TF>, HybridVector<T2,N,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct CrossTrait< HybridVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct CrossTrait< CustomVector<T1,AF,PF,TF>, DynamicVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct CrossTrait< DynamicVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 >
+struct CrossTrait< CustomVector<T1,AF1,PF1,TF>, CustomVector<T2,AF2,PF2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct DivTrait< CustomVector<T1,AF,PF,TF>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = DynamicVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct DivTrait< CustomVector<T1,AF,PF,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct DivTrait< StaticVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = StaticVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N >
+struct DivTrait< CustomVector<T1,AF,PF,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF >
+struct DivTrait< HybridVector<T1,N,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = HybridVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct DivTrait< CustomVector<T1,AF,PF,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct DivTrait< DynamicVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = DynamicVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 >
+struct DivTrait< CustomVector<T1,AF1,PF1,TF>, CustomVector<T2,AF2,PF2,TF> >
+{
+ using Type = DynamicVector< DivTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool AF, bool PF, bool TF >
+struct SubvectorTrait< CustomVector<T1,AF,PF,TF> >
+{
+ using Type = DynamicVector<T1,TF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/DenseIterator.h b/src/cpu/blaze/math/dense/DenseIterator.h
new file mode 100644
index 00000000..5fcc1863
--- /dev/null
+++ b/src/cpu/blaze/math/dense/DenseIterator.h
@@ -0,0 +1,755 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/DenseIterator.h
+// \brief Header file for the DenseIterator class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+//
+// * The names of its contributors may not be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_DENSEITERATOR_H_
+#define _BLAZE_MATH_DENSE_DENSEITERATOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/SIMD.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of a generic iterator for dense vectors and matrices.
+// \ingroup math
+//
+// The DenseIterator represents a generic random-access iterator that can be used for dense
+// vectors and specific rows/columns of dense matrices.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+class DenseIterator
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Type ValueType; //!< Type of the underlying elements.
+ typedef Type* PointerType; //!< Pointer return type.
+ typedef Type& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! SIMD type of the elements.
+ typedef SIMDTrait_<Type> SIMDType;
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline DenseIterator() noexcept;
+ explicit inline DenseIterator( Type* ptr ) noexcept;
+
+ template< typename Other, bool AF2 >
+ inline DenseIterator( const DenseIterator<Other,AF2>& it ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ // No explicitly declared copy assignment operator.
+ inline DenseIterator& operator+=( ptrdiff_t inc ) noexcept;
+ inline DenseIterator& operator-=( ptrdiff_t inc ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Increment/decrement operators***************************************************************
+ /*!\name Increment/decrement operators */
+ //@{
+ inline DenseIterator& operator++() noexcept;
+ inline const DenseIterator operator++( int ) noexcept;
+ inline DenseIterator& operator--() noexcept;
+ inline const DenseIterator operator--( int ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline ReferenceType operator[]( size_t index ) const noexcept;
+ inline ReferenceType operator* () const noexcept;
+ inline PointerType operator->() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline PointerType base() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ inline const SIMDType load () const noexcept;
+ inline const SIMDType loada () const noexcept;
+ inline const SIMDType loadu () const noexcept;
+ inline void store ( const SIMDType& value ) const noexcept;
+ inline void storea( const SIMDType& value ) const noexcept;
+ inline void storeu( const SIMDType& value ) const noexcept;
+ inline void stream( const SIMDType& value ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ PointerType ptr_; //!< Pointer to the current element.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default constructor for the DenseIterator class.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline DenseIterator<Type,AF>::DenseIterator() noexcept
+ : ptr_( nullptr ) // Pointer to the current element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for the DenseIterator class.
+//
+// \param ptr Pointer to the initial element.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline DenseIterator<Type,AF>::DenseIterator( Type* ptr ) noexcept
+ : ptr_( ptr ) // Pointer to the current element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different DenseIterator instances.
+//
+// \param it The foreign DenseIterator instance to be copied.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+template< typename Other // Type of the foreign elements
+ , bool AF2 > // Alignment flag of the foreign iterator
+inline DenseIterator<Type,AF>::DenseIterator( const DenseIterator<Other,AF2>& it ) noexcept
+ : ptr_( it.base() ) // Pointer to the current element
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator.
+//
+// \param inc The increment of the iterator.
+// \return Reference to the incremented iterator.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline DenseIterator<Type,AF>& DenseIterator<Type,AF>::operator+=( ptrdiff_t inc ) noexcept
+{
+ ptr_ += inc;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator.
+//
+// \param dec The decrement of the iterator.
+// \return Reference to the decremented iterator.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline DenseIterator<Type,AF>& DenseIterator<Type,AF>::operator-=( ptrdiff_t dec ) noexcept
+{
+ ptr_ -= dec;
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// INCREMENT/DECREMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Pre-increment operator.
+//
+// \return Reference to the incremented iterator.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline DenseIterator<Type,AF>& DenseIterator<Type,AF>::operator++() noexcept
+{
+ ++ptr_;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Post-increment operator.
+//
+// \return The previous position of the iterator.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline const DenseIterator<Type,AF> DenseIterator<Type,AF>::operator++( int ) noexcept
+{
+ return DenseIterator( ptr_++ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Pre-decrement operator.
+//
+// \return Reference to the decremented iterator.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline DenseIterator<Type,AF>& DenseIterator<Type,AF>::operator--() noexcept
+{
+ --ptr_;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Post-decrement operator.
+//
+// \return The previous position of the iterator.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline const DenseIterator<Type,AF> DenseIterator<Type,AF>::operator--( int ) noexcept
+{
+ return DenseIterator( ptr_-- );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the underlying elements.
+//
+// \param index Access index.
+// \return Reference to the accessed value.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline typename DenseIterator<Type,AF>::ReferenceType
+ DenseIterator<Type,AF>::operator[]( size_t index ) const noexcept
+{
+ return ptr_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the element at the current iterator position.
+//
+// \return Reference to the current element.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline typename DenseIterator<Type,AF>::ReferenceType
+ DenseIterator<Type,AF>::operator*() const noexcept
+{
+ return *ptr_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the element at the current iterator position.
+//
+// \return Pointer to the element at the current iterator position.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline typename DenseIterator<Type,AF>::PointerType
+ DenseIterator<Type,AF>::operator->() const noexcept
+{
+ return ptr_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Low-level access to the underlying member of the iterator.
+//
+// \return Pointer to the current memory location.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline typename DenseIterator<Type,AF>::PointerType DenseIterator<Type,AF>::base() const noexcept
+{
+ return ptr_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Load of the SIMD element at the current iterator position.
+//
+// \return The loaded SIMD element.
+//
+// This function performs a load of the SIMD element of the current element. This function must
+// \b NOT be called explicitly! It is used internally for the performance optimized evaluation
+// of expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline const typename DenseIterator<Type,AF>::SIMDType
+ DenseIterator<Type,AF>::load() const noexcept
+{
+ if( AF )
+ return loada();
+ else
+ return loadu();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of the SIMD element at the current iterator position.
+//
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of the SIMD element of the current element. This
+// function must \b NOT be called explicitly! It is used internally for the performance optimized
+// evaluation of expression templates. Calling this function explicitly might result in erroneous
+// results and/or in compilation errors.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline const typename DenseIterator<Type,AF>::SIMDType
+ DenseIterator<Type,AF>::loada() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( ptr_ ), "Invalid alignment detected" );
+
+ return blaze::loada( ptr_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of the SIMD element at the current iterator position.
+//
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of the SIMD element of the current element. This
+// function must \b NOT be called explicitly! It is used internally for the performance optimized
+// evaluation of expression templates. Calling this function explicitly might result in erroneous
+// results and/or in compilation errors.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline const typename DenseIterator<Type,AF>::SIMDType
+ DenseIterator<Type,AF>::loadu() const noexcept
+{
+ return blaze::loadu( ptr_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of the SIMD element at the current iterator position.
+//
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of the SIMD element of the current element. This function must
+// \b NOT be called explicitly! It is used internally for the performance optimized evaluation
+// of expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline void DenseIterator<Type,AF>::store( const SIMDType& value ) const noexcept
+{
+ if( AF )
+ storea( value );
+ else
+ storeu( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of the SIMD element at the current iterator position.
+//
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of the SIMD element of the current element. This
+// function must \b NOT be called explicitly! It is used internally for the performance optimized
+// evaluation of expression templates. Calling this function explicitly might result in erroneous
+// results and/or in compilation errors.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline void DenseIterator<Type,AF>::storea( const SIMDType& value ) const noexcept
+{
+ blaze::storea( ptr_, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of the SIMD element at the current iterator position.
+//
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of the SIMD element of the current element. This
+// function must \b NOT be called explicitly! It is used internally for the performance optimized
+// evaluation of expression templates. Calling this function explicitly might result in erroneous
+// results and/or in compilation errors.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline void DenseIterator<Type,AF>::storeu( const SIMDType& value ) const noexcept
+{
+ blaze::storeu( ptr_, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of the SIMD element at the current iterator position.
+//
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of the SIMD element of the current
+// element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Type of the elements
+ , bool AF > // Alignment flag
+inline void DenseIterator<Type,AF>::stream( const SIMDType& value ) const noexcept
+{
+ blaze::stream( ptr_, value );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DenseIterator operators */
+//@{
+template< typename T1, bool AF1, typename T2, bool AF2 >
+inline bool operator==( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept;
+
+template< typename T1, bool AF1, typename T2, bool AF2 >
+inline bool operator!=( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept;
+
+template< typename T1, bool AF1, typename T2, bool AF2 >
+inline bool operator<( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept;
+
+template< typename T1, bool AF1, typename T2, bool AF2 >
+inline bool operator>( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept;
+
+template< typename T1, bool AF1, typename T2, bool AF2 >
+inline bool operator<=( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept;
+
+template< typename T1, bool AF1, typename T2, bool AF2 >
+inline bool operator>=( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept;
+
+template< typename Type, bool AF >
+inline const DenseIterator<Type,AF> operator+( const DenseIterator<Type,AF>& it, ptrdiff_t inc ) noexcept;
+
+template< typename Type, bool AF >
+inline const DenseIterator<Type,AF> operator+( ptrdiff_t inc, const DenseIterator<Type,AF>& it ) noexcept;
+
+template< typename Type, bool AF >
+inline const DenseIterator<Type,AF> operator-( const DenseIterator<Type,AF>& it, ptrdiff_t inc ) noexcept;
+
+template< typename Type, bool AF >
+inline ptrdiff_t operator-( const DenseIterator<Type,AF>& lhs, const DenseIterator<Type,AF>& rhs ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two DenseIterator objects.
+//
+// \param lhs The left-hand side iterator.
+// \param rhs The right-hand side iterator.
+// \return \a true if the iterators refer to the same element, \a false if not.
+*/
+template< typename T1 // Element type of the left-hand side iterator
+ , bool AF1 // Alignment flag of the left-hand side iterator
+ , typename T2 // Element type of the right-hand side iterator
+ , bool AF2 > // Alignment flag of the right-hand side iterator
+inline bool operator==( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept
+{
+ return lhs.base() == rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two DenseIterator objects.
+//
+// \param lhs The left-hand side iterator.
+// \param rhs The right-hand side iterator.
+// \return \a true if the iterators don't refer to the same element, \a false if they do.
+*/
+template< typename T1 // Element type of the left-hand side iterator
+ , bool AF1 // Alignment flag of the left-hand side iterator
+ , typename T2 // Element type of the right-hand side iterator
+ , bool AF2 > // Alignment flag of the right-hand side iterator
+inline bool operator!=( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept
+{
+ return lhs.base() != rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between two DenseIterator objects.
+//
+// \param lhs The left-hand side iterator.
+// \param rhs The right-hand side iterator.
+// \return \a true if the left-hand side iterator is smaller, \a false if not.
+*/
+template< typename T1 // Element type of the left-hand side iterator
+ , bool AF1 // Alignment flag of the left-hand side iterator
+ , typename T2 // Element type of the right-hand side iterator
+ , bool AF2 > // Alignment flag of the right-hand side iterator
+inline bool operator<( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept
+{
+ return lhs.base() < rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between two DenseIterator objects.
+//
+// \param lhs The left-hand side iterator.
+// \param rhs The right-hand side iterator.
+// \return \a true if the left-hand side iterator is greater, \a false if not.
+*/
+template< typename T1 // Element type of the left-hand side iterator
+ , bool AF1 // Alignment flag of the left-hand side iterator
+ , typename T2 // Element type of the right-hand side iterator
+ , bool AF2 > // Alignment flag of the right-hand side iterator
+inline bool operator>( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept
+{
+ return lhs.base() > rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between two DenseIterator objects.
+//
+// \param lhs The left-hand side iterator.
+// \param rhs The right-hand side iterator.
+// \return \a true if the left-hand side iterator is less or equal, \a false if not.
+*/
+template< typename T1 // Element type of the left-hand side iterator
+ , bool AF1 // Alignment flag of the left-hand side iterator
+ , typename T2 // Element type of the right-hand side iterator
+ , bool AF2 > // Alignment flag of the right-hand side iterator
+inline bool operator<=( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept
+{
+ return lhs.base() <= rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between two DenseIterator objects.
+//
+// \param lhs The left-hand side iterator.
+// \param rhs The right-hand side iterator.
+// \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+*/
+template< typename T1 // Element type of the left-hand side iterator
+ , bool AF1 // Alignment flag of the left-hand side iterator
+ , typename T2 // Element type of the right-hand side iterator
+ , bool AF2 > // Alignment flag of the right-hand side iterator
+inline bool operator>=( const DenseIterator<T1,AF1>& lhs, const DenseIterator<T2,AF2>& rhs ) noexcept
+{
+ return lhs.base() >= rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition between a DenseIterator and an integral value.
+//
+// \param it The iterator to be incremented.
+// \param inc The number of elements the iterator is incremented.
+// \return The incremented iterator.
+*/
+template< typename Type // Element type of the iterator
+ , bool AF > // Alignment flag of the iterator
+inline const DenseIterator<Type,AF> operator+( const DenseIterator<Type,AF>& it, ptrdiff_t inc ) noexcept
+{
+ return DenseIterator<Type,AF>( it.base() + inc );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition between an integral value and a DenseIterator.
+//
+// \param inc The number of elements the iterator is incremented.
+// \param it The iterator to be incremented.
+// \return The incremented iterator.
+*/
+template< typename Type // Element type of the iterator
+ , bool AF > // Alignment flag of the iterator
+inline const DenseIterator<Type,AF> operator+( ptrdiff_t inc, const DenseIterator<Type,AF>& it ) noexcept
+{
+ return DenseIterator<Type,AF>( it.base() + inc );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction between a DenseIterator and an integral value.
+//
+// \param it The iterator to be decremented.
+// \param dec The number of elements the iterator is decremented.
+// \return The decremented iterator.
+*/
+template< typename Type // Element type of the iterator
+ , bool AF > // Alignment flag of the iterator
+inline const DenseIterator<Type,AF> operator-( const DenseIterator<Type,AF>& it, ptrdiff_t dec ) noexcept
+{
+ return DenseIterator<Type,AF>( it.base() - dec );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Calculating the number of elements between two DenseIterator objects.
+//
+// \param lhs The left-hand side iterator.
+// \param rhs The right-hand side iterator.
+// \return The number of elements between the two iterators.
+*/
+template< typename Type // Element type of the iterator
+ , bool AF > // Alignment flag of the iterator
+inline ptrdiff_t operator-( const DenseIterator<Type,AF>& lhs, const DenseIterator<Type,AF>& rhs ) noexcept
+{
+ return lhs.base() - rhs.base();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/DenseMatrix.h b/src/cpu/blaze/math/dense/DenseMatrix.h
new file mode 100644
index 00000000..fd9ec24d
--- /dev/null
+++ b/src/cpu/blaze/math/dense/DenseMatrix.h
@@ -0,0 +1,1750 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/DenseMatrix.h
+// \brief Header file for utility functions for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_DENSEMATRIX_H_
+#define _BLAZE_MATH_DENSE_DENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Triangular.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Equal.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/StorageOrder.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsIdentity.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DenseMatrix operators */
+//@{
+template< typename T1, typename T2 >
+inline bool operator==( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,false>& rhs );
+
+template< typename T1, typename T2 >
+inline bool operator==( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,true>& rhs );
+
+template< typename T1, typename T2, bool SO >
+inline bool operator==( const DenseMatrix<T1,SO>& lhs, const DenseMatrix<T2,!SO>& rhs );
+
+template< typename T1, typename T2, bool SO >
+inline bool operator==( const DenseMatrix<T1,SO>& lhs, const SparseMatrix<T2,false>& rhs );
+
+template< typename T1, typename T2, bool SO >
+inline bool operator==( const DenseMatrix<T1,SO>& lhs, const SparseMatrix<T2,true>& rhs );
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+inline bool operator==( const SparseMatrix<T1,SO1>& lhs, const DenseMatrix<T2,SO2>& rhs );
+
+template< typename T1, typename T2 >
+inline EnableIf_<IsNumeric<T2>, bool > operator==( const DenseMatrix<T1,false>& mat, T2 scalar );
+
+template< typename T1, typename T2 >
+inline EnableIf_<IsNumeric<T2>, bool > operator==( const DenseMatrix<T1,true>& mat, T2 scalar );
+
+template< typename T1, typename T2, bool SO >
+inline EnableIf_<IsNumeric<T2>, bool > operator==( T1 scalar, const DenseMatrix<T2,SO>& mat );
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+inline bool operator!=( const DenseMatrix<T1,SO1>& lhs, const DenseMatrix<T2,SO2>& rhs );
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+inline bool operator!=( const DenseMatrix<T1,SO1>& lhs, const SparseMatrix<T2,SO2>& rhs );
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+inline bool operator!=( const SparseMatrix<T1,SO1>& lhs, const DenseMatrix<T2,SO2>& rhs );
+
+template< typename T1, typename T2, bool SO >
+inline EnableIf_<IsNumeric<T2>, bool > operator!=( const DenseMatrix<T1,SO>& mat, T2 scalar );
+
+template< typename T1, typename T2, bool SO >
+inline EnableIf_<IsNumeric<T2>, bool > operator!=( T1 scalar, const DenseMatrix<T2,SO>& mat );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of two rwo-major dense matrices.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side matrix for the comparison.
+// \param rhs The right-hand side matrix for the comparison.
+// \return \a true if the two matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline bool operator==( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+
+ // Early exit in case the matrix sizes don't match
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
+ return false;
+
+ // Evaluation of the two dense matrix operands
+ CT1 A( ~lhs );
+ CT2 B( ~rhs );
+
+ // In order to compare the two matrices, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ for( size_t i=0; i<A.rows(); ++i ) {
+ for( size_t j=0; j<A.columns(); ++j ) {
+ if( !equal( A(i,j), B(i,j) ) ) return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of two column-major dense matrices.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side matrix for the comparison.
+// \param rhs The right-hand side matrix for the comparison.
+// \return \a true if the two matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline bool operator==( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+
+ // Early exit in case the matrix sizes don't match
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
+ return false;
+
+ // Evaluation of the two dense matrix operands
+ CT1 A( ~lhs );
+ CT2 B( ~rhs );
+
+ // In order to compare the two matrices, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ for( size_t j=0; j<A.columns(); ++j ) {
+ for( size_t i=0; i<A.rows(); ++i ) {
+ if( !equal( A(i,j), B(i,j) ) ) return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of two dense matrices with different storage order.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side matrix for the comparison.
+// \param rhs The right-hand side matrix for the comparison.
+// \return \a true if the two matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+inline bool operator==( const DenseMatrix<T1,SO>& lhs, const DenseMatrix<T2,!SO>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+
+ // Early exit in case the matrix sizes don't match
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
+ return false;
+
+ // Evaluation of the two dense matrix operands
+ CT1 A( ~lhs );
+ CT2 B( ~rhs );
+
+ // In order to compare the two matrices, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ const size_t rows ( A.rows() );
+ const size_t columns( A.columns() );
+ const size_t block ( 16 );
+
+ for( size_t ii=0; ii<rows; ii+=block ) {
+ const size_t iend( ( rows < ii+block )?( rows ):( ii+block ) );
+ for( size_t jj=0; jj<columns; jj+=block ) {
+ const size_t jend( ( columns < jj+block )?( columns ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ if( !equal( A(i,j), B(i,j) ) ) return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a dense matrix and a row-major sparse matrix.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the comparison.
+// \param rhs The right-hand side row-major sparse matrix for the comparison.
+// \return \a true if the two matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the left-hand side dense matrix
+inline bool operator==( const DenseMatrix<T1,SO>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+ typedef ConstIterator_< RemoveReference_<CT2> > ConstIterator;
+
+ // Early exit in case the matrix sizes don't match
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
+ return false;
+
+ // Evaluation of the dense matrix and sparse matrix operand
+ CT1 A( ~lhs );
+ CT2 B( ~rhs );
+
+ // In order to compare the two matrices, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ size_t j( 0 );
+
+ for( size_t i=0; i<B.rows(); ++i ) {
+ j = 0;
+ for( ConstIterator element=B.begin(i); element!=B.end(i); ++element, ++j ) {
+ for( ; j<element->index(); ++j ) {
+ if( !isDefault( A(i,j) ) ) return false;
+ }
+ if( !equal( element->value(), A(i,j) ) ) return false;
+ }
+ for( ; j<A.columns(); ++j ) {
+ if( !isDefault( A(i,j) ) ) return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a dense matrix and a column-major sparse matrix.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the comparison.
+// \param rhs The right-hand side column-major sparse matrix for the comparison.
+// \return \a true if the two matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the left-hand side dense matrix
+inline bool operator==( const DenseMatrix<T1,SO>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+ typedef ConstIterator_< RemoveReference_<CT2> > ConstIterator;
+
+ // Early exit in case the matrix sizes don't match
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
+ return false;
+
+ // Evaluation of the dense matrix and sparse matrix operand
+ CT1 A( ~lhs );
+ CT2 B( ~rhs );
+
+ // In order to compare the two matrices, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ size_t i( 0 );
+
+ for( size_t j=0; j<B.columns(); ++j ) {
+ i = 0;
+ for( ConstIterator element=B.begin(j); element!=B.end(j); ++element, ++i ) {
+ for( ; i<element->index(); ++i ) {
+ if( !isDefault( A(i,j) ) ) return false;
+ }
+ if( !equal( element->value(), A(i,j) ) ) return false;
+ }
+ for( ; i<A.rows(); ++i ) {
+ if( !isDefault( A(i,j) ) ) return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a sparse matrix and a dense matrix.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the comparison.
+// \param rhs The right-hand side dense matrix for the comparison.
+// \return \a true if the two matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , bool SO1 // Storage order of the left-hand side sparse matrix
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side sparse matrix
+inline bool operator==( const SparseMatrix<T1,SO1>& lhs, const DenseMatrix<T2,SO2>& rhs )
+{
+ return ( rhs == lhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a row-major dense matrix and a scalar value.
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side row-major dense matrix for the comparison.
+// \param scalar The right-hand side scalar value for the comparison.
+// \return \a true if all elements of the matrix are equal to the scalar, \a false if not.
+//
+// If all values of the matrix are equal to the scalar value, the equality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side scalar
+inline EnableIf_<IsNumeric<T2>, bool > operator==( const DenseMatrix<T1,false>& mat, T2 scalar )
+{
+ typedef CompositeType_<T1> CT1;
+
+ // Evaluation of the dense matrix operand
+ CT1 A( ~mat );
+
+ // In order to compare the matrix and the scalar value, the data values of the lower-order
+ // data type are converted to the higher-order data type within the equal function.
+ for( size_t i=0; i<A.rows(); ++i ) {
+ for( size_t j=0; j<A.columns(); ++j ) {
+ if( !equal( A(i,j), scalar ) ) return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a column-major dense matrix and a scalar value.
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side column-major dense matrix for the comparison.
+// \param scalar The right-hand side scalar value for the comparison.
+// \return \a true if all elements of the matrix are equal to the scalar, \a false if not.
+//
+// If all values of the matrix are equal to the scalar value, the equality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side scalar
+inline EnableIf_<IsNumeric<T2>, bool > operator==( const DenseMatrix<T1,true>& mat, T2 scalar )
+{
+ typedef CompositeType_<T1> CT1;
+
+ // Evaluation of the dense matrix operand
+ CT1 A( ~mat );
+
+ // In order to compare the matrix and the scalar value, the data values of the lower-order
+ // data type are converted to the higher-order data type within the equal function.
+ for( size_t j=0; j<A.columns(); ++j ) {
+ for( size_t i=0; i<A.rows(); ++i ) {
+ if( !equal( A(i,j), scalar ) ) return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a scalar value and a dense matrix.
+// \ingroup dense_matrix
+//
+// \param scalar The left-hand side scalar value for the comparison.
+// \param mat The right-hand side dense matrix for the comparison.
+// \return \a true if all elements of the matrix are equal to the scalar, \a false if not.
+//
+// If all values of the matrix are equal to the scalar value, the equality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side scalar
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+inline EnableIf_<IsNumeric<T1>, bool > operator==( T1 scalar, const DenseMatrix<T2,SO>& mat )
+{
+ return ( mat == scalar );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of two dense matrices.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the comparison.
+// \param rhs The right-hand side dense matrix for the comparison.
+// \return \a true if the two matrices are not equal, \a false if they are equal.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline bool operator!=( const DenseMatrix<T1,SO1>& lhs, const DenseMatrix<T2,SO2>& rhs )
+{
+ return !( lhs == rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of a dense matrix and a sparse matrix.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the comparison.
+// \param rhs The right-hand side sparse matrix for the comparison.
+// \return \a true if the two matrices are not equal, \a false if they are equal.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO2 > // Storage order of the right-hand side sparse matrix
+inline bool operator!=( const DenseMatrix<T1,SO1>& lhs, const SparseMatrix<T2,SO2>& rhs )
+{
+ return !( lhs == rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of a sparse matrix and a dense matrix.
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the comparison.
+// \param rhs The right-hand side dense matrix for the comparison.
+// \return \a true if the two matrices are not equal, \a false if they are equal.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , bool SO1 // Storage order of the left-hand side sparse matrix
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order right-hand side dense matrix
+inline bool operator!=( const SparseMatrix<T1,SO1>& lhs, const DenseMatrix<T2,SO2>& rhs )
+{
+ return !( rhs == lhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of a dense matrix and a scalar value.
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side dense matrix for the comparison.
+// \param scalar The right-hand side scalar value for the comparison.
+// \return \a true if at least one element of the matrix is different from the scalar, \a false if not.
+//
+// If one value of the matrix is inequal to the scalar value, the inequality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side scalar
+ , bool SO > // Storage order
+inline EnableIf_<IsNumeric<T2>, bool > operator!=( const DenseMatrix<T1,SO>& mat, T2 scalar )
+{
+ return !( mat == scalar );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of a scalar value and a dense matrix.
+// \ingroup dense_matrix
+//
+// \param scalar The left-hand side scalar value for the comparison.
+// \param mat The right-hand side dense matrix for the comparison.
+// \return \a true if at least one element of the matrix is different from the scalar, \a false if not.
+//
+// If one value of the matrix is inequal to the scalar value, the inequality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side scalar
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+inline EnableIf_<IsNumeric<T1>, bool > operator!=( T1 scalar, const DenseMatrix<T2,SO>& mat )
+{
+ return !( mat == scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DenseMatrix functions */
+//@{
+template< typename MT, bool SO >
+bool isnan( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isSymmetric( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isHermitian( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isUniform( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isLower( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isUniLower( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isStrictlyLower( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isUpper( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isUniUpper( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isStrictlyUpper( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isDiagonal( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+bool isIdentity( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+const ElementType_<MT> min( const DenseMatrix<MT,SO>& dm );
+
+template< typename MT, bool SO >
+const ElementType_<MT> max( const DenseMatrix<MT,SO>& dm );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks the given dense matrix for not-a-number elements.
+// \ingroup dense_matrix
+//
+// \param dm The matrix to be checked for not-a-number elements.
+// \return \a true if at least one element of the matrix is not-a-number, \a false otherwise.
+//
+// This function checks the dense matrix for not-a-number (NaN) elements. If at least one
+// element of the matrix is not-a-number, the function returns \a true, otherwise it returns
+// \a false.
+
+ \code
+ blaze::DynamicMatrix<double> A( 3UL, 4UL );
+ // ... Initialization
+ if( isnan( A ) ) { ... }
+ \endcode
+
+// Note that this function only works for matrices with floating point elements. The attempt to
+// use it for a matrix with a non-floating point element type results in a compile time error.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isnan( const DenseMatrix<MT,SO>& dm )
+{
+ typedef CompositeType_<MT> CT;
+
+ CT A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( size_t j=0UL; j<A.columns(); ++j )
+ if( isnan( A(i,j) ) ) return true;
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( size_t i=0UL; i<A.rows(); ++i )
+ if( isnan( A(i,j) ) ) return true;
+ }
+ }
+
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is symmetric.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is symmetric, \a false if not.
+//
+// This function checks if the given dense matrix is symmetric. The matrix is considered to be
+// symmetric if it is a square matrix whose transpose is equal to itself (\f$ A = A^T \f$). The
+// following code example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isSymmetric( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a symmetric matrix:
+
+ \code
+ if( isSymmetric( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isSymmetric( const DenseMatrix<MT,SO>& dm )
+{
+ typedef CompositeType_<MT> CT;
+
+ if( IsSymmetric<MT>::value )
+ return true;
+
+ if( !isSquare( ~dm ) )
+ return false;
+
+ if( (~dm).rows() < 2UL )
+ return true;
+
+ if( IsTriangular<MT>::value )
+ return isDiagonal( ~dm );
+
+ CT A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=1UL; i<A.rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !equal( A(i,j), A(j,i) ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=1UL; j<A.columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ if( !equal( A(i,j), A(j,i) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is Hermitian.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is Hermitian, \a false if not.
+//
+// This function checks if the given dense matrix is an Hermitian matrix. The matrix is considered
+// to be an Hermitian matrix if it is a square matrix whose conjugate transpose is equal to itself
+// (\f$ A = \overline{A^T} \f$), i.e. each matrix element \f$ a_{ij} \f$ is equal to the complex
+// conjugate of the element \f$ a_{ji} \f$. The following code example demonstrates the use of the
+// function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isHermitian( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in an Hermitian matrix:
+
+ \code
+ if( isHermitian( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isHermitian( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ElementType_<MT> ET;
+ typedef CompositeType_<MT> CT;
+
+ if( IsHermitian<MT>::value )
+ return true;
+
+ if( !IsNumeric<ET>::value || !isSquare( ~dm ) )
+ return false;
+
+ if( (~dm).rows() < 2UL )
+ return true;
+
+ if( IsTriangular<MT>::value )
+ return isDiagonal( ~dm );
+
+ CT A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !equal( A(i,j), conj( A(j,i) ) ) )
+ return false;
+ }
+ if( !isReal( A(i,i) ) )
+ return false;
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ if( !equal( A(i,j), conj( A(j,i) ) ) )
+ return false;
+ }
+ if( !isReal( A(j,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checks if the given row-major triangular dense matrix is a uniform matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+*/
+template< typename MT > // Type of the dense matrix
+bool isUniform_backend( const DenseMatrix<MT,false>& dm, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() != 0UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() != 0UL, "Invalid number of columns detected" );
+
+ const size_t ibegin( ( IsStrictlyLower<MT>::value )?( 1UL ):( 0UL ) );
+ const size_t iend ( ( IsStrictlyUpper<MT>::value )?( (~dm).rows()-1UL ):( (~dm).rows() ) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ if( !IsUpper<MT>::value ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !isDefault( (~dm)(i,j) ) )
+ return false;
+ }
+ }
+ if( !isDefault( (~dm)(i,i) ) )
+ return false;
+ if( !IsLower<MT>::value ) {
+ for( size_t j=i+1UL; j<(~dm).columns(); ++j ) {
+ if( !isDefault( (~dm)(i,j) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checks if the given column-major triangular dense matrix is a uniform matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+*/
+template< typename MT > // Type of the dense matrix
+bool isUniform_backend( const DenseMatrix<MT,true>& dm, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() != 0UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() != 0UL, "Invalid number of columns detected" );
+
+ const size_t jbegin( ( IsStrictlyUpper<MT>::value )?( 1UL ):( 0UL ) );
+ const size_t jend ( ( IsStrictlyLower<MT>::value )?( (~dm).columns()-1UL ):( (~dm).columns() ) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ if( !IsLower<MT>::value ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ if( !isDefault( (~dm)(i,j) ) )
+ return false;
+ }
+ }
+ if( !isDefault( (~dm)(j,j) ) )
+ return false;
+ if( !IsUpper<MT>::value ) {
+ for( size_t i=j+1UL; i<(~dm).rows(); ++i ) {
+ if( !isDefault( (~dm)(i,j) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checks if the given row-major general dense matrix is a uniform matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+*/
+template< typename MT > // Type of the dense matrix
+bool isUniform_backend( const DenseMatrix<MT,false>& dm, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() != 0UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() != 0UL, "Invalid number of columns detected" );
+
+ ConstReference_<MT> cmp( (~dm)(0UL,0UL) );
+
+ for( size_t i=0UL; i<(~dm).rows(); ++i ) {
+ for( size_t j=0UL; j<(~dm).columns(); ++j ) {
+ if( (~dm)(i,j) != cmp )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checks if the given column-major general dense matrix is a uniform matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+*/
+template< typename MT > // Type of the dense matrix
+bool isUniform_backend( const DenseMatrix<MT,true>& dm, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() != 0UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() != 0UL, "Invalid number of columns detected" );
+
+ ConstReference_<MT> cmp( (~dm)(0UL,0UL) );
+
+ for( size_t j=0UL; j<(~dm).columns(); ++j ) {
+ for( size_t i=0UL; i<(~dm).rows(); ++i ) {
+ if( (~dm)(i,j) != cmp )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is a uniform matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+//
+// This function checks if the given dense matrix is a uniform matrix. The matrix is considered
+// to be uniform if all its elements are identical. The following code example demonstrates the
+// use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isUniform( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a uniform matrix:
+
+ \code
+ if( isUniform( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isUniform( const DenseMatrix<MT,SO>& dm )
+{
+ if( IsUniTriangular<MT>::value )
+ return false;
+
+ if( (~dm).rows() == 0UL || (~dm).columns() == 0UL ||
+ ( (~dm).rows() == 1UL && (~dm).columns() == 1UL ) )
+ return true;
+
+ CompositeType_<MT> A( ~dm ); // Evaluation of the dense matrix operand
+
+ return isUniform_backend( A, typename IsTriangular<MT>::Type() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is a lower triangular matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a lower triangular matrix, \a false if not.
+//
+// This function checks if the given dense matrix is a lower triangular matrix. The matrix is
+// considered to be lower triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ l_{0,0} & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & l_{1,1} & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & l_{2,2} & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & l_{N,N} \\
+ \end{array}\right).\f]
+
+// \f$ 0 \times 0 \f$ or \f$ 1 \times 1 \f$ matrices are considered as trivially lower triangular.
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isLower( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a lower triangular matrix:
+
+ \code
+ if( isLower( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isLower( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+
+ if( IsLower<MT>::value )
+ return true;
+
+ if( !isSquare( ~dm ) )
+ return false;
+
+ if( (~dm).rows() < 2UL )
+ return true;
+
+ Tmp A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows()-1UL; ++i ) {
+ for( size_t j=i+1UL; j<A.columns(); ++j ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=1UL; j<A.columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is a lower unitriangular matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a lower unitriangular matrix, \a false if not.
+//
+// This function checks if the given dense matrix is a lower unitriangular matrix. The matrix is
+// considered to be lower unitriangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & 1 & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & 1 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & 1 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isUniLower( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a lower unitriangular matrix:
+
+ \code
+ if( isUniLower( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isUniLower( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+
+ if( IsUniLower<MT>::value )
+ return true;
+
+ if( !isSquare( ~dm ) )
+ return false;
+
+ Tmp A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ if( !isOne( A(i,i) ) )
+ return false;
+ for( size_t j=i+1UL; j<A.columns(); ++j ) {
+ if( !isZero( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ if( !isZero( A(i,j) ) )
+ return false;
+ }
+ if( !isOne( A(j,j) ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is a strictly lower triangular matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a strictly lower triangular matrix, \a false if not.
+//
+// This function checks if the given dense matrix is a strictly lower triangular matrix. The
+// matrix is considered to be strictly lower triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & 0 & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & 0 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & 0 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isStrictlyLower( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a strictly lower triangular
+// matrix:
+
+ \code
+ if( isStrictlyLower( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isStrictlyLower( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+
+ if( IsStrictlyLower<MT>::value )
+ return true;
+
+ if( IsUniLower<MT>::value || IsUniUpper<MT>::value || !isSquare( ~dm ) )
+ return false;
+
+ Tmp A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( size_t j=i; j<A.columns(); ++j ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( size_t i=0UL; i<=j; ++i ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is an upper triangular matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is an upper triangular matrix, \a false if not.
+//
+// This function checks if the given dense matrix is an upper triangular matrix. The matrix is
+// considered to be upper triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ u_{0,0} & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & u_{1,1} & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & u_{2,2} & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & u_{N,N} \\
+ \end{array}\right).\f]
+
+// \f$ 0 \times 0 \f$ or \f$ 1 \times 1 \f$ matrices are considered as trivially upper triangular.
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isUpper( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in an upper triangular matrix:
+
+ \code
+ if( isUpper( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isUpper( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+
+ if( IsUpper<MT>::value )
+ return true;
+
+ if( !isSquare( ~dm ) )
+ return false;
+
+ if( (~dm).rows() < 2UL )
+ return true;
+
+ Tmp A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=1UL; i<A.rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns()-1UL; ++j ) {
+ for( size_t i=j+1UL; i<A.rows(); ++i ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is an upper unitriangular matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is an upper unitriangular matrix, \a false if not.
+//
+// This function checks if the given dense matrix is an upper unitriangular matrix. The matrix is
+// considered to be upper unitriangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & 1 & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & 1 & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & 1 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isUniUpper( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in an upper unitriangular matrix:
+
+ \code
+ if( isUniUpper( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isUniUpper( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+
+ if( IsUniUpper<MT>::value )
+ return true;
+
+ if( !isSquare( ~dm ) )
+ return false;
+
+ Tmp A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !isZero( A(i,j) ) )
+ return false;
+ }
+ if( !isOne( A(i,i) ) )
+ return false;
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ if( !isOne( A(j,j) ) )
+ return false;
+ for( size_t i=j+1UL; i<A.rows(); ++i ) {
+ if( !isZero( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense matrix is a strictly upper triangular matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is a strictly upper triangular matrix, \a false if not.
+//
+// This function checks if the given dense matrix is a strictly upper triangular matrix. The
+// matrix is considered to be strictly upper triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & 0 & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & 0 & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & 0 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isStrictlyUpper( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a strictly upper triangular
+// matrix:
+
+ \code
+ if( isStrictlyUpper( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isStrictlyUpper( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+
+ if( IsStrictlyUpper<MT>::value )
+ return true;
+
+ if( IsUniLower<MT>::value || IsUniUpper<MT>::value || !isSquare( ~dm ) )
+ return false;
+
+ Tmp A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( size_t i=j; i<A.rows(); ++i ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the give dense matrix is diagonal.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is diagonal, \a false if not.
+//
+// This function tests whether the matrix is diagonal, i.e. if the non-diagonal elements are
+// default elements. In case of integral or floating point data types, a diagonal matrix has
+// the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ aa & 0 & 0 & \cdots & 0 \\
+ 0 & bb & 0 & \cdots & 0 \\
+ 0 & 0 & cc & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & 0 \\
+ 0 & 0 & 0 & 0 & xx \\
+ \end{array}\right)\f]
+
+// \f$ 0 \times 0 \f$ or \f$ 1 \times 1 \f$ matrices are considered as trivially diagonal. The
+// following example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isDiagonal( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a diagonal matrix:
+
+ \code
+ if( isDiagonal( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isDiagonal( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+
+ if( IsDiagonal<MT>::value )
+ return true;
+
+ if( !isSquare( ~dm ) )
+ return false;
+
+ if( (~dm).rows() < 2UL )
+ return true;
+
+ Tmp A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ if( !IsUpper<MT>::value ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ if( !IsLower<MT>::value ) {
+ for( size_t j=i+1UL; j<A.columns(); ++j ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ if( !IsLower<MT>::value ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ if( !IsUpper<MT>::value ) {
+ for( size_t i=j+1UL; i<A.rows(); ++i ) {
+ if( !isDefault( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the give dense matrix is an identity matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be checked.
+// \return \a true if the matrix is an identity matrix, \a false if not.
+//
+// This function tests whether the matrix is an identity matrix, i.e. if the diagonal elements
+// are 1 and the non-diagonal elements are 0. In case of integral or floating point data types,
+// an identity matrix has the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & 0 & 0 & \cdots & 0 \\
+ 0 & 1 & 0 & \cdots & 0 \\
+ 0 & 0 & 1 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & 0 \\
+ 0 & 0 & 0 & 0 & 1 \\
+ \end{array}\right)\f]
+
+// The following example demonstrates the use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isIdentity( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in an identity matrix:
+
+ \code
+ if( isIdentity( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+bool isIdentity( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+
+ if( IsIdentity<MT>::value )
+ return true;
+
+ if( !isSquare( ~dm ) )
+ return false;
+
+ if( (~dm).rows() == 0UL )
+ return true;
+
+ Tmp A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ if( !IsUpper<MT>::value ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ if( !isZero( A(i,j) ) )
+ return false;
+ }
+ }
+ if( !IsUniLower<MT>::value && !IsUniUpper<MT>::value && !isOne( A(i,i) ) ) {
+ return false;
+ }
+ if( !IsLower<MT>::value ) {
+ for( size_t j=i+1UL; j<A.columns(); ++j ) {
+ if( !isZero( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ if( !IsLower<MT>::value ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ if( !isZero( A(i,j) ) )
+ return false;
+ }
+ }
+ if( !IsUniLower<MT>::value && !IsUniUpper<MT>::value && !isOne( A(j,j) ) ) {
+ return false;
+ }
+ if( !IsUpper<MT>::value ) {
+ for( size_t i=j+1UL; i<A.rows(); ++i ) {
+ if( !isZero( A(i,j) ) )
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the smallest element of the dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The smallest dense matrix element.
+//
+// This function returns the smallest element of the given dense matrix. This function can
+// only be used for element types that support the smaller-than relationship. In case the
+// matrix currently has either 0 rows or 0 columns, the returned value is the default value
+// (e.g. 0 in case of fundamental data types).
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+const ElementType_<MT> min( const DenseMatrix<MT,SO>& dm )
+{
+ using blaze::min;
+
+ typedef ElementType_<MT> ET;
+ typedef CompositeType_<MT> CT;
+
+ CT A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( A.rows() == 0UL || A.columns() == 0UL ) return ET();
+
+ ET minimum( A(0,0) );
+
+ if( SO == rowMajor ) {
+ for( size_t j=1UL; j<A.columns(); ++j )
+ minimum = min( minimum, A(0UL,j) );
+ for( size_t i=1UL; i<A.rows(); ++i )
+ for( size_t j=0UL; j<A.columns(); ++j )
+ minimum = min( minimum, A(i,j) );
+ }
+ else {
+ for( size_t i=1UL; i<A.rows(); ++i )
+ minimum = min( minimum, A(i,0UL) );
+ for( size_t j=1UL; j<A.columns(); ++j )
+ for( size_t i=0UL; i<A.rows(); ++i )
+ minimum = min( minimum, A(i,j) );
+ }
+
+ return minimum;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the largest element of the dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The largest dense matrix element.
+//
+// This function returns the largest element of the given dense matrix. This function can
+// only be used for element types that support the smaller-than relationship. In case the
+// matrix currently has either 0 rows or 0 columns, the returned value is the default value
+// (e.g. 0 in case of fundamental data types).
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Transpose flag
+const ElementType_<MT> max( const DenseMatrix<MT,SO>& dm )
+{
+ using blaze::max;
+
+ typedef ElementType_<MT> ET;
+ typedef CompositeType_<MT> CT;
+
+ CT A( ~dm ); // Evaluation of the dense matrix operand
+
+ if( A.rows() == 0UL || A.columns() == 0UL ) return ET();
+
+ ET maximum( A(0,0) );
+
+ if( SO == rowMajor ) {
+ for( size_t j=1UL; j<A.columns(); ++j )
+ maximum = max( maximum, A(0UL,j) );
+ for( size_t i=1UL; i<A.rows(); ++i )
+ for( size_t j=0UL; j<A.columns(); ++j )
+ maximum = max( maximum, A(i,j) );
+ }
+ else {
+ for( size_t i=1UL; i<A.rows(); ++i )
+ maximum = max( maximum, A(i,0UL) );
+ for( size_t j=1UL; j<A.columns(); ++j )
+ for( size_t i=0UL; i<A.rows(); ++i )
+ maximum = max( maximum, A(i,j) );
+ }
+
+ return maximum;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/DenseVector.h b/src/cpu/blaze/math/dense/DenseVector.h
new file mode 100644
index 00000000..a0b8a593
--- /dev/null
+++ b/src/cpu/blaze/math/dense/DenseVector.h
@@ -0,0 +1,648 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/DenseVector.h
+// \brief Header file for utility functions for dense vectors
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_DENSEVECTOR_H_
+#define _BLAZE_MATH_DENSE_DENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Equal.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsDivisor.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/Sqrt.h>
+#include <blaze/math/shims/Square.h>
+#include <blaze/math/TransposeFlag.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DenseVector operators */
+//@{
+template< typename T1, bool TF1, typename T2, bool TF2 >
+inline bool operator==( const DenseVector<T1,TF1>& lhs, const DenseVector<T2,TF2>& rhs );
+
+template< typename T1, bool TF1, typename T2, bool TF2 >
+inline bool operator==( const DenseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs );
+
+template< typename T1, bool TF1, typename T2, bool TF2 >
+inline bool operator==( const SparseVector<T1,TF1>& lhs, const DenseVector<T2,TF2>& rhs );
+
+template< typename T1, typename T2, bool TF >
+inline EnableIf_<IsNumeric<T2>, bool > operator==( const DenseVector<T1,TF>& vec, T2 scalar );
+
+template< typename T1, typename T2, bool TF >
+inline EnableIf_<IsNumeric<T1>, bool > operator==( T1 scalar, const DenseVector<T2,TF>& vec );
+
+template< typename T1, bool TF1, typename T2, bool TF2 >
+inline bool operator!=( const DenseVector<T1,TF1>& lhs, const DenseVector<T2,TF2>& rhs );
+
+template< typename T1, bool TF1, typename T2, bool TF2 >
+inline bool operator!=( const DenseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs );
+
+template< typename T1, bool TF1, typename T2, bool TF2 >
+inline bool operator!=( const SparseVector<T1,TF1>& lhs, const DenseVector<T2,TF2>& rhs );
+
+template< typename T1, typename T2, bool TF >
+inline EnableIf_<IsNumeric<T2>, bool > operator!=( const DenseVector<T1,TF>& vec, T2 scalar );
+
+template< typename T1, typename T2, bool TF >
+inline EnableIf_<IsNumeric<T1>, bool > operator!=( T1 scalar, const DenseVector<T2,TF>& vec );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of two dense vectors.
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the comparison.
+// \param rhs The right-hand side dense vector for the comparison.
+// \return \a true if the two vectors are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+inline bool operator==( const DenseVector<T1,TF1>& lhs, const DenseVector<T2,TF2>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+
+ // Early exit in case the vector sizes don't match
+ if( (~lhs).size() != (~rhs).size() ) return false;
+
+ // Evaluation of the two dense vector operands
+ CT1 a( ~lhs );
+ CT2 b( ~rhs );
+
+ // In order to compare the two vectors, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ for( size_t i=0; i<a.size(); ++i )
+ if( !equal( a[i], b[i] ) ) return false;
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a dense vector and a sparse vector.
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the comparison.
+// \param rhs The right-hand side sparse vector for the comparison.
+// \return \a true if the two vectors are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+inline bool operator==( const DenseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+ typedef ConstIterator_< RemoveReference_<CT2> > ConstIterator;
+
+ // Early exit in case the vector sizes don't match
+ if( (~lhs).size() != (~rhs).size() ) return false;
+
+ // Evaluation of the dense vector and sparse vector operand
+ CT1 a( ~lhs );
+ CT2 b( ~rhs );
+
+ // In order to compare the two vectors, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ size_t i( 0 );
+
+ for( ConstIterator element=b.begin(); element!=b.end(); ++element, ++i ) {
+ for( ; i<element->index(); ++i ) {
+ if( !isDefault( a[i] ) ) return false;
+ }
+ if( !equal( element->value(), a[i] ) ) return false;
+ }
+ for( ; i<a.size(); ++i ) {
+ if( !isDefault( a[i] ) ) return false;
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a sparse vector and a dense vector.
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector for the comparison.
+// \param rhs The right-hand side dense vector for the comparison.
+// \return \a true if the two vectors are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , bool TF1 // Transpose flag of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+inline bool operator==( const SparseVector<T1,TF1>& lhs, const DenseVector<T2,TF2>& rhs )
+{
+ return ( rhs == lhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a dense vector and a scalar value.
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector for the comparison.
+// \param scalar The right-hand side scalar value for the comparison.
+// \return \a true if all elements of the vector are equal to the scalar, \a false if not.
+//
+// If all values of the vector are equal to the scalar value, the equality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side scalar
+ , bool TF > // Transpose flag
+inline EnableIf_<IsNumeric<T2>, bool > operator==( const DenseVector<T1,TF>& vec, T2 scalar )
+{
+ typedef CompositeType_<T1> CT1;
+
+ // Evaluation of the dense vector operand
+ CT1 a( ~vec );
+
+ // In order to compare the vector and the scalar value, the data values of the lower-order
+ // data type are converted to the higher-order data type within the equal function.
+ for( size_t i=0; i<a.size(); ++i )
+ if( !equal( a[i], scalar ) ) return false;
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of a scalar value and a dense vector.
+// \ingroup dense_vector
+//
+// \param scalar The left-hand side scalar value for the comparison.
+// \param vec The right-hand side dense vector for the comparison.
+// \return \a true if all elements of the vector are equal to the scalar, \a false if not.
+//
+// If all values of the vector are equal to the scalar value, the equality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side scalar
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline EnableIf_<IsNumeric<T1>, bool > operator==( T1 scalar, const DenseVector<T2,TF>& vec )
+{
+ return ( vec == scalar );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of two dense vectors.
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the comparison.
+// \param rhs The right-hand side dense vector for the comparison.
+// \return \a true if the two vectors are not equal, \a false if they are equal.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+inline bool operator!=( const DenseVector<T1,TF1>& lhs, const DenseVector<T2,TF2>& rhs )
+{
+ return !( lhs == rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of a dense vector and a sparse vector.
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the comparison.
+// \param rhs The right-hand side sparse vector for the comparison.
+// \return \a true if the two vectors are not equal, \a false if they are equal.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+inline bool operator!=( const DenseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs )
+{
+ return !( lhs == rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of a sparse vector and a dense vector.
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector for the comparison.
+// \param rhs The right-hand side dense vector for the comparison.
+// \return \a true if the two vectors are not equal, \a false if they are equal.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , bool TF1 // Transpose flag of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+inline bool operator!=( const SparseVector<T1,TF1>& lhs, const DenseVector<T2,TF2>& rhs )
+{
+ return !( rhs == lhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of a dense vector and a scalar value.
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector for the comparison.
+// \param scalar The right-hand side scalar value for the comparison.
+// \return \a true if at least one element of the vector is different from the scalar, \a false if not.
+//
+// If one value of the vector is inequal to the scalar value, the inequality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side scalar
+ , bool TF > // Transpose flag
+inline EnableIf_<IsNumeric<T2>, bool > operator!=( const DenseVector<T1,TF>& vec, T2 scalar )
+{
+ return !( vec == scalar );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of a scalar value and a dense vector.
+// \ingroup dense_vector
+//
+// \param scalar The left-hand side scalar value for the comparison.
+// \param vec The right-hand side dense vector for the comparison.
+// \return \a true if at least one element of the vector is different from the scalar, \a false if not.
+//
+// If one value of the vector is inequal to the scalar value, the inequality test returns \a true,
+// otherwise \a false. Note that this function can only be used with built-in, numerical data
+// types!
+*/
+template< typename T1 // Type of the left-hand side scalar
+ , typename T2 // Type of the right-hand side vector
+ , bool TF > // Transpose flag
+inline EnableIf_<IsNumeric<T1>, bool > operator!=( T1 scalar, const DenseVector<T2,TF>& vec )
+{
+ return !( vec == scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DenseVector functions */
+//@{
+template< typename VT, bool TF >
+bool isnan( const DenseVector<VT,TF>& dv );
+
+template< typename VT, bool TF >
+bool isDivisor( const DenseVector<VT,TF>& dv );
+
+template< typename VT, bool TF >
+bool isUniform( const DenseVector<VT,TF>& dv );
+
+template< typename VT, bool TF >
+const ElementType_<VT> sqrLength( const DenseVector<VT,TF>& dv );
+
+template< typename VT, bool TF >
+inline auto length( const DenseVector<VT,TF>& dv ) -> decltype( sqrt( sqrLength( ~dv ) ) );
+
+template< typename VT, bool TF >
+const ElementType_<VT> min( const DenseVector<VT,TF>& dv );
+
+template< typename VT, bool TF >
+const ElementType_<VT> max( const DenseVector<VT,TF>& dv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks the given dense vector for not-a-number elements.
+// \ingroup dense_vector
+//
+// \param dv The vector to be checked for not-a-number elements.
+// \return \a true if at least one element of the vector is not-a-number, \a false otherwise.
+//
+// This function checks the N-dimensional dense vector for not-a-number (NaN) elements. If at
+// least one element of the vector is not-a-number, the function returns \a true, otherwise it
+// returns \a false.
+
+ \code
+ blaze::DynamicVector<double> a;
+ // ... Resizing and initialization
+ if( isnan( a ) ) { ... }
+ \endcode
+
+// Note that this function only works for vectors with floating point elements. The attempt to
+// use it for a vector with a non-floating point element type results in a compile time error.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+bool isnan( const DenseVector<VT,TF>& dv )
+{
+ CompositeType_<VT> a( ~dv ); // Evaluation of the dense vector operand
+
+ for( size_t i=0UL; i<a.size(); ++i ) {
+ if( isnan( a[i] ) ) return true;
+ }
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given dense vector is a valid divisor.
+// \ingroup dense_vector
+//
+// \param dv The dense vector to be tested.
+// \return \a true in case the given vector is a valid divisor, \a false otherwise.
+//
+// This function checks if the given dense vector is a valid divisor. If all elements of the
+// vector are valid divisors the function returns \a true, if at least one element of the vector
+// is not a valid divisor, the function returns \a false.
+
+ \code
+ StaticVector<int,3UL> a{ 1, -1, 2 }; // isDivisor( a ) returns true
+ StaticVector<int,3UL> b{ 1, -1, 0 }; // isDivisor( b ) returns false
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+bool isDivisor( const DenseVector<VT,TF>& dv )
+{
+ CompositeType_<VT> a( ~dv ); // Evaluation of the dense vector operand
+
+ for( size_t i=0UL; i<a.size(); ++i ) {
+ if( !isDivisor( a[i] ) ) return false;
+ }
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given dense vector is a uniform vector.
+// \ingroup dense_vector
+//
+// \param dv The dense vector to be checked.
+// \return \a true if the vector is a uniform vector, \a false if not.
+//
+// This function checks if the given dense vector is a uniform vector. The vector is considered
+// to be uniform if all its elements are identical. The following code example demonstrates the
+// use of the function:
+
+ \code
+ blaze::DynamicVector<int,blaze::columnVector> a, b;
+ // ... Initialization
+ if( isUniform( a ) ) { ... }
+ \endcode
+
+// It is also possible to check if a vector expression results in a uniform vector:
+
+ \code
+ if( isUniform( a + b ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary vector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+bool isUniform( const DenseVector<VT,TF>& dv )
+{
+ typedef CompositeType_<VT> CT;
+ typedef ConstReference_< RemoveReference_<CT> > ConstReference;
+
+ if( (~dv).size() < 2UL )
+ return true;
+
+ CT a( ~dv ); // Evaluation of the dense vector operand
+
+ ConstReference cmp( (~dv)[0UL] );
+
+ for( size_t i=1UL; i<(~dv).size(); ++i ) {
+ if( (~dv)[i] != cmp )
+ return false;
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Calculation of the dense vector square length \f$|\vec{a}|^2\f$.
+// \ingroup dense_vector
+//
+// \param dv The given dense vector.
+// \return The square length of the dense vector.
+//
+// This function calculates the actual square length of the dense vector.
+//
+// \note This operation is only defined for numeric data types. In case the element type is
+// not a numeric data type (i.e. a user defined data type or boolean) the attempt to use the
+// sqrLength() function results in a compile time error!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+const ElementType_<VT> sqrLength( const DenseVector<VT,TF>& dv )
+{
+ typedef ElementType_<VT> ElementType;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ElementType );
+
+ ElementType sum( 0 );
+ for( size_t i=0UL; i<(~dv).size(); ++i )
+ sum += sq( (~dv)[i] );
+ return sum;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Calculation of the dense vector length \f$|\vec{a}|\f$.
+// \ingroup dense_vector
+//
+// \param dv The given dense vector.
+// \return The length of the dense vector.
+//
+// This function calculates the actual length of the dense vector. The return type of the
+// length() function depends on the actual element type of the vector instance:
+//
+// <table border="0" cellspacing="0" cellpadding="1">
+// <tr>
+// <td width="250px"> \b Type </td>
+// <td width="100px"> \b LengthType </td>
+// </tr>
+// <tr>
+// <td>float</td>
+// <td>float</td>
+// </tr>
+// <tr>
+// <td>integral data types and double</td>
+// <td>double</td>
+// </tr>
+// <tr>
+// <td>long double</td>
+// <td>long double</td>
+// </tr>
+// <tr>
+// <td>complex<T></td>
+// <td>complex<T></td>
+// </tr>
+// </table>
+//
+// \note This operation is only defined for numeric data types. In case the element type is
+// not a numeric data type (i.e. a user defined data type or boolean) the attempt to use the
+// sqrLength() function results in a compile time error!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline auto length( const DenseVector<VT,TF>& dv ) -> decltype( sqrt( sqrLength( ~dv ) ) )
+{
+ return sqrt( sqrLength( ~dv ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the smallest element of the dense vector.
+// \ingroup dense_vector
+//
+// \param dv The given dense vector.
+// \return The smallest dense vector element.
+//
+// This function returns the smallest element of the given dense vector. This function can
+// only be used for element types that support the smaller-than relationship. In case the
+// vector currently has a size of 0, the returned value is the default value (e.g. 0 in case
+// of fundamental data types).
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+const ElementType_<VT> min( const DenseVector<VT,TF>& dv )
+{
+ using blaze::min;
+
+ typedef ElementType_<VT> ET;
+ typedef CompositeType_<VT> CT;
+
+ CT a( ~dv ); // Evaluation of the dense vector operand
+
+ if( a.size() == 0UL ) return ET();
+
+ ET minimum( a[0] );
+ for( size_t i=1UL; i<a.size(); ++i )
+ minimum = min( minimum, a[i] );
+ return minimum;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the largest element of the dense vector.
+// \ingroup dense_vector
+//
+// \param dv The given dense vector.
+// \return The largest dense vector element.
+//
+// This function returns the largest element of the given dense vector. This function can
+// only be used for element types that support the smaller-than relationship. In case the
+// vector currently has a size of 0, the returned value is the default value (e.g. 0 in case
+// of fundamental data types).
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+const ElementType_<VT> max( const DenseVector<VT,TF>& dv )
+{
+ using blaze::max;
+
+ typedef ElementType_<VT> ET;
+ typedef CompositeType_<VT> CT;
+
+ CT a( ~dv ); // Evaluation of the dense vector operand
+
+ if( a.size() == 0UL ) return ET();
+
+ ET maximum( a[0] );
+ for( size_t i=1UL; i<a.size(); ++i )
+ maximum = max( maximum, a[i] );
+ return maximum;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/DynamicMatrix.h b/src/cpu/blaze/math/dense/DynamicMatrix.h
new file mode 100644
index 00000000..c93b0972
--- /dev/null
+++ b/src/cpu/blaze/math/dense/DynamicMatrix.h
@@ -0,0 +1,6324 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/DynamicMatrix.h
+// \brief Header file for the implementation of a dynamic MxN matrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_DYNAMICMATRIX_H_
+#define _BLAZE_MATH_DENSE_DYNAMICMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/Diagonal.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/dense/DenseIterator.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/InvExprTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/CacheSize.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Restrict.h>
+#include <blaze/system/StorageOrder.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Algorithm.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup dynamic_matrix DynamicMatrix
+// \ingroup dense_matrix
+*/
+/*!\brief Efficient implementation of a dynamic \f$ M \times N \f$ matrix.
+// \ingroup dynamic_matrix
+//
+// The DynamicMatrix class template is the representation of an arbitrary sized matrix with
+// \f$ M \times N \f$ dynamically allocated elements of arbitrary type. The type of the elements
+// and the storage order of the matrix can be specified via the two template parameters:
+
+ \code
+ template< typename Type, bool SO >
+ class DynamicMatrix;
+ \endcode
+
+// - Type: specifies the type of the matrix elements. DynamicMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// Depending on the storage order, the matrix elements are either stored in a row-wise fashion
+// or in a column-wise fashion. Given the 2x3 matrix
+
+ \f[\left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 4 & 5 & 6 \\
+ \end{array}\right)\f]\n
+
+// in case of row-major order the elements are stored in the order
+
+ \f[\left(\begin{array}{*{6}{c}}
+ 1 & 2 & 3 & 4 & 5 & 6. \\
+ \end{array}\right)\f]
+
+// In case of column-major order the elements are stored in the order
+
+ \f[\left(\begin{array}{*{6}{c}}
+ 1 & 4 & 2 & 5 & 3 & 6. \\
+ \end{array}\right)\f]
+
+// The use of DynamicMatrix is very natural and intuitive. All operations (addition, subtraction,
+// multiplication, scaling, ...) can be performed on all possible combination of row-major and
+// column-major dense and sparse matrices with fitting element types. The following example gives
+// an impression of the use of DynamicMatrix:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,rowMajor> A( 2, 3 ); // Default constructed, non-initialized, row-major 2x3 matrix
+ A(0,0) = 1.0; A(0,1) = 2.0; A(0,2) = 3.0; // Initialization of the first row
+ A(1,0) = 4.0; A(1,1) = 5.0; A(1,2) = 6.0; // Initialization of the second row
+
+ DynamicMatrix<float,columnMajor> B( 2, 3 ); // Default constructed column-major single precision 2x3 matrix
+ B(0,0) = 1.0; B(0,1) = 3.0; B(0,2) = 5.0; // Initialization of the first row
+ B(1,0) = 2.0; B(1,1) = 4.0; B(1,2) = 6.0; // Initialization of the second row
+
+ CompressedMatrix<float> C( 2, 3 ); // Empty row-major sparse single precision matrix
+ DynamicMatrix<float> D( 3, 2, 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix
+
+ DynamicMatrix<double,rowMajor> E( A ); // Creation of a new row-major matrix as a copy of A
+ DynamicMatrix<double,columnMajor> F; // Creation of a default column-major matrix
+
+ E = A + B; // Matrix addition and assignment to a row-major matrix
+ F = A - C; // Matrix subtraction and assignment to a column-major matrix
+ F = A * D; // Matrix multiplication between two matrices of different element types
+
+ A *= 2.0; // In-place scaling of matrix A
+ E = 2.0 * B; // Scaling of matrix B
+ F = D * 2.0; // Scaling of matrix D
+
+ E += A - B; // Addition assignment
+ E -= A + C; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , bool SO = defaultStorageOrder > // Storage order
+class DynamicMatrix : public DenseMatrix< DynamicMatrix<Type,SO>, SO >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DynamicMatrix<Type,SO> This; //!< Type of this DynamicMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this DynamicMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef DynamicMatrix<Type,!SO> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef DynamicMatrix<Type,!SO> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Type* Pointer; //!< Pointer to a non-constant matrix value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant matrix value.
+
+ typedef DenseIterator<Type,usePadding> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,usePadding> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a DynamicMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef DynamicMatrix<ET,SO> Other; //!< The type of the other DynamicMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the element type of the matrix is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline DynamicMatrix() noexcept;
+ explicit inline DynamicMatrix( size_t m, size_t n );
+ explicit inline DynamicMatrix( size_t m, size_t n, const Type& init );
+ explicit inline DynamicMatrix( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other >
+ explicit inline DynamicMatrix( size_t m, size_t n, const Other* array );
+
+ template< typename Other, size_t M, size_t N >
+ explicit inline DynamicMatrix( const Other (&array)[M][N] );
+
+ inline DynamicMatrix( const DynamicMatrix& m );
+ inline DynamicMatrix( DynamicMatrix&& m ) noexcept;
+ template< typename MT, bool SO2 > inline DynamicMatrix( const Matrix<MT,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~DynamicMatrix();
+ //@}
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t i ) noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i ) noexcept;
+ inline ConstIterator begin ( size_t i ) const noexcept;
+ inline ConstIterator cbegin( size_t i ) const noexcept;
+ inline Iterator end ( size_t i ) noexcept;
+ inline ConstIterator end ( size_t i ) const noexcept;
+ inline ConstIterator cend ( size_t i ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline DynamicMatrix& operator=( const Type& rhs );
+ inline DynamicMatrix& operator=( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other, size_t M, size_t N >
+ inline DynamicMatrix& operator=( const Other (&array)[M][N] );
+
+ inline DynamicMatrix& operator=( const DynamicMatrix& rhs );
+ inline DynamicMatrix& operator=( DynamicMatrix&& rhs ) noexcept;
+
+ template< typename MT, bool SO2 > inline DynamicMatrix& operator= ( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline DynamicMatrix& operator+=( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline DynamicMatrix& operator-=( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline DynamicMatrix& operator*=( const Matrix<MT,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, DynamicMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, DynamicMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t m, size_t n, bool preserve=true );
+ inline void extend ( size_t m, size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ inline DynamicMatrix& transpose();
+ inline DynamicMatrix& ctranspose();
+ template< typename Other > inline DynamicMatrix& scale( const Other& scalar );
+ inline void swap( DynamicMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDAdd< Type, ElementType_<MT> >::value &&
+ !IsDiagonal<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDSub< Type, ElementType_<MT> >::value &&
+ !IsDiagonal<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT >
+ inline DisableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void assign( const DenseMatrix<MT,!SO>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,!SO>& rhs );
+
+ template< typename MT >
+ inline DisableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void addAssign( const DenseMatrix<MT,!SO>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,!SO>& rhs );
+
+ template< typename MT >
+ inline DisableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void subAssign( const DenseMatrix<MT,!SO>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,!SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t adjustColumns( size_t minColumns ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t m_; //!< The current number of rows of the matrix.
+ size_t n_; //!< The current number of columns of the matrix.
+ size_t nn_; //!< The alignment adjusted number of columns.
+ size_t capacity_; //!< The maximum capacity of the matrix.
+ Type* BLAZE_RESTRICT v_; //!< The dynamically allocated matrix elements.
+ /*!< Access to the matrix elements is gained via the function call
+ operator. In case of row-major order the memory layout of the
+ elements is
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ N & N+1 & N+2 & \cdots & 2 \cdot N-1 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ M \cdot N-N & M \cdot N-N+1 & M \cdot N-N+2 & \cdots & M \cdot N-1 \\
+ \end{array}\right)\f]. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for DynamicMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>::DynamicMatrix() noexcept
+ : m_ ( 0UL ) // The current number of rows of the matrix
+ , n_ ( 0UL ) // The current number of columns of the matrix
+ , nn_ ( 0UL ) // The alignment adjusted number of columns
+ , capacity_( 0UL ) // The maximum capacity of the matrix
+ , v_ ( nullptr ) // The matrix elements
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$. No element initialization is performed!
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+//
+// \note This constructor is only responsible to allocate the required dynamic memory. No
+// element initialization is performed!
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>::DynamicMatrix( size_t m, size_t n )
+ : m_ ( m ) // The current number of rows of the matrix
+ , n_ ( n ) // The current number of columns of the matrix
+ , nn_ ( adjustColumns( n ) ) // The alignment adjusted number of columns
+ , capacity_( m_*nn_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=n_; j<nn_; ++j ) {
+ v_[i*nn_+j] = Type();
+ }
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a homogenous initialization of all \f$ m \times n \f$ matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param init The initial value of the matrix elements.
+//
+// All matrix elements are initialized with the specified value.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>::DynamicMatrix( size_t m, size_t n, const Type& init )
+ : m_ ( m ) // The current number of rows of the matrix
+ , n_ ( n ) // The current number of columns of the matrix
+ , nn_ ( adjustColumns( n ) ) // The alignment adjusted number of columns
+ , capacity_( m_*nn_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*nn_+j] = init;
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t j=n_; j<nn_; ++j )
+ v_[i*nn_+j] = Type();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+//
+// This constructor provides the option to explicitly initialize the elements of the matrix by
+// means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<int,rowMajor> A{ { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all its elements are
+// initialized by the values of the given initializer list. Missing values are initialized as
+// default (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>::DynamicMatrix( initializer_list< initializer_list<Type> > list )
+ : m_ ( list.size() ) // The current number of rows of the matrix
+ , n_ ( determineColumns( list ) ) // The current number of columns of the matrix
+ , nn_ ( adjustColumns( n_ ) ) // The alignment adjusted number of columns
+ , capacity_( m_*nn_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*nn_ ), v_+(i+1UL)*nn_, Type() );
+ ++i;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param array Dynamic array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[20];
+ // ... Initialization of the dynamic array
+ blaze::DynamicMatrix<int,rowMajor> v( 4UL, 5UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized according to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a m by
+// \a n elements. Providing an array with less elements results in undefined behavior!
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the initialization array
+inline DynamicMatrix<Type,SO>::DynamicMatrix( size_t m, size_t n, const Other* array )
+ : m_ ( m ) // The current number of rows of the matrix
+ , n_ ( n ) // The current number of columns of the matrix
+ , nn_ ( adjustColumns( n ) ) // The alignment adjusted number of columns
+ , capacity_( m_*nn_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j )
+ v_[i*nn_+j] = array[i*n+j];
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t j=n; j<nn_; ++j )
+ v_[i*nn_+j] = Type();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::DynamicMatrix<int,rowMajor> A( init );
+ \endcode
+
+// The matrix is sized according to the size of the array and initialized with the values from
+// the given array. Missing values are initialized with default values (as e.g. the value 6 in
+// the example).
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Other // Data type of the initialization array
+ , size_t M // Number of rows of the initialization array
+ , size_t N > // Number of columns of the initialization array
+inline DynamicMatrix<Type,SO>::DynamicMatrix( const Other (&array)[M][N] )
+ : m_ ( M ) // The current number of rows of the matrix
+ , n_ ( N ) // The current number of columns of the matrix
+ , nn_ ( adjustColumns( N ) ) // The alignment adjusted number of columns
+ , capacity_( m_*nn_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*nn_+j] = array[i][j];
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t j=N; j<nn_; ++j )
+ v_[i*nn_+j] = Type();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for DynamicMatrix.
+//
+// \param m Matrix to be copied.
+//
+// The copy constructor is explicitly defined due to the required dynamic memory management
+// and in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>::DynamicMatrix( const DynamicMatrix& m )
+ : m_ ( m.m_ ) // The current number of rows of the matrix
+ , n_ ( m.n_ ) // The current number of columns of the matrix
+ , nn_ ( m.nn_ ) // The alignment adjusted number of columns
+ , capacity_( m_*nn_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ BLAZE_INTERNAL_ASSERT( capacity_ <= m.capacity_, "Invalid capacity estimation" );
+
+ for( size_t i=0UL; i<capacity_; ++i )
+ v_[i] = m.v_[i];
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The move constructor for DynamicMatrix.
+//
+// \param m The matrix to be move into this instance.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>::DynamicMatrix( DynamicMatrix&& m ) noexcept
+ : m_ ( m.m_ ) // The current number of rows of the matrix
+ , n_ ( m.n_ ) // The current number of columns of the matrix
+ , nn_ ( m.nn_ ) // The alignment adjusted number of columns
+ , capacity_( m.capacity_ ) // The maximum capacity of the matrix
+ , v_ ( m.v_ ) // The matrix elements
+{
+ m.m_ = 0UL;
+ m.n_ = 0UL;
+ m.nn_ = 0UL;
+ m.capacity_ = 0UL;
+ m.v_ = nullptr;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline DynamicMatrix<Type,SO>::DynamicMatrix( const Matrix<MT,SO2>& m )
+ : m_ ( (~m).rows() ) // The current number of rows of the matrix
+ , n_ ( (~m).columns() ) // The current number of columns of the matrix
+ , nn_ ( adjustColumns( n_ ) ) // The alignment adjusted number of columns
+ , capacity_( m_*nn_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=( IsSparseMatrix<MT>::value ? 0UL : n_ );
+ j<( IsVectorizable<Type>::value ? nn_ : n_ ); ++j ) {
+ v_[i*nn_+j] = Type();
+ }
+ }
+
+ smpAssign( *this, ~m );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The destructor for DynamicMatrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>::~DynamicMatrix()
+{
+ deallocate( v_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::Reference
+ DynamicMatrix<Type,SO>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
+ return v_[i*nn_+j];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::ConstReference
+ DynamicMatrix<Type,SO>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
+ return v_[i*nn_+j];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::Reference
+ DynamicMatrix<Type,SO>::at( size_t i, size_t j )
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::ConstReference
+ DynamicMatrix<Type,SO>::at( size_t i, size_t j ) const
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::Pointer
+ DynamicMatrix<Type,SO>::data() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::ConstPointer
+ DynamicMatrix<Type,SO>::data() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::Pointer
+ DynamicMatrix<Type,SO>::data( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return v_ + i*nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::ConstPointer
+ DynamicMatrix<Type,SO>::data( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return v_ + i*nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::Iterator
+ DynamicMatrix<Type,SO>::begin( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return Iterator( v_ + i*nn_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::ConstIterator
+ DynamicMatrix<Type,SO>::begin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*nn_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::ConstIterator
+ DynamicMatrix<Type,SO>::cbegin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*nn_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::Iterator
+ DynamicMatrix<Type,SO>::end( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return Iterator( v_ + i*nn_ + n_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::ConstIterator
+ DynamicMatrix<Type,SO>::end( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*nn_ + n_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline typename DynamicMatrix<Type,SO>::ConstIterator
+ DynamicMatrix<Type,SO>::cend( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*nn_ + n_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Homogenous assignment to all matrix elements.
+//
+// \param rhs Scalar value to be assigned to all matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::operator=( const Type& rhs )
+{
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*nn_+j] = rhs;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+//
+// This assignment operator offers the option to directly assign to all elements of the matrix
+// by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<int,rowMajor> A;
+ A = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix is resized according to the given initializer list and all its elements are
+// assigned the values from the given initializer list. Missing values are initialized as
+// default (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>&
+ DynamicMatrix<Type,SO>::operator=( initializer_list< initializer_list<Type> > list )
+{
+ resize( list.size(), determineColumns( list ), false );
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*nn_ ), v_+(i+1UL)*nn_, Type() );
+ ++i;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array assignment to all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+//
+// This assignment operator offers the option to directly set all elements of the matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::DynamicMatrix<int,rowMajor> A;
+ A = init;
+ \endcode
+
+// The matrix is resized according to the size of the array and assigned the values of the given
+// array. Missing values are initialized with default values (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Other // Data type of the initialization array
+ , size_t M // Number of rows of the initialization array
+ , size_t N > // Number of columns of the initialization array
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::operator=( const Other (&array)[M][N] )
+{
+ resize( M, N, false );
+
+ for( size_t i=0UL; i<M; ++i )
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*nn_+j] = array[i][j];
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for DynamicMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::operator=( const DynamicMatrix& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ resize( rhs.m_, rhs.n_, false );
+ smpAssign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Move assignment operator for DynamicMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::operator=( DynamicMatrix&& rhs ) noexcept
+{
+ deallocate( v_ );
+
+ m_ = rhs.m_;
+ n_ = rhs.n_;
+ nn_ = rhs.nn_;
+ capacity_ = rhs.capacity_;
+ v_ = rhs.v_;
+
+ rhs.m_ = 0UL;
+ rhs.n_ = 0UL;
+ rhs.nn_ = 0UL;
+ rhs.capacity_ = 0UL;
+ rhs.v_ = nullptr;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::operator=( const Matrix<MT,SO2>& rhs )
+{
+ typedef TransExprTrait_<This> TT;
+ typedef CTransExprTrait_<This> CT;
+ typedef InvExprTrait_<This> IT;
+
+ if( IsSame<MT,TT>::value && (~rhs).isAliased( this ) ) {
+ transpose();
+ }
+ else if( IsSame<MT,CT>::value && (~rhs).isAliased( this ) ) {
+ ctranspose();
+ }
+ else if( !IsSame<MT,IT>::value && (~rhs).canAlias( this ) ) {
+ DynamicMatrix tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( (~rhs).rows(), (~rhs).columns(), false );
+ if( IsSparseMatrix<MT>::value )
+ reset();
+ smpAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::operator+=( const Matrix<MT,SO2>& rhs )
+{
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpAddAssign( *this, tmp );
+ }
+ else {
+ smpAddAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::operator-=( const Matrix<MT,SO2>& rhs )
+{
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpSubAssign( *this, tmp );
+ }
+ else {
+ smpSubAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::operator*=( const Matrix<MT,SO2>& rhs )
+{
+ if( (~rhs).rows() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ DynamicMatrix tmp( *this * (~rhs) );
+ swap( tmp );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, DynamicMatrix<Type,SO> >&
+ DynamicMatrix<Type,SO>::operator*=( Other rhs )
+{
+ smpAssign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, DynamicMatrix<Type,SO> >&
+ DynamicMatrix<Type,SO>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ smpAssign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline size_t DynamicMatrix<Type,SO>::rows() const noexcept
+{
+ return m_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline size_t DynamicMatrix<Type,SO>::columns() const noexcept
+{
+ return n_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the
+// total number of elements of a row/column. In case the storage order is set to \a rowMajor
+// the function returns the spacing between two rows, in case the storage flag is set to
+// \a columnMajor the function returns the spacing between two columns.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline size_t DynamicMatrix<Type,SO>::spacing() const noexcept
+{
+ return nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline size_t DynamicMatrix<Type,SO>::capacity() const noexcept
+{
+ return capacity_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline size_t DynamicMatrix<Type,SO>::capacity( size_t i ) const noexcept
+{
+ UNUSED_PARAMETER( i );
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return nn_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the dense matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline size_t DynamicMatrix<Type,SO>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ if( !isDefault( v_[i*nn_+j] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline size_t DynamicMatrix<Type,SO>::nonZeros( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t jend( i*nn_ + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=i*nn_; j<jend; ++j )
+ if( !isDefault( v_[j] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void DynamicMatrix<Type,SO>::reset()
+{
+ using blaze::clear;
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ clear( v_[i*nn_+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void DynamicMatrix<Type,SO>::reset( size_t i )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ for( size_t j=0UL; j<n_; ++j )
+ clear( v_[i*nn_+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the \f$ M \times N \f$ matrix.
+//
+// \return void
+//
+// After the clear() function, the size of the matrix is 0.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void DynamicMatrix<Type,SO>::clear()
+{
+ resize( 0UL, 0UL, false );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the matrix.
+//
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true. However, new matrix elements are not initialized!
+//
+// The following example illustrates the resize operation of a \f$ 2 \times 4 \f$ matrix to a
+// \f$ 4 \times 2 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & 4 \\
+ 5 & 6 & 7 & 8 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{2}{c}}
+ 1 & 2 \\
+ 5 & 6 \\
+ x & x \\
+ x & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+void DynamicMatrix<Type,SO>::resize( size_t m, size_t n, bool preserve )
+{
+ using blaze::min;
+
+ if( m == m_ && n == n_ ) return;
+
+ const size_t nn( adjustColumns( n ) );
+
+ if( preserve )
+ {
+ Type* BLAZE_RESTRICT v = allocate<Type>( m*nn );
+ const size_t min_m( min( m, m_ ) );
+ const size_t min_n( min( n, n_ ) );
+
+ for( size_t i=0UL; i<min_m; ++i ) {
+ transfer( v_+i*nn_, v_+i*nn_+min_n, v+i*nn );
+ }
+
+ std::swap( v_, v );
+ deallocate( v );
+ capacity_ = m*nn;
+ }
+ else if( m*nn > capacity_ ) {
+ Type* BLAZE_RESTRICT v = allocate<Type>( m*nn );
+ std::swap( v_, v );
+ deallocate( v );
+ capacity_ = m*nn;
+ }
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=0UL; i<m; ++i )
+ for( size_t j=n; j<nn; ++j )
+ v_[i*nn+j] = Type();
+ }
+
+ m_ = m;
+ n_ = n;
+ nn_ = nn;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Extending the size of the matrix.
+//
+// \param m Number of additional rows.
+// \param n Number of additional columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a m rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. However, new matrix elements are not
+// initialized!
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void DynamicMatrix<Type,SO>::extend( size_t m, size_t n, bool preserve )
+{
+ resize( m_+m, n_+n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the dense matrix.
+// \return void
+//
+// This function increases the capacity of the dense matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void DynamicMatrix<Type,SO>::reserve( size_t elements )
+{
+ if( elements > capacity_ )
+ {
+ // Allocating a new array
+ Type* BLAZE_RESTRICT tmp = allocate<Type>( elements );
+
+ // Initializing the new array
+ transfer( v_, v_+capacity_, tmp );
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=capacity_; i<elements; ++i )
+ tmp[i] = Type();
+ }
+
+ // Replacing the old array
+ std::swap( tmp, v_ );
+ deallocate( tmp );
+ capacity_ = elements;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::transpose()
+{
+ using std::swap;
+
+ const size_t block( BLOCK_SIZE );
+
+ if( m_ == n_ )
+ {
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( ii+block, m_ ) );
+ for( size_t jj=0UL; jj<=ii; jj+=block ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ const size_t jend( min( jj+block, n_, i ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ swap( v_[i*nn_+j], v_[j*nn_+i] );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ DynamicMatrix tmp( trans(*this) );
+ this->swap( tmp );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::ctranspose()
+{
+ const size_t block( BLOCK_SIZE );
+
+ if( m_ == n_ )
+ {
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( ii+block, m_ ) );
+ for( size_t jj=0UL; jj<ii; jj+=block ) {
+ const size_t jend( min( jj+block, n_ ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ cswap( v_[i*nn_+j], v_[j*nn_+i] );
+ }
+ }
+ }
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=ii; j<i; ++j ) {
+ cswap( v_[i*nn_+j], v_[j*nn_+i] );
+ }
+ conjugate( v_[i*nn_+i] );
+ }
+ }
+ }
+ else
+ {
+ DynamicMatrix tmp( ctrans(*this) );
+ swap( tmp );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the scalar value
+inline DynamicMatrix<Type,SO>& DynamicMatrix<Type,SO>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*nn_+j] *= scalar;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void DynamicMatrix<Type,SO>::swap( DynamicMatrix& m ) noexcept
+{
+ std::swap( m_ , m.m_ );
+ std::swap( n_ , m.n_ );
+ std::swap( nn_, m.nn_ );
+ std::swap( capacity_, m.capacity_ );
+ std::swap( v_ , m.v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Adjusting the number columns of the matrix according to its data type \a Type.
+//
+// \param minColumns The minimum necessary number of columns.
+// \return The adjusted number of columns.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline size_t DynamicMatrix<Type,SO>::adjustColumns( size_t minColumns ) const noexcept
+{
+ if( usePadding && IsVectorizable<Type>::value )
+ return nextMultiple<size_t>( minColumns, SIMDSIZE );
+ else return minColumns;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the dynamic matrix are intact.
+//
+// \return \a true in case the dynamic matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the dynamic matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline bool DynamicMatrix<Type,SO>::isIntact() const noexcept
+{
+ if( m_ * n_ > capacity_ )
+ return false;
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=n_; j<nn_; ++j ) {
+ if( v_[i*nn_+j] != Type() )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool DynamicMatrix<Type,SO>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool DynamicMatrix<Type,SO>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline bool DynamicMatrix<Type,SO>::isAligned() const noexcept
+{
+ return ( usePadding || columns() % SIMDSIZE == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline bool DynamicMatrix<Type,SO>::canSMPAssign() const noexcept
+{
+ return ( rows() > SMP_DMATASSIGN_THRESHOLD );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller then the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,SO>::SIMDType
+ DynamicMatrix<Type,SO>::load( size_t i, size_t j ) const noexcept
+{
+ if( usePadding )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,SO>::SIMDType
+ DynamicMatrix<Type,SO>::loada( size_t i, size_t j ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i*nn_+j ), "Invalid alignment detected" );
+
+ return loada( v_+i*nn_+j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,SO>::SIMDType
+ DynamicMatrix<Type,SO>::loadu( size_t i, size_t j ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
+
+ return loadu( v_+i*nn_+j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ DynamicMatrix<Type,SO>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( usePadding )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ DynamicMatrix<Type,SO>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i*nn_+j ), "Invalid alignment detected" );
+
+ storea( v_+i*nn_+j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ DynamicMatrix<Type,SO>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
+
+ storeu( v_+i*nn_+j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the column index (in case of a
+// row-major matrix) or the row index (in case of a column-major matrix) must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ DynamicMatrix<Type,SO>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i*nn_+j ), "Invalid alignment detected" );
+
+ stream( v_+i*nn_+j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename DynamicMatrix<Type,SO>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ DynamicMatrix<Type,SO>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ v_[i*nn_+j ] = (~rhs)(i,j );
+ v_[i*nn_+j+1UL] = (~rhs)(i,j+1UL);
+ }
+ if( jpos < n_ ) {
+ v_[i*nn_+jpos] = (~rhs)(i,jpos);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename DynamicMatrix<Type,SO>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ DynamicMatrix<Type,SO>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ const size_t jpos( ( remainder )?( n_ & size_t(-SIMDSIZE) ):( n_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ if( usePadding && useStreaming &&
+ ( m_*n_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) && !(~rhs).isAliased( this ) )
+ {
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+ Iterator left( begin(i) );
+ ConstIterator_<MT> right( (~rhs).begin(i) );
+
+ for( ; j<jpos; j+=SIMDSIZE, left+=SIMDSIZE, right+=SIMDSIZE ) {
+ left.stream( right.load() );
+ }
+ for( ; remainder && j<n_; ++j, ++left, ++right ) {
+ *left = *right;
+ }
+ }
+ }
+ else
+ {
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+ Iterator left( begin(i) );
+ ConstIterator_<MT> right( (~rhs).begin(i) );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( right.load() ); left+=SIMDSIZE, right+=SIMDSIZE;
+ }
+ for( ; remainder && j<n_; ++j ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline void DynamicMatrix<Type,SO>::assign( const DenseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( m_, ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( n_, jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ v_[i*nn_+j] = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,SO>::assign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*nn_+element->index()] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,SO>::assign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*nn_+j] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename DynamicMatrix<Type,SO>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ DynamicMatrix<Type,SO>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[i*nn_+i] += (~rhs)(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ size_t j( jbegin );
+
+ for( ; (j+2UL) <= jend; j+=2UL ) {
+ v_[i*nn_+j ] += (~rhs)(i,j );
+ v_[i*nn_+j+1UL] += (~rhs)(i,j+1UL);
+ }
+ if( j < jend ) {
+ v_[i*nn_+j] += (~rhs)(i,j);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename DynamicMatrix<Type,SO>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ DynamicMatrix<Type,SO>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+ Iterator left( begin(i) + jbegin );
+ ConstIterator_<MT> right( (~rhs).begin(i) + jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<jend; ++j ) {
+ *left += *right; ++left; ++right;
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline void DynamicMatrix<Type,SO>::addAssign( const DenseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( m_, ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block )
+ {
+ if( IsLower<MT>::value && ii < jj ) break;
+ if( IsUpper<MT>::value && ii > jj ) continue;
+
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( max( ( IsStrictlyUpper<MT>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( min( ( IsStrictlyLower<MT>::value ? i : i+1UL ), n_, jj+block ) )
+ :( min( n_, jj+block ) ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ v_[i*nn_+j] += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,SO>::addAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*nn_+element->index()] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,SO>::addAssign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*nn_+j] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename DynamicMatrix<Type,SO>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ DynamicMatrix<Type,SO>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[i*nn_+i] -= (~rhs)(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ size_t j( jbegin );
+
+ for( ; (j+2UL) <= jend; j+=2UL ) {
+ v_[i*nn_+j ] -= (~rhs)(i,j );
+ v_[i*nn_+j+1UL] -= (~rhs)(i,j+1UL);
+ }
+ if( j < jend ) {
+ v_[i*nn_+j] -= (~rhs)(i,j);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename DynamicMatrix<Type,SO>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ DynamicMatrix<Type,SO>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+ Iterator left( begin(i) + jbegin );
+ ConstIterator_<MT> right( (~rhs).begin(i) + jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<jend; ++j ) {
+ *left -= *right; ++left; ++right;
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side dense matrix
+inline void DynamicMatrix<Type,SO>::subAssign( const DenseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( m_, ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block )
+ {
+ if( IsLower<MT>::value && ii < jj ) break;
+ if( IsUpper<MT>::value && ii > jj ) continue;
+
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( max( ( IsStrictlyUpper<MT>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( min( ( IsStrictlyLower<MT>::value ? i : i+1UL ), n_, jj+block ) )
+ :( min( n_, jj+block ) ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ v_[i*nn_+j] -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,SO>::subAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*nn_+element->index()] -= element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,SO>::subAssign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*nn_+j] -= element->value();
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of DynamicMatrix for column-major matrices.
+// \ingroup dynamic_matrix
+//
+// This specialization of DynamicMatrix adapts the class template to the requirements of
+// column-major matrices.
+*/
+template< typename Type > // Data type of the matrix
+class DynamicMatrix<Type,true> : public DenseMatrix< DynamicMatrix<Type,true>, true >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DynamicMatrix<Type,true> This; //!< Type of this DynamicMatrix instance.
+ typedef DenseMatrix<This,true> BaseType; //!< Base type of this DynamicMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef DynamicMatrix<Type,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef DynamicMatrix<Type,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Type* Pointer; //!< Pointer to a non-constant matrix value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant matrix value.
+
+ typedef DenseIterator<Type,usePadding> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,usePadding> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a DynamicMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef DynamicMatrix<ET,true> Other; //!< The type of the other DynamicMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the element type of the matrix is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline DynamicMatrix() noexcept;
+ explicit inline DynamicMatrix( size_t m, size_t n );
+ explicit inline DynamicMatrix( size_t m, size_t n, const Type& init );
+ explicit inline DynamicMatrix( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other > explicit inline DynamicMatrix( size_t m, size_t n, const Other* array );
+
+ template< typename Other, size_t M, size_t N >
+ explicit inline DynamicMatrix( const Other (&array)[M][N] );
+
+ inline DynamicMatrix( const DynamicMatrix& m );
+ inline DynamicMatrix( DynamicMatrix&& m );
+ template< typename MT, bool SO > inline DynamicMatrix( const Matrix<MT,SO>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~DynamicMatrix();
+ //@}
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t j ) noexcept;
+ inline ConstPointer data ( size_t j ) const noexcept;
+ inline Iterator begin ( size_t j ) noexcept;
+ inline ConstIterator begin ( size_t j ) const noexcept;
+ inline ConstIterator cbegin( size_t j ) const noexcept;
+ inline Iterator end ( size_t j ) noexcept;
+ inline ConstIterator end ( size_t j ) const noexcept;
+ inline ConstIterator cend ( size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline DynamicMatrix& operator=( const Type& rhs );
+ inline DynamicMatrix& operator=( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other, size_t M, size_t N >
+ inline DynamicMatrix& operator=( const Other (&array)[M][N] );
+
+ inline DynamicMatrix& operator=( const DynamicMatrix& rhs );
+ inline DynamicMatrix& operator=( DynamicMatrix&& rhs );
+
+ template< typename MT, bool SO > inline DynamicMatrix& operator= ( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline DynamicMatrix& operator+=( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline DynamicMatrix& operator-=( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline DynamicMatrix& operator*=( const Matrix<MT,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, DynamicMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, DynamicMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t j ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t j ) const;
+ inline void reset();
+ inline void reset( size_t j );
+ inline void clear();
+ void resize ( size_t m, size_t n, bool preserve=true );
+ inline void extend ( size_t m, size_t n, bool preserve=true );
+ inline void reserve( size_t elements );
+ inline DynamicMatrix& transpose();
+ inline DynamicMatrix& ctranspose();
+ template< typename Other > inline DynamicMatrix& scale( const Other& scalar );
+ inline void swap( DynamicMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDAdd< Type, ElementType_<MT> >::value &&
+ !IsDiagonal<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDSub< Type, ElementType_<MT> >::value &&
+ !IsDiagonal<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT >
+ inline DisableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT > inline void assign( const DenseMatrix<MT,false>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,false>& rhs );
+
+ template< typename MT >
+ inline DisableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT > inline void addAssign( const DenseMatrix<MT,false>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,false>& rhs );
+
+ template< typename MT >
+ inline DisableIf_<VectorizedSubAssign<MT> > subAssign ( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT >
+ inline EnableIf_<VectorizedSubAssign<MT> > subAssign ( const DenseMatrix<MT,true>& rhs );
+
+ template< typename MT > inline void subAssign( const DenseMatrix<MT,false>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t adjustRows( size_t minRows ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t m_; //!< The current number of rows of the matrix.
+ size_t mm_; //!< The alignment adjusted number of rows.
+ size_t n_; //!< The current number of columns of the matrix.
+ size_t capacity_; //!< The maximum capacity of the matrix.
+ Type* BLAZE_RESTRICT v_; //!< The dynamically allocated matrix elements.
+ /*!< Access to the matrix elements is gained via the function call
+ operator. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for DynamicMatrix.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>::DynamicMatrix() noexcept
+ : m_ ( 0UL ) // The current number of rows of the matrix
+ , mm_ ( 0UL ) // The alignment adjusted number of rows
+ , n_ ( 0UL ) // The current number of columns of the matrix
+ , capacity_( 0UL ) // The maximum capacity of the matrix
+ , v_ ( nullptr ) // The matrix elements
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$. No element initialization is performed!
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+//
+// \note This constructor is only responsible to allocate the required dynamic memory. No
+// element initialization is performed!
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>::DynamicMatrix( size_t m, size_t n )
+ : m_ ( m ) // The current number of rows of the matrix
+ , mm_ ( adjustRows( m ) ) // The alignment adjusted number of rows
+ , n_ ( n ) // The current number of columns of the matrix
+ , capacity_( mm_*n_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ if( IsVectorizable<Type>::value ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=m_; i<mm_; ++i ) {
+ v_[i+j*mm_] = Type();
+ }
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a homogenous initialization of all \f$ m \times n \f$ matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param init The initial value of the matrix elements.
+//
+// All matrix elements are initialized with the specified value.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>::DynamicMatrix( size_t m, size_t n, const Type& init )
+ : m_ ( m ) // The current number of rows of the matrix
+ , mm_ ( adjustRows( m ) ) // The alignment adjusted number of rows
+ , n_ ( n ) // The current number of columns of the matrix
+ , capacity_( mm_*n_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*mm_] = init;
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=m_; i<mm_; ++i )
+ v_[i+j*mm_] = Type();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+//
+// This constructor provides the option to explicitly initialize the elements of the matrix by
+// means of an initializer list:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<int,columnMajor> A{ { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all its elements are
+// initialized by the values of the given initializer list. Missing values are initialized as
+// default (as e.g. the value 6 in the example).
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>::DynamicMatrix( initializer_list< initializer_list<Type> > list )
+ : m_ ( list.size() ) // The current number of rows of the matrix
+ , mm_ ( adjustRows( m_ ) ) // The alignment adjusted number of rows
+ , n_ ( determineColumns( list ) ) // The current number of columns of the matrix
+ , capacity_( mm_*n_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ v_[i+j*mm_] = element;
+ ++j;
+ }
+ for( ; j<n_; ++j ) {
+ v_[i+j*mm_] = Type();
+ }
+ ++i;
+ }
+
+ BLAZE_INTERNAL_ASSERT( i == m_, "Invalid number of elements detected" );
+
+ if( IsVectorizable<Type>::value ) {
+ for( ; i<mm_; ++i ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ v_[i+j*mm_] = Type();
+ }
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param array Dynamic array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a dynamic array:
+
+ \code
+ using blaze::columnMajor;
+
+ int* array = new int[20];
+ // ... Initialization of the dynamic array
+ blaze::DynamicMatrix<int,columnMajor> v( array, 5UL, 4UL );
+ delete[] array;
+ \endcode
+
+// The matrix is sized according to the given size of the array and initialized with the values
+// from the given array. Note that it is expected that the given \a array has at least \a m by
+// \a n elements. Providing an array with less elements results in undefined behavior!
+*/
+template< typename Type > // Data type of the matrix
+template< typename Other > // Data type of the initialization array
+inline DynamicMatrix<Type,true>::DynamicMatrix( size_t m, size_t n, const Other* array )
+ : m_ ( m ) // The current number of rows of the matrix
+ , mm_ ( adjustRows( m ) ) // The alignment adjusted number of rows
+ , n_ ( n ) // The current number of columns of the matrix
+ , capacity_( mm_*n_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ for( size_t j=0UL; j<n; ++j ) {
+ for( size_t i=0UL; i<m; ++i )
+ v_[i+j*mm_] = array[i+j*m];
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=m; i<mm_; ++i )
+ v_[i+j*mm_] = Type();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a static array:
+
+ \code
+ using blaze::columnMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::DynamicMatrix<int,columnMajor> A( init );
+ \endcode
+
+// The matrix is sized according to the size of the array and initialized with the values from
+// the given array. Missing values are initialized with default values (as e.g. the value 6 in
+// the example).
+*/
+template< typename Type > // Data type of the matrix
+template< typename Other // Data type of the initialization array
+ , size_t M // Number of rows of the initialization array
+ , size_t N > // Number of columns of the initialization array
+inline DynamicMatrix<Type,true>::DynamicMatrix( const Other (&array)[M][N] )
+ : m_ ( M ) // The current number of rows of the matrix
+ , mm_ ( adjustRows( M ) ) // The alignment adjusted number of rows
+ , n_ ( N ) // The current number of columns of the matrix
+ , capacity_( mm_*n_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*mm_] = array[i][j];
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=M; i<mm_; ++i )
+ v_[i+j*mm_] = Type();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for DynamicMatrix.
+//
+// \param m Matrix to be copied.
+//
+// The copy constructor is explicitly defined due to the required dynamic memory management
+// and in order to enable/facilitate NRV optimization.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>::DynamicMatrix( const DynamicMatrix& m )
+ : m_ ( m.m_ ) // The current number of rows of the matrix
+ , mm_ ( m.mm_ ) // The alignment adjusted number of rows
+ , n_ ( m.n_ ) // The current number of columns of the matrix
+ , capacity_( mm_*n_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ BLAZE_INTERNAL_ASSERT( capacity_ <= m.capacity_, "Invalid capacity estimation" );
+
+ for( size_t i=0UL; i<capacity_; ++i )
+ v_[i] = m.v_[i];
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for DynamicMatrix.
+//
+// \param m The matrix to be moved into this instance.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>::DynamicMatrix( DynamicMatrix&& m )
+ : m_ ( m.m_ ) // The current number of rows of the matrix
+ , mm_ ( m.mm_ ) // The alignment adjusted number of rows
+ , n_ ( m.n_ ) // The current number of columns of the matrix
+ , capacity_( m.capacity_ ) // The maximum capacity of the matrix
+ , v_ ( m.v_ ) // The matrix elements
+{
+ m.m_ = 0UL;
+ m.mm_ = 0UL;
+ m.n_ = 0UL;
+ m.capacity_ = 0UL;
+ m.v_ = nullptr;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT // Type of the foreign matrix
+ , bool SO > // Storage order of the foreign matrix
+inline DynamicMatrix<Type,true>::DynamicMatrix( const Matrix<MT,SO>& m )
+ : m_ ( (~m).rows() ) // The current number of rows of the matrix
+ , mm_ ( adjustRows( m_ ) ) // The alignment adjusted number of rows
+ , n_ ( (~m).columns() ) // The current number of columns of the matrix
+ , capacity_( mm_*n_ ) // The maximum capacity of the matrix
+ , v_ ( allocate<Type>( capacity_ ) ) // The matrix elements
+{
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=( IsSparseMatrix<MT>::value ? 0UL : m_ );
+ i<( IsVectorizable<Type>::value ? mm_ : m_ ); ++i ) {
+ v_[i+j*mm_] = Type();
+ }
+ }
+
+ smpAssign( *this, ~m );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The destructor for DynamicMatrix.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>::~DynamicMatrix()
+{
+ deallocate( v_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::Reference
+ DynamicMatrix<Type,true>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
+ return v_[i+j*mm_];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::ConstReference
+ DynamicMatrix<Type,true>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
+ return v_[i+j*mm_];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::Reference
+ DynamicMatrix<Type,true>::at( size_t i, size_t j )
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::ConstReference
+ DynamicMatrix<Type,true>::at( size_t i, size_t j ) const
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a column are given by the \c columns() member functions, the total number
+// of elements including padding is given by the \c spacing() member function.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::Pointer
+ DynamicMatrix<Type,true>::data() noexcept
+{
+ return v_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a column are given by the \c columns() member functions, the total number
+// of elements including padding is given by the \c spacing() member function.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::ConstPointer
+ DynamicMatrix<Type,true>::data() const noexcept
+{
+ return v_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::Pointer
+ DynamicMatrix<Type,true>::data( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return v_ + j*mm_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::ConstPointer
+ DynamicMatrix<Type,true>::data( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return v_ + j*mm_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::Iterator
+ DynamicMatrix<Type,true>::begin( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return Iterator( v_ + j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::ConstIterator
+ DynamicMatrix<Type,true>::begin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::ConstIterator
+ DynamicMatrix<Type,true>::cbegin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::Iterator
+ DynamicMatrix<Type,true>::end( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return Iterator( v_ + j*mm_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::ConstIterator
+ DynamicMatrix<Type,true>::end( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*mm_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline typename DynamicMatrix<Type,true>::ConstIterator
+ DynamicMatrix<Type,true>::cend( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*mm_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all matrix elements.
+//
+// \param rhs Scalar value to be assigned to all matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::operator=( const Type& rhs )
+{
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*mm_] = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+//
+// This assignment operator offers the option to directly assign to all elements of the matrix
+// by means of an initializer list:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<int,columnMajor> A;
+ A = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix is resized according to the given initializer list and all its elements are
+// assigned the values from the given initializer list. Missing values are initialized as
+// default (as e.g. the value 6 in the example).
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>&
+ DynamicMatrix<Type,true>::operator=( initializer_list< initializer_list<Type> > list )
+{
+ resize( list.size(), determineColumns( list ), false );
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ v_[i+j*mm_] = element;
+ ++j;
+ }
+ for( ; j<n_; ++j ) {
+ v_[i+j*mm_] = Type();
+ }
+ ++i;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+//
+// This assignment operator offers the option to directly set all elements of the matrix:
+
+ \code
+ using blaze::columnMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::DynamicMatrix<int,columnMajor> A;
+ A = init;
+ \endcode
+
+// The matrix is resized according to the size of the array and assigned the values of the given
+// array. Missing values are initialized with default values (as e.g. the value 6 in the example).
+*/
+template< typename Type > // Data type of the matrix
+template< typename Other // Data type of the initialization array
+ , size_t M // Number of rows of the initialization array
+ , size_t N > // Number of columns of the initialization array
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::operator=( const Other (&array)[M][N] )
+{
+ resize( M, N, false );
+
+ for( size_t j=0UL; j<N; ++j )
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*mm_] = array[i][j];
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for DynamicMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::operator=( const DynamicMatrix& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ resize( rhs.m_, rhs.n_, false );
+ smpAssign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for DynamicMatrix.
+//
+// \param rhs The matrix to be moved into this instance.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::operator=( DynamicMatrix&& rhs )
+{
+ deallocate( v_ );
+
+ m_ = rhs.m_;
+ mm_ = rhs.mm_;
+ n_ = rhs.n_;
+ capacity_ = rhs.capacity_;
+ v_ = rhs.v_;
+
+ rhs.m_ = 0UL;
+ rhs.mm_ = 0UL;
+ rhs.n_ = 0UL;
+ rhs.capacity_ = 0UL;
+ rhs.v_ = nullptr;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::operator=( const Matrix<MT,SO>& rhs )
+{
+ typedef TransExprTrait_<This> TT;
+ typedef CTransExprTrait_<This> CT;
+ typedef InvExprTrait_<This> IT;
+
+ if( IsSame<MT,TT>::value && (~rhs).isAliased( this ) ) {
+ transpose();
+ }
+ else if( IsSame<MT,CT>::value && (~rhs).isAliased( this ) ) {
+ ctranspose();
+ }
+ else if( !IsSame<MT,IT>::value && (~rhs).canAlias( this ) ) {
+ DynamicMatrix tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( (~rhs).rows(), (~rhs).columns(), false );
+ if( IsSparseMatrix<MT>::value )
+ reset();
+ smpAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::operator+=( const Matrix<MT,SO>& rhs )
+{
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpAddAssign( *this, tmp );
+ }
+ else {
+ smpAddAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::operator-=( const Matrix<MT,SO>& rhs )
+{
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ smpSubAssign( *this, tmp );
+ }
+ else {
+ smpSubAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::operator*=( const Matrix<MT,SO>& rhs )
+{
+ if( (~rhs).rows() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ DynamicMatrix tmp( *this * (~rhs) );
+ swap( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename Type > // Data type of the matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, DynamicMatrix<Type,true> >&
+ DynamicMatrix<Type,true>::operator*=( Other rhs )
+{
+ smpAssign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename Type > // Data type of the matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, DynamicMatrix<Type,true> >&
+ DynamicMatrix<Type,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ smpAssign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline size_t DynamicMatrix<Type,true>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline size_t DynamicMatrix<Type,true>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two columns.
+//
+// \return The spacing between the beginning of two columns.
+//
+// This function returns the spacing between the beginning of two column, i.e. the total number
+// of elements of a column.
+*/
+template< typename Type > // Data type of the matrix
+inline size_t DynamicMatrix<Type,true>::spacing() const noexcept
+{
+ return mm_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline size_t DynamicMatrix<Type,true>::capacity() const noexcept
+{
+ return capacity_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified column.
+//
+// \param j The index of the column.
+// \return The current capacity of column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline size_t DynamicMatrix<Type,true>::capacity( size_t j ) const noexcept
+{
+ UNUSED_PARAMETER( j );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return mm_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the dense matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline size_t DynamicMatrix<Type,true>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ if( !isDefault( v_[i+j*mm_] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified column.
+//
+// \param j The index of the column.
+// \return The number of non-zero elements of column \a j.
+*/
+template< typename Type > // Data type of the matrix
+inline size_t DynamicMatrix<Type,true>::nonZeros( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t iend( j*mm_ + m_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=j*mm_; i<iend; ++i )
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type > // Data type of the matrix
+inline void DynamicMatrix<Type,true>::reset()
+{
+ using blaze::clear;
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ clear( v_[i+j*mm_] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified column to the default initial values.
+//
+// \param j The index of the column.
+// \return void
+//
+// This function reset the values in the specified column to their default value. Note that
+// the capacity of the column remains unchanged.
+*/
+template< typename Type > // Data type of the matrix
+inline void DynamicMatrix<Type,true>::reset( size_t j )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ for( size_t i=0UL; i<m_; ++i )
+ clear( v_[i+j*mm_] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the \f$ M \times N \f$ matrix.
+//
+// \return void
+//
+// After the clear() function, the size of the matrix is 0.
+*/
+template< typename Type > // Data type of the matrix
+inline void DynamicMatrix<Type,true>::clear()
+{
+ resize( 0UL, 0UL, false );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the matrix.
+//
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true. However, new matrix elements are not initialized!
+//
+// The following example illustrates the resize operation of a \f$ 2 \times 4 \f$ matrix to a
+// \f$ 4 \times 2 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & 4 \\
+ 5 & 6 & 7 & 8 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{2}{c}}
+ 1 & 2 \\
+ 5 & 6 \\
+ x & x \\
+ x & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename Type > // Data type of the matrix
+void DynamicMatrix<Type,true>::resize( size_t m, size_t n, bool preserve )
+{
+ using blaze::min;
+
+ if( m == m_ && n == n_ ) return;
+
+ const size_t mm( adjustRows( m ) );
+
+ if( preserve )
+ {
+ Type* BLAZE_RESTRICT v = allocate<Type>( mm*n );
+ const size_t min_m( min( m, m_ ) );
+ const size_t min_n( min( n, n_ ) );
+
+ for( size_t j=0UL; j<min_n; ++j ) {
+ transfer( v_+j*mm_, v_+min_m+j*mm_, v+j*mm );
+ }
+
+ std::swap( v_, v );
+ deallocate( v );
+ capacity_ = mm*n;
+ }
+ else if( mm*n > capacity_ ) {
+ Type* BLAZE_RESTRICT v = allocate<Type>( mm*n );
+ std::swap( v_, v );
+ deallocate( v );
+ capacity_ = mm*n;
+ }
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t j=0UL; j<n; ++j )
+ for( size_t i=m; i<mm; ++i )
+ v_[i+j*mm] = Type();
+ }
+
+ m_ = m;
+ mm_ = mm;
+ n_ = n;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param m Number of additional rows.
+// \param n Number of additional columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a m rows and \a n columns. During this operation,
+// new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
+// this function potentially changes all matrix elements. In order to preserve the old matrix
+// values, the \a preserve flag can be set to \a true. However, new matrix elements are not
+// initialized!
+*/
+template< typename Type > // Data type of the matrix
+inline void DynamicMatrix<Type,true>::extend( size_t m, size_t n, bool preserve )
+{
+ resize( m_+m, n_+n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the matrix.
+//
+// \param elements The new minimum capacity of the dense matrix.
+// \return void
+//
+// This function increases the capacity of the dense matrix to at least \a elements elements.
+// The current values of the matrix elements are preserved.
+*/
+template< typename Type > // Data type of the matrix
+inline void DynamicMatrix<Type,true>::reserve( size_t elements )
+{
+ if( elements > capacity_ )
+ {
+ // Allocating a new array
+ Type* BLAZE_RESTRICT tmp = allocate<Type>( elements );
+
+ // Initializing the new array
+ transfer( v_, v_+capacity_, tmp );
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=capacity_; i<elements; ++i )
+ tmp[i] = Type();
+ }
+
+ // Replacing the old array
+ std::swap( tmp, v_ );
+ deallocate( tmp );
+ capacity_ = elements;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::transpose()
+{
+ using std::swap;
+
+ const size_t block( BLOCK_SIZE );
+
+ if( m_ == n_ )
+ {
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( jj+block, n_ ) );
+ for( size_t ii=0UL; ii<=jj; ii+=block ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ const size_t iend( min( ii+block, m_, j ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ swap( v_[i+j*mm_], v_[j+i*mm_] );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ DynamicMatrix tmp( trans(*this) );
+ this->swap( tmp );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename Type > // Data type of the matrix
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::ctranspose()
+{
+ const size_t block( BLOCK_SIZE );
+
+ if( m_ == n_ )
+ {
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( jj+block, n_ ) );
+ for( size_t ii=0UL; ii<jj; ii+=block ) {
+ const size_t iend( min( ii+block, m_ ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ cswap( v_[i+j*mm_], v_[j+i*mm_] );
+ }
+ }
+ }
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=jj; i<j; ++i ) {
+ cswap( v_[i+j*mm_], v_[j+i*mm_] );
+ }
+ conjugate( v_[j+j*mm_] );
+ }
+ }
+ }
+ else
+ {
+ DynamicMatrix tmp( ctrans(*this) );
+ this->swap( tmp );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename Type > // Data type of the matrix
+template< typename Other > // Data type of the scalar value
+inline DynamicMatrix<Type,true>& DynamicMatrix<Type,true>::scale( const Other& scalar )
+{
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*mm_] *= scalar;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename Type > // Data type of the matrix
+inline void DynamicMatrix<Type,true>::swap( DynamicMatrix& m ) noexcept
+{
+ std::swap( m_ , m.m_ );
+ std::swap( mm_, m.mm_ );
+ std::swap( n_ , m.n_ );
+ std::swap( capacity_, m.capacity_ );
+ std::swap( v_ , m.v_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Adjusting the number rows of the matrix according to its data type \a Type.
+//
+// \param minRows The minimum necessary number of rows.
+// \return The adjusted number of rows.
+*/
+template< typename Type > // Data type of the matrix
+inline size_t DynamicMatrix<Type,true>::adjustRows( size_t minRows ) const noexcept
+{
+ if( usePadding && IsVectorizable<Type>::value )
+ return nextMultiple<size_t>( minRows, SIMDSIZE );
+ else return minRows;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the dynamic matrix are intact.
+//
+// \return \a true in case the dynamic matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the dynamic matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type > // Data type of the matrix
+inline bool DynamicMatrix<Type,true>::isIntact() const noexcept
+{
+ if( m_ * n_ > capacity_ )
+ return false;
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=m_; i<mm_; ++i ) {
+ if( v_[i+j*mm_] != Type() )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type > // Data type of the matrix
+template< typename Other > // Data type of the foreign expression
+inline bool DynamicMatrix<Type,true>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type > // Data type of the matrix
+template< typename Other > // Data type of the foreign expression
+inline bool DynamicMatrix<Type,true>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each column of the matrix are guaranteed to conform to
+// the alignment restrictions of the element type \a Type.
+*/
+template< typename Type > // Data type of the matrix
+inline bool DynamicMatrix<Type,true>::isAligned() const noexcept
+{
+ return ( usePadding || rows() % SIMDSIZE == 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename Type > // Data type of the matrix
+inline bool DynamicMatrix<Type,true>::canSMPAssign() const noexcept
+{
+ return ( columns() > SMP_DMATASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the row index must be a multiple of the number of values inside
+// the SIMD element. This function must \b NOT be called explicitly! It is used internally
+// for the performance optimized evaluation of expression templates. Calling this function
+// explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type > // Data type of the matrix
+BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,true>::SIMDType
+ DynamicMatrix<Type,true>::load( size_t i, size_t j ) const noexcept
+{
+ if( usePadding )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type > // Data type of the matrix
+BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,true>::SIMDType
+ DynamicMatrix<Type,true>::loada( size_t i, size_t j ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i+j*mm_ ), "Invalid alignment detected" );
+
+ return loada( v_+i+j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type > // Data type of the matrix
+BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,true>::SIMDType
+ DynamicMatrix<Type,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+
+ return loadu( v_+i+j*mm_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller then the number
+// of columns. Additionally, the row index must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type > // Data type of the matrix
+BLAZE_ALWAYS_INLINE void
+ DynamicMatrix<Type,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( usePadding )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type > // Data type of the matrix
+BLAZE_ALWAYS_INLINE void
+ DynamicMatrix<Type,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i+j*mm_ ), "Invalid alignment detected" );
+
+ storea( v_+i+j*mm_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type > // Data type of the matrix
+BLAZE_ALWAYS_INLINE void
+ DynamicMatrix<Type,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+
+ storeu( v_+i+j*mm_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the row index must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename Type > // Data type of the matrix
+BLAZE_ALWAYS_INLINE void
+ DynamicMatrix<Type,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i+j*mm_ ), "Invalid alignment detected" );
+
+ stream( v_+i+j*mm_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename DynamicMatrix<Type,true>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ DynamicMatrix<Type,true>::assign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i +j*mm_] = (~rhs)(i ,j);
+ v_[i+1UL+j*mm_] = (~rhs)(i+1UL,j);
+ }
+ if( ipos < m_ ) {
+ v_[ipos+j*mm_] = (~rhs)(ipos,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename DynamicMatrix<Type,true>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ DynamicMatrix<Type,true>::assign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ const size_t ipos( ( remainder )?( m_ & size_t(-SIMDSIZE) ):( m_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ if( usePadding && useStreaming &&
+ ( m_*n_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) && !(~rhs).isAliased( this ) )
+ {
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+ Iterator left( begin(j) );
+ ConstIterator_<MT> right( (~rhs).begin(j) );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<m_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+ else
+ {
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+ Iterator left( begin(j) );
+ ConstIterator_<MT> right( (~rhs).begin(j) );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<m_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline void DynamicMatrix<Type,true>::assign( const DenseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( n_, jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( min( m_, ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ v_[i+j*mm_] = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,true>::assign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*mm_] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,true>::assign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*mm_] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename DynamicMatrix<Type,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ DynamicMatrix<Type,true>::addAssign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[j+j*mm_] += (~rhs)(j,j);
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ size_t i( ibegin );
+
+ for( ; (i+2UL) <= iend; i+=2UL ) {
+ v_[i +j*mm_] += (~rhs)(i ,j);
+ v_[i+1UL+j*mm_] += (~rhs)(i+1UL,j);
+ }
+ if( i < iend ) {
+ v_[i+j*mm_] += (~rhs)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename DynamicMatrix<Type,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ DynamicMatrix<Type,true>::addAssign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+ Iterator left( begin(j) + ibegin );
+ ConstIterator_<MT> right( (~rhs).begin(j) + ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<iend; ++i ) {
+ *left += *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline void DynamicMatrix<Type,true>::addAssign( const DenseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( n_, jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block )
+ {
+ if( IsLower<MT>::value && ii < jj ) continue;
+ if( IsUpper<MT>::value && ii > jj ) break;
+
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( max( ( IsStrictlyLower<MT>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( min( ( IsStrictlyUpper<MT>::value ? j : j+1UL ), m_, ii+block ) )
+ :( min( m_, ii+block ) ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ v_[i+j*mm_] += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,true>::addAssign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*mm_] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,true>::addAssign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*mm_] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline DisableIf_<typename DynamicMatrix<Type,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ DynamicMatrix<Type,true>::subAssign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[j+j*mm_] -= (~rhs)(j,j);
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ size_t i( ibegin );
+
+ for( ; (i+2UL) <= iend; i+=2UL ) {
+ v_[i +j*mm_] -= (~rhs)(i ,j);
+ v_[i+1+j*mm_] -= (~rhs)(i+1,j);
+ }
+ if( i < iend ) {
+ v_[i+j*mm_] -= (~rhs)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline EnableIf_<typename DynamicMatrix<Type,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ DynamicMatrix<Type,true>::subAssign( const DenseMatrix<MT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+ Iterator left( begin(j) + ibegin );
+ ConstIterator_<MT> right( (~rhs).begin(j) + ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<iend; ++i ) {
+ *left -= *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side dense matrix
+inline void DynamicMatrix<Type,true>::subAssign( const DenseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( min( n_, jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block )
+ {
+ if( IsLower<MT>::value && ii < jj ) continue;
+ if( IsUpper<MT>::value && ii > jj ) break;
+
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( max( ( IsStrictlyLower<MT>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( min( ( IsStrictlyUpper<MT>::value ? j : j+1UL ), m_, ii+block ) )
+ :( min( m_, ii+block ) ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ v_[i+j*mm_] -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,true>::subAssign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*mm_] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the matrix
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void DynamicMatrix<Type,true>::subAssign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*mm_] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// DYNAMICMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DynamicMatrix operators */
+//@{
+template< typename Type, bool SO >
+inline void reset( DynamicMatrix<Type,SO>& m );
+
+template< typename Type, bool SO >
+inline void reset( DynamicMatrix<Type,SO>& m, size_t i );
+
+template< typename Type, bool SO >
+inline void clear( DynamicMatrix<Type,SO>& m );
+
+template< typename Type, bool SO >
+inline bool isDefault( const DynamicMatrix<Type,SO>& m );
+
+template< typename Type, bool SO >
+inline bool isIntact( const DynamicMatrix<Type,SO>& m ) noexcept;
+
+template< typename Type, bool SO >
+inline void swap( DynamicMatrix<Type,SO>& a, DynamicMatrix<Type,SO>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given dynamic matrix.
+// \ingroup dynamic_matrix
+//
+// \param m The matrix to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void reset( DynamicMatrix<Type,SO>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column of the given dynamic matrix.
+// \ingroup dynamic_matrix
+//
+// \param m The matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given dynamic matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void reset( DynamicMatrix<Type,SO>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given dynamic matrix.
+// \ingroup dynamic_matrix
+//
+// \param m The matrix to be cleared.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void clear( DynamicMatrix<Type,SO>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given dynamic matrix is in default state.
+// \ingroup dynamic_matrix
+//
+// \param m The matrix to be tested for its default state.
+// \return \a true in case the given matrix's rows and columns are zero, \a false otherwise.
+//
+// This function checks whether the dynamic matrix is in default (constructed) state, i.e. if
+// it's number of rows and columns is 0. In case it is in default state, the function returns
+// \a true, else it will return \a false. The following example demonstrates the use of the
+// \a isDefault() function:
+
+ \code
+ blaze::DynamicMatrix<int> A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline bool isDefault( const DynamicMatrix<Type,SO>& m )
+{
+ return ( m.rows() == 0UL && m.columns() == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given dynamic matrix are intact.
+// \ingroup dynamic_matrix
+//
+// \param m The dynamic matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the dynamic matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::DynamicMatrix<int> A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline bool isIntact( const DynamicMatrix<Type,SO>& m ) noexcept
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two dynamic matrices.
+// \ingroup dynamic_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+inline void swap( DynamicMatrix<Type,SO>& a, DynamicMatrix<Type,SO>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool SO >
+struct HasConstDataAccess< DynamicMatrix<T,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool SO >
+struct HasMutableDataAccess< DynamicMatrix<T,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool SO >
+struct IsAligned< DynamicMatrix<T,SO> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool SO >
+struct IsPadded< DynamicMatrix<T,SO> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool SO >
+struct IsResizable< DynamicMatrix<T,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2, size_t M, size_t N >
+struct AddTrait< DynamicMatrix<T1,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct AddTrait< DynamicMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct AddTrait< StaticMatrix<T1,M,N,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct AddTrait< StaticMatrix<T1,M,N,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, bool SO, typename T2, size_t M, size_t N >
+struct AddTrait< DynamicMatrix<T1,SO>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct AddTrait< DynamicMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct AddTrait< HybridMatrix<T1,M,N,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct AddTrait< HybridMatrix<T1,M,N,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct AddTrait< DynamicMatrix<T1,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct AddTrait< DynamicMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2, size_t M, size_t N >
+struct SubTrait< DynamicMatrix<T1,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct SubTrait< DynamicMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct SubTrait< StaticMatrix<T1,M,N,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct SubTrait< StaticMatrix<T1,M,N,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, bool SO, typename T2, size_t M, size_t N >
+struct SubTrait< DynamicMatrix<T1,SO>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct SubTrait< DynamicMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct SubTrait< HybridMatrix<T1,M,N,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct SubTrait< HybridMatrix<T1,M,N,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct SubTrait< DynamicMatrix<T1,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct SubTrait< DynamicMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2 >
+struct MultTrait< DynamicMatrix<T1,SO>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, typename T2, bool SO >
+struct MultTrait< T1, DynamicMatrix<T2,SO>, EnableIf_<IsNumeric<T1> > >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO, typename T2, size_t N >
+struct MultTrait< DynamicMatrix<T1,SO>, StaticVector<T2,N,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2, bool SO >
+struct MultTrait< StaticVector<T1,N,true>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO, typename T2, size_t N >
+struct MultTrait< DynamicMatrix<T1,SO>, HybridVector<T2,N,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2, bool SO >
+struct MultTrait< HybridVector<T1,N,true>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct MultTrait< DynamicMatrix<T1,SO>, DynamicVector<T2,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, bool SO >
+struct MultTrait< DynamicVector<T1,true>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO, typename T2, bool AF, bool PF >
+struct MultTrait< DynamicMatrix<T1,SO>, CustomVector<T2,AF,PF,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2, bool SO >
+struct MultTrait< CustomVector<T1,AF,PF,true>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct MultTrait< DynamicMatrix<T1,SO>, CompressedVector<T2,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, bool SO >
+struct MultTrait< CompressedVector<T1,true>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct MultTrait< DynamicMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct MultTrait< StaticMatrix<T1,M,N,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct MultTrait< DynamicMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct MultTrait< HybridMatrix<T1,M,N,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct MultTrait< DynamicMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2 >
+struct DivTrait< DynamicMatrix<T1,SO>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = DynamicMatrix< DivTrait_<T1,T2>, SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2 >
+struct MathTrait< DynamicMatrix<T1,SO>, DynamicMatrix<T2,SO> >
+{
+ using HighType = DynamicMatrix< typename MathTrait<T1,T2>::HighType, SO >;
+ using LowType = DynamicMatrix< typename MathTrait<T1,T2>::LowType , SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO >
+struct SubmatrixTrait< DynamicMatrix<T1,SO> >
+{
+ using Type = DynamicMatrix<T1,SO>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO >
+struct RowTrait< DynamicMatrix<T1,SO> >
+{
+ using Type = DynamicVector<T1,true>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO >
+struct ColumnTrait< DynamicMatrix<T1,SO> >
+{
+ using Type = DynamicVector<T1,false>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/DynamicVector.h b/src/cpu/blaze/math/dense/DynamicVector.h
new file mode 100644
index 00000000..104fe045
--- /dev/null
+++ b/src/cpu/blaze/math/dense/DynamicVector.h
@@ -0,0 +1,2973 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/DynamicVector.h
+// \brief Header file for the implementation of an arbitrarily sized vector
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_DYNAMICVECTOR_H_
+#define _BLAZE_MATH_DENSE_DYNAMICVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/dense/DenseIterator.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/system/CacheSize.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Restrict.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/system/TransposeFlag.h>
+#include <blaze/util/Algorithm.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup dynamic_vector DynamicVector
+// \ingroup dense_vector
+*/
+/*!\brief Efficient implementation of an arbitrary sized vector.
+// \ingroup dynamic_vector
+//
+// The DynamicVector class template is the representation of an arbitrary sized vector with
+// dynamically allocated elements of arbitrary type. The type of the elements and the transpose
+// flag of the vector can be specified via the two template parameters:
+
+ \code
+ template< typename Type, bool TF >
+ class DynamicVector;
+ \endcode
+
+// - Type: specifies the type of the vector elements. DynamicVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - TF : specifies whether the vector is a row vector (\a blaze::rowVector) or a column
+// vector (\a blaze::columnVector). The default value is \a blaze::columnVector.
+//
+// These contiguously stored elements can be directly accessed with the subscript operator. The
+// numbering of the vector elements is
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right)\f]
+
+// The use of DynamicVector is very natural and intuitive. All operations (addition, subtraction,
+// multiplication, scaling, ...) can be performed on all possible combinations of dense and sparse
+// vectors with fitting element types. The following example gives an impression of the use of
+// DynamicVector:
+
+ \code
+ using blaze::DynamicVector;
+ using blaze::CompressedVector;
+ using blaze::DynamicMatrix;
+
+ DynamicVector<double> a( 2 ); // Non-initialized 2D vector of size 2
+ a[0] = 1.0; // Initialization of the first element
+ a[1] = 2.0; // Initialization of the second element
+
+ DynamicVector<double> b( 2, 2.0 ); // Directly, homogeneously initialized 2D vector
+ CompressedVector<float> c( 2 ); // Empty sparse single precision vector
+ DynamicVector<double> d; // Default constructed dynamic vector
+ DynamicMatrix<double> A; // Default constructed row-major matrix
+
+ d = a + b; // Vector addition between vectors of equal element type
+ d = a - c; // Vector subtraction between a dense and sparse vector with different element types
+ d = a * b; // Component-wise vector multiplication
+
+ a *= 2.0; // In-place scaling of vector
+ d = a * 2.0; // Scaling of vector a
+ d = 2.0 * a; // Scaling of vector a
+
+ d += a - b; // Addition assignment
+ d -= a + c; // Subtraction assignment
+ d *= a * b; // Multiplication assignment
+
+ double scalar = trans( a ) * b; // Scalar/dot/inner product between two vectors
+
+ A = a * trans( b ); // Outer product between two vectors
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool TF = defaultTransposeFlag > // Transpose flag
+class DynamicVector : public DenseVector< DynamicVector<Type,TF>, TF >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DynamicVector<Type,TF> This; //!< Type of this DynamicVector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this DynamicVector instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef DynamicVector<Type,!TF> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the vector elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the vector elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations
+ typedef const DynamicVector& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant vector value.
+ typedef const Type& ConstReference; //!< Reference to a constant vector value.
+ typedef Type* Pointer; //!< Pointer to a non-constant vector value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant vector value.
+
+ typedef DenseIterator<Type,aligned> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,aligned> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a DynamicVector with different data/element type.
+ */
+ template< typename ET > // Data type of the other vector
+ struct Rebind {
+ typedef DynamicVector<ET,TF> Other; //!< The type of the other DynamicVector.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
+ in can be optimized via SIMD operationss. In case the element type of the vector is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline DynamicVector() noexcept;
+ explicit inline DynamicVector( size_t n );
+ explicit inline DynamicVector( size_t n, const Type& init );
+ explicit inline DynamicVector( initializer_list<Type> list );
+
+ template< typename Other >
+ explicit inline DynamicVector( size_t n, const Other* array );
+
+ template< typename Other, size_t N >
+ explicit inline DynamicVector( const Other (&array)[N] );
+
+ inline DynamicVector( const DynamicVector& v );
+ inline DynamicVector( DynamicVector&& v ) noexcept;
+ template< typename VT > inline DynamicVector( const Vector<VT,TF>& v );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~DynamicVector();
+ //@}
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) noexcept;
+ inline ConstReference operator[]( size_t index ) const noexcept;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin () noexcept;
+ inline ConstIterator begin () const noexcept;
+ inline ConstIterator cbegin() const noexcept;
+ inline Iterator end () noexcept;
+ inline ConstIterator end () const noexcept;
+ inline ConstIterator cend () const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline DynamicVector& operator=( const Type& rhs );
+ inline DynamicVector& operator=( initializer_list<Type> list );
+
+ template< typename Other, size_t N >
+ inline DynamicVector& operator=( const Other (&array)[N] );
+
+ inline DynamicVector& operator=( const DynamicVector& rhs );
+ inline DynamicVector& operator=( DynamicVector&& rhs ) noexcept;
+
+ template< typename VT > inline DynamicVector& operator= ( const Vector<VT,TF>& rhs );
+ template< typename VT > inline DynamicVector& operator+=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline DynamicVector& operator-=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline DynamicVector& operator*=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline DynamicVector& operator/=( const DenseVector<VT,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, DynamicVector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, DynamicVector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline void clear();
+ inline void resize( size_t n, bool preserve=true );
+ inline void extend( size_t n, bool preserve=true );
+ inline void reserve( size_t n );
+ template< typename Other > inline DynamicVector& scale( const Other& scalar );
+ inline void swap( DynamicVector& v ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDAdd< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDSub< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDMult< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDDiv< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t adjustCapacity( size_t minCapacity ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t size_; //!< The current size/dimension of the vector.
+ size_t capacity_; //!< The maximum capacity of the vector.
+ Type* BLAZE_RESTRICT v_; //!< The dynamically allocated vector elements.
+ /*!< Access to the vector elements is gained via the subscript operator.
+ The order of the elements is
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right)\f] */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for DynamicVector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>::DynamicVector() noexcept
+ : size_ ( 0UL ) // The current size/dimension of the vector
+ , capacity_( 0UL ) // The maximum capacity of the vector
+ , v_ ( nullptr ) // The vector elements
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a vector of size \a n. No element initialization is performed!
+//
+// \param n The size of the vector.
+//
+// \note This constructor is only responsible to allocate the required dynamic memory. No
+// element initialization is performed!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>::DynamicVector( size_t n )
+ : size_ ( n ) // The current size/dimension of the vector
+ , capacity_( adjustCapacity( n ) ) // The maximum capacity of the vector
+ , v_ ( allocate<Type>( capacity_ ) ) // The vector elements
+{
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=size_; i<capacity_; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a homogeneous initialization of all \a n vector elements.
+//
+// \param n The size of the vector.
+// \param init The initial value of the vector elements.
+//
+// All vector elements are initialized with the specified value.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>::DynamicVector( size_t n, const Type& init )
+ : size_ ( n ) // The current size/dimension of the vector
+ , capacity_( adjustCapacity( n ) ) // The maximum capacity of the vector
+ , v_ ( allocate<Type>( capacity_ ) ) // The vector elements
+{
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] = init;
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=size_; i<capacity_; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List initialization of all vector elements.
+//
+// \param list The initializer list.
+//
+// This assignment operator provides the option to explicitly initialize the elements of the
+// vector within a constructor call:
+
+ \code
+ blaze::DynamicVector<double> v1{ 4.2, 6.3, -1.2 };
+ \endcode
+
+// The vector is sized according to the size of the initializer list and all its elements are
+// initialized by the values of the given initializer list.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>::DynamicVector( initializer_list<Type> list )
+ : size_ ( list.size() ) // The current size/dimension of the vector
+ , capacity_( adjustCapacity( size_ ) ) // The maximum capacity of the vector
+ , v_ ( allocate<Type>( capacity_ ) ) // The vector elements
+{
+ std::fill( std::copy( list.begin(), list.end(), v_ ), v_+capacity_, Type() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all vector elements.
+//
+// \param n The size of the vector.
+// \param array Dynamic array for the initialization.
+//
+// This assignment operator offers the option to directly initialize the elements of the vector
+// with a dynamic array:
+
+ \code
+ double* array = new double[4];
+ // ... Initialization of the dynamic array
+ blaze::DynamicVector<double> v( array, 4UL );
+ delete[] array;
+ \endcode
+
+// The vector is sized according to the specified size of the array and initialized with the
+// values from the given array. Note that it is expected that the given \a array has at least
+// \a n elements. Providing an array with less elements results in undefined behavior!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the initialization array
+inline DynamicVector<Type,TF>::DynamicVector( size_t n, const Other* array )
+ : size_ ( n ) // The current size/dimension of the vector
+ , capacity_( adjustCapacity( n ) ) // The maximum capacity of the vector
+ , v_ ( allocate<Type>( capacity_ ) ) // The vector elements
+{
+ for( size_t i=0UL; i<n; ++i )
+ v_[i] = array[i];
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=n; i<capacity_; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all vector elements.
+//
+// \param array N-dimensional array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the vector with a
+// static array:
+
+ \code
+ const int init[4] = { 1, 2, 3 };
+ blaze::DynamicVector<int> v( init );
+ \endcode
+
+// The vector is sized according to the size of the array and initialized with the values from the
+// given array. Missing values are initialized with default values (as e.g. the fourth element in
+// the example).
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other // Data type of the initialization array
+ , size_t N > // Dimension of the initialization array
+inline DynamicVector<Type,TF>::DynamicVector( const Other (&array)[N] )
+ : size_ ( N ) // The current size/dimension of the vector
+ , capacity_( adjustCapacity( N ) ) // The maximum capacity of the vector
+ , v_ ( allocate<Type>( capacity_ ) ) // The vector elements
+{
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = array[i];
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=N; i<capacity_; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for DynamicVector.
+//
+// \param v Vector to be copied.
+//
+// The copy constructor is explicitly defined due to the required dynamic memory management
+// and in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>::DynamicVector( const DynamicVector& v )
+ : size_ ( v.size_ ) // The current size/dimension of the vector
+ , capacity_( adjustCapacity( v.size_ ) ) // The maximum capacity of the vector
+ , v_ ( allocate<Type>( capacity_ ) ) // The vector elements
+{
+ BLAZE_INTERNAL_ASSERT( capacity_ <= v.capacity_, "Invalid capacity estimation" );
+
+ for( size_t i=0UL; i<capacity_; ++i )
+ v_[i] = v.v_[i];
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The move constructor for DynamicVector.
+//
+// \param v The vector to be moved into this instance.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>::DynamicVector( DynamicVector&& v ) noexcept
+ : size_ ( v.size_ ) // The current size/dimension of the vector
+ , capacity_( v.capacity_ ) // The maximum capacity of the vector
+ , v_ ( v.v_ ) // The vector elements
+{
+ v.size_ = 0UL;
+ v.capacity_ = 0UL;
+ v.v_ = nullptr;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different vectors.
+//
+// \param v Vector to be copied.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the foreign vector
+inline DynamicVector<Type,TF>::DynamicVector( const Vector<VT,TF>& v )
+ : size_ ( (~v).size() ) // The current size/dimension of the vector
+ , capacity_( adjustCapacity( size_ ) ) // The maximum capacity of the vector
+ , v_ ( allocate<Type>( capacity_ ) ) // The vector elements
+{
+ for( size_t i=( IsSparseVector<VT>::value ? 0UL : size_ );
+ i<( IsVectorizable<Type>::value ? capacity_ : size_ ); ++i ) {
+ v_[i] = Type();
+ }
+
+ smpAssign( *this, ~v );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The destructor for DynamicVector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>::~DynamicVector()
+{
+ deallocate( v_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::Reference
+ DynamicVector<Type,TF>::operator[]( size_t index ) noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::ConstReference
+ DynamicVector<Type,TF>::operator[]( size_t index ) const noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::Reference
+ DynamicVector<Type,TF>::at( size_t index )
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::ConstReference
+ DynamicVector<Type,TF>::at( size_t index ) const
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::Pointer DynamicVector<Type,TF>::data() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dynamic vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::ConstPointer DynamicVector<Type,TF>::data() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the dynamic vector.
+//
+// \return Iterator to the first element of the dynamic vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::Iterator DynamicVector<Type,TF>::begin() noexcept
+{
+ return Iterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the dynamic vector.
+//
+// \return Iterator to the first element of the dynamic vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::ConstIterator DynamicVector<Type,TF>::begin() const noexcept
+{
+ return ConstIterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the dynamic vector.
+//
+// \return Iterator to the first element of the dynamic vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::ConstIterator DynamicVector<Type,TF>::cbegin() const noexcept
+{
+ return ConstIterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the dynamic vector.
+//
+// \return Iterator just past the last element of the dynamic vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::Iterator DynamicVector<Type,TF>::end() noexcept
+{
+ return Iterator( v_ + size_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the dynamic vector.
+//
+// \return Iterator just past the last element of the dynamic vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::ConstIterator DynamicVector<Type,TF>::end() const noexcept
+{
+ return ConstIterator( v_ + size_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the dynamic vector.
+//
+// \return Iterator just past the last element of the dynamic vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename DynamicVector<Type,TF>::ConstIterator DynamicVector<Type,TF>::cend() const noexcept
+{
+ return ConstIterator( v_ + size_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Homogenous assignment to all vector elements.
+//
+// \param rhs Scalar value to be assigned to all vector elements.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator=( const Type& rhs )
+{
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] = rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List assignment to all vector elements.
+//
+// \param list The initializer list.
+//
+// This assignment operator offers the option to directly assign to all elements of the vector
+// by means of an initializer list:
+
+ \code
+ blaze::DynamicVector<double> v;
+ v = { 4.2, 6.3, -1.2 };
+ \endcode
+
+// The vector is resized according to the size of the initializer list and all its elements are
+// assigned the values from the given initializer list.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator=( initializer_list<Type> list )
+{
+ resize( list.size(), false );
+ std::copy( list.begin(), list.end(), v_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array assignment to all vector elements.
+//
+// \param array N-dimensional array for the assignment.
+// \return Reference to the assigned vector.
+//
+// This assignment operator offers the option to directly set all elements of the vector:
+
+ \code
+ const int init[4] = { 1, 2, 3 };
+ blaze::DynamicVector<int> v;
+ v = init;
+ \endcode
+
+// The vector is resized according to the size of the array and assigned the values from the given
+// array. Missing values are initialized with default values (as e.g. the fourth element in the
+// example).
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other // Data type of the initialization array
+ , size_t N > // Dimension of the initialization array
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator=( const Other (&array)[N] )
+{
+ resize( N, false );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = array[i];
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for DynamicVector.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+//
+// The vector is resized according to the given N-dimensional vector and initialized as a
+// copy of this vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator=( const DynamicVector& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ resize( rhs.size_, false );
+ smpAssign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Move assignment operator for DynamicVector.
+//
+// \param rhs The vector to be moved into this instance.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator=( DynamicVector&& rhs ) noexcept
+{
+ deallocate( v_ );
+
+ size_ = rhs.size_;
+ capacity_ = rhs.capacity_;
+ v_ = rhs.v_;
+
+ rhs.size_ = 0UL;
+ rhs.capacity_ = 0UL;
+ rhs.v_ = nullptr;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+//
+// The vector is resized according to the given vector and initialized as a copy of this vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).canAlias( this ) ) {
+ DynamicVector tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( (~rhs).size(), false );
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator+=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ smpAddAssign( *this, tmp );
+ }
+ else {
+ smpAddAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator-=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ smpSubAssign( *this, tmp );
+ }
+ else {
+ smpSubAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator*=( const Vector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( IsSparseVector<VT>::value || (~rhs).canAlias( this ) ) {
+ DynamicVector<Type,TF> tmp( *this * (~rhs) );
+ swap( tmp );
+ }
+ else {
+ smpMultAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::operator/=( const DenseVector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ DynamicVector<Type,TF> tmp( *this / (~rhs) );
+ swap( tmp );
+ }
+ else {
+ smpDivAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a vector and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, DynamicVector<Type,TF> >&
+ DynamicVector<Type,TF>::operator*=( Other rhs )
+{
+ smpAssign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a vector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, DynamicVector<Type,TF> >&
+ DynamicVector<Type,TF>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ smpAssign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the vector.
+//
+// \return The size of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline size_t DynamicVector<Type,TF>::size() const noexcept
+{
+ return size_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the vector.
+//
+// \return The capacity of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline size_t DynamicVector<Type,TF>::capacity() const noexcept
+{
+ return capacity_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the vector.
+//
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline size_t DynamicVector<Type,TF>::nonZeros() const
+{
+ size_t nonzeros( 0 );
+
+ for( size_t i=0UL; i<size_; ++i ) {
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+ }
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void DynamicVector<Type,TF>::reset()
+{
+ using blaze::clear;
+ for( size_t i=0UL; i<size_; ++i )
+ clear( v_[i] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the vector.
+//
+// \return void
+//
+// After the clear() function, the size of the vector is 0.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void DynamicVector<Type,TF>::clear()
+{
+ resize( 0UL, false );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the vector.
+//
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the vector using the given size to \a n. During this operation, new
+// dynamic memory may be allocated in case the capacity of the vector is too small. Note that
+// this function may invalidate all existing views (subvectors, ...) on the vector if it is
+// used to shrink the vector. Additionally, the resize operation potentially changes all vector
+// elements. In order to preserve the old vector values, the \a preserve flag can be set to
+// \a true. However, new vector elements are not initialized!
+//
+// The following example illustrates the resize operation of a vector of size 2 to a vector of
+// size 4. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{2}{c}}
+ 1 & 2 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & x & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void DynamicVector<Type,TF>::resize( size_t n, bool preserve )
+{
+ if( n > capacity_ )
+ {
+ // Allocating a new array
+ const size_t newCapacity( adjustCapacity( n ) );
+ Type* BLAZE_RESTRICT tmp = allocate<Type>( newCapacity );
+
+ // Initializing the new array
+ if( preserve ) {
+ transfer( v_, v_+size_, tmp );
+ }
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=size_; i<newCapacity; ++i )
+ tmp[i] = Type();
+ }
+
+ // Replacing the old array
+ std::swap( v_, tmp );
+ deallocate( tmp );
+ capacity_ = newCapacity;
+ }
+ else if( IsVectorizable<Type>::value && n < size_ )
+ {
+ for( size_t i=n; i<size_; ++i )
+ v_[i] = Type();
+ }
+
+ size_ = n;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Extending the size of the vector.
+//
+// \param n Number of additional vector elements.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+//
+// This function increases the vector size by \a n elements. During this operation, new dynamic
+// memory may be allocated in case the capacity of the vector is too small. Therefore this
+// function potentially changes all vector elements. In order to preserve the old vector values,
+// the \a preserve flag can be set to \a true. However, new vector elements are not initialized!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void DynamicVector<Type,TF>::extend( size_t n, bool preserve )
+{
+ resize( size_+n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the vector.
+//
+// \param n The new minimum capacity of the vector.
+// \return void
+//
+// This function increases the capacity of the vector to at least \a n elements. The current
+// values of the vector elements are preserved.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void DynamicVector<Type,TF>::reserve( size_t n )
+{
+ if( n > capacity_ )
+ {
+ // Allocating a new array
+ const size_t newCapacity( adjustCapacity( n ) );
+ Type* BLAZE_RESTRICT tmp = allocate<Type>( newCapacity );
+
+ // Initializing the new array
+ transfer( v_, v_+size_, tmp );
+
+ if( IsVectorizable<Type>::value ) {
+ for( size_t i=size_; i<newCapacity; ++i )
+ tmp[i] = Type();
+ }
+
+ // Replacing the old array
+ std::swap( tmp, v_ );
+ deallocate( tmp );
+ capacity_ = newCapacity;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the vector scaling.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline DynamicVector<Type,TF>& DynamicVector<Type,TF>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] *= scalar;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two vectors.
+//
+// \param v The vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void DynamicVector<Type,TF>::swap( DynamicVector& v ) noexcept
+{
+ std::swap( size_, v.size_ );
+ std::swap( capacity_, v.capacity_ );
+ std::swap( v_, v.v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Adjusting the new capacity of the vector according to its data type \a Type.
+//
+// \param minCapacity The minimum necessary capacity.
+// \return The new capacity.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline size_t DynamicVector<Type,TF>::adjustCapacity( size_t minCapacity ) const noexcept
+{
+ if( usePadding && IsVectorizable<Type>::value )
+ return nextMultiple<size_t>( minCapacity, SIMDSIZE );
+ else return minCapacity;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the dynamic vector are intact.
+//
+// \return \a true in case the dynamic vector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the dynamic vector are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline bool DynamicVector<Type,TF>::isIntact() const noexcept
+{
+ if( size_ > capacity_ )
+ return false;
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=size_; i<capacity_; ++i ) {
+ if( v_[i] != Type() )
+ return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address can alias with the vector. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool DynamicVector<Type,TF>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address is aliased with the vector. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool DynamicVector<Type,TF>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is properly aligned in memory.
+//
+// \return \a true in case the vector is aligned, \a false if not.
+//
+// This function returns whether the vector is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of the vector are guaranteed to conform to the alignment
+// restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline bool DynamicVector<Type,TF>::isAligned() const noexcept
+{
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector can be used in SMP assignments.
+//
+// \return \a true in case the vector can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the vector can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current size of the
+// vector).
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline bool DynamicVector<Type,TF>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename DynamicVector<Type,TF>::SIMDType
+ DynamicVector<Type,TF>::load( size_t index ) const noexcept
+{
+ return loada( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename DynamicVector<Type,TF>::SIMDType
+ DynamicVector<Type,TF>::loada( size_t index ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid alignment detected" );
+
+ return loada( v_+index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename DynamicVector<Type,TF>::SIMDType
+ DynamicVector<Type,TF>::loadu( size_t index ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+
+ return loadu( v_+index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ DynamicVector<Type,TF>::store( size_t index, const SIMDType& value ) noexcept
+{
+ storea( index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ DynamicVector<Type,TF>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid alignment detected" );
+
+ storea( v_+index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense vector.
+// The index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ DynamicVector<Type,TF>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+
+ storeu( v_+index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense vector. The index must be smaller than the number of vector elements and it must be
+// a multiple of the number of values inside the SIMD element. This function must \b NOT be
+// called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ DynamicVector<Type,TF>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid alignment detected" );
+
+ stream( v_+index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ DynamicVector<Type,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] = (~rhs)[i ];
+ v_[i+1UL] = (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] = (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ DynamicVector<Type,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i=0UL;
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ if( useStreaming && size_ > ( cacheSize/( sizeof(Type) * 3UL ) ) && !(~rhs).isAliased( this ) )
+ {
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<size_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ else
+ {
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<size_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void DynamicVector<Type,TF>::assign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ DynamicVector<Type,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] += (~rhs)[i ];
+ v_[i+1UL] += (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] += (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ DynamicVector<Type,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<size_; ++i ) {
+ *left += *right; ++left; ++right;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void DynamicVector<Type,TF>::addAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ DynamicVector<Type,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] -= (~rhs)[i ];
+ v_[i+1UL] -= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] -= (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ DynamicVector<Type,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<size_; ++i ) {
+ *left -= *right; ++left; ++right;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void DynamicVector<Type,TF>::subAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] -= element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ DynamicVector<Type,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] *= (~rhs)[i ];
+ v_[i+1UL] *= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] *= (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ DynamicVector<Type,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<size_; ++i ) {
+ *left *= *right; ++left; ++right;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void DynamicVector<Type,TF>::multAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const DynamicVector tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = tmp[element->index()] * element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisior.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ DynamicVector<Type,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ v_[i ] /= (~rhs)[i ];
+ v_[i+1UL] /= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ v_[ipos] /= (~rhs)[ipos];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename DynamicVector<Type,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ DynamicVector<Type,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left /= *right; ++left; ++right;
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DYNAMICVECTOR OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DynamicVector operators */
+//@{
+template< typename Type, bool TF >
+inline void reset( DynamicVector<Type,TF>& v );
+
+template< typename Type, bool TF >
+inline void clear( DynamicVector<Type,TF>& v );
+
+template< typename Type, bool TF >
+inline bool isDefault( const DynamicVector<Type,TF>& v );
+
+template< typename Type, bool TF >
+inline bool isIntact( const DynamicVector<Type,TF>& v ) noexcept;
+
+template< typename Type, bool TF >
+inline void swap( DynamicVector<Type,TF>& a, DynamicVector<Type,TF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given dynamic vector.
+// \ingroup dynamic_vector
+//
+// \param v The dynamic vector to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void reset( DynamicVector<Type,TF>& v )
+{
+ v.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given dynamic vector.
+// \ingroup dynamic_vector
+//
+// \param v The dynamic vector to be cleared.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void clear( DynamicVector<Type,TF>& v )
+{
+ v.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given dynamic vector is in default state.
+// \ingroup dynamic_vector
+//
+// \param v The dynamic vector to be tested for its default state.
+// \return \a true in case the given vector's size is zero, \a false otherwise.
+//
+// This function checks whether the dynamic vector is in default (constructed) state, i.e. if
+// it's size is 0. In case it is in default state, the function returns \a true, else it will
+// return \a false. The following example demonstrates the use of the \a isDefault() function:
+
+ \code
+ blaze::DynamicVector<int> a;
+ // ... Resizing and initialization
+ if( isDefault( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline bool isDefault( const DynamicVector<Type,TF>& v )
+{
+ return ( v.size() == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given dynamic vector are intact.
+// \ingroup dynamic_vector
+//
+// \param v The dynamic vector to be tested.
+// \return \a true in case the given vector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the dynamic vector are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::DynamicVector<int> a;
+ // ... Resizing and initialization
+ if( isIntact( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline bool isIntact( const DynamicVector<Type,TF>& v ) noexcept
+{
+ return v.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two vectors.
+// \ingroup dynamic_vector
+//
+// \param a The first vector to be swapped.
+// \param b The second vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void swap( DynamicVector<Type,TF>& a, DynamicVector<Type,TF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool TF >
+struct HasConstDataAccess< DynamicVector<T,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool TF >
+struct HasMutableDataAccess< DynamicVector<T,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool TF >
+struct IsAligned< DynamicVector<T,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool TF >
+struct IsPadded< DynamicVector<T,TF> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool TF >
+struct IsResizable< DynamicVector<T,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2, size_t N >
+struct AddTrait< DynamicVector<T1,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct AddTrait< StaticVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct AddTrait< DynamicVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct AddTrait< HybridVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ using Type = HybridVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct AddTrait< DynamicVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< AddTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2, size_t N >
+struct SubTrait< DynamicVector<T1,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct SubTrait< StaticVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct SubTrait< DynamicVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct SubTrait< HybridVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ using Type = HybridVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct SubTrait< DynamicVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< SubTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2 >
+struct MultTrait< DynamicVector<T1,TF>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2, bool TF >
+struct MultTrait< T1, DynamicVector<T2,TF>, EnableIf_<IsNumeric<T1> > >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct MultTrait< DynamicVector<T1,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, typename T2, size_t N >
+struct MultTrait< DynamicVector<T1,false>, StaticVector<T2,N,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, size_t N >
+struct MultTrait< DynamicVector<T1,true>, StaticVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MultTrait< StaticVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< StaticVector<T1,N,false>, DynamicVector<T2,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< StaticVector<T1,N,true>, DynamicVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct MultTrait< DynamicVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, typename T2, size_t N >
+struct MultTrait< DynamicVector<T1,false>, HybridVector<T2,N,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, size_t N >
+struct MultTrait< DynamicVector<T1,true>, HybridVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MultTrait< HybridVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< HybridVector<T1,N,false>, DynamicVector<T2,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< HybridVector<T1,N,true>, DynamicVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct MultTrait< DynamicVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2 >
+struct MultTrait< DynamicVector<T1,false>, DynamicVector<T2,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2 >
+struct MultTrait< DynamicVector<T1,true>, DynamicVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CROSSTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2 >
+struct CrossTrait< DynamicVector<T1,TF>, StaticVector<T2,3UL,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct CrossTrait< StaticVector<T1,3UL,TF>, DynamicVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct CrossTrait< DynamicVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct CrossTrait< HybridVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct CrossTrait< DynamicVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2 >
+struct DivTrait< DynamicVector<T1,TF>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = DynamicVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct DivTrait< DynamicVector<T1,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct DivTrait< StaticVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ using Type = StaticVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct DivTrait< DynamicVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct DivTrait< HybridVector<T1,N,TF>, DynamicVector<T2,TF> >
+{
+ using Type = HybridVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct DivTrait< DynamicVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< DivTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2 >
+struct MathTrait< DynamicVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using HighType = DynamicVector< typename MathTrait<T1,T2>::HighType, TF >;
+ using LowType = DynamicVector< typename MathTrait<T1,T2>::LowType , TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF >
+struct SubvectorTrait< DynamicVector<T1,TF> >
+{
+ using Type = DynamicVector<T1,TF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/Forward.h b/src/cpu/blaze/math/dense/Forward.h
new file mode 100644
index 00000000..4e997587
--- /dev/null
+++ b/src/cpu/blaze/math/dense/Forward.h
@@ -0,0 +1,65 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/Forward.h
+// \brief Header file for all forward declarations for dense vectors and matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_FORWARD_H_
+#define _BLAZE_MATH_DENSE_FORWARD_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+template< typename, bool, bool, bool > class CustomMatrix;
+template< typename, bool, bool, bool > class CustomVector;
+template< typename, bool > class DynamicVector;
+template< typename, bool > class DynamicMatrix;
+template< typename, size_t, size_t, bool > class HybridMatrix;
+template< typename, size_t, bool > class HybridVector;
+template< typename, size_t, size_t, bool > class StaticMatrix;
+template< typename, size_t, bool > class StaticVector;
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/HybridMatrix.h b/src/cpu/blaze/math/dense/HybridMatrix.h
new file mode 100644
index 00000000..67a3e0b7
--- /dev/null
+++ b/src/cpu/blaze/math/dense/HybridMatrix.h
@@ -0,0 +1,6663 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/HybridMatrix.h
+// \brief Header file for the implementation of a fixed-size matrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_HYBRIDMATRIX_H_
+#define _BLAZE_MATH_DENSE_HYBRIDMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/Diagonal.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/dense/DenseIterator.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/InvExprTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/StorageOrder.h>
+#include <blaze/util/AlignedArray.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/mpl/NextMultiple.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup hybrid_matrix HybridMatrix
+// \ingroup dense_matrix
+*/
+/*!\brief Efficient implementation of a dynamically sized matrix with static memory.
+// \ingroup hybrid_matrix
+//
+// The HybridMatrix class template combines the flexibility of a dynamically sized matrix with
+// the efficiency and performance of a fixed-size matrix. It is implemented as a crossing between
+// the blaze::StaticMatrix and the blaze::DynamicMatrix class templates: Similar to the static
+// matrix it uses static stack memory instead of dynamically allocated memory and similar to the
+// dynamic matrix it can be resized (within the extend of the static memory). The type of the
+// elements, the maximum number of rows and columns and the storage order of the matrix can be
+// specified via the four template parameters:
+
+ \code
+ template< typename Type, size_t M, size_t N, bool SO >
+ class HybridMatrix;
+ \endcode
+
+// - Type: specifies the type of the matrix elements. HybridMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - M : specifies the maximum number of rows of the matrix.
+// - N : specifies the maximum number of columns of the matrix. Note that it is expected
+// that HybridMatrix is only used for tiny and small matrices.
+// - SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// Depending on the storage order, the matrix elements are either stored in a row-wise fashion
+// or in a column-wise fashion. Given the 2x3 matrix
+
+ \f[\left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 4 & 5 & 6 \\
+ \end{array}\right)\f]\n
+
+// in case of row-major order the elements are stored in the order
+
+ \f[\left(\begin{array}{*{6}{c}}
+ 1 & 2 & 3 & 4 & 5 & 6. \\
+ \end{array}\right)\f]
+
+// In case of column-major order the elements are stored in the order
+
+ \f[\left(\begin{array}{*{6}{c}}
+ 1 & 4 & 2 & 5 & 3 & 6. \\
+ \end{array}\right)\f]
+
+// The use of HybridMatrix is very natural and intuitive. All operations (addition, subtraction,
+// multiplication, scaling, ...) can be performed on all possible combination of row-major and
+// column-major dense and sparse matrices with fitting element types. The following example gives
+// an impression of the use of HybridMatrix:
+
+ \code
+ using blaze::HybridMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ HybridMatrix<double,rowMajor> A( 2, 3 ); // Default constructed, non-initialized, row-major 2x3 matrix
+ A(0,0) = 1.0; A(0,1) = 2.0; A(0,2) = 3.0; // Initialization of the first row
+ A(1,0) = 4.0; A(1,1) = 5.0; A(1,2) = 6.0; // Initialization of the second row
+
+ HybridMatrix<float,columnMajor> B( 2, 3 ); // Default constructed column-major single precision 2x3 matrix
+ B(0,0) = 1.0; B(0,1) = 3.0; B(0,2) = 5.0; // Initialization of the first row
+ B(1,0) = 2.0; B(1,1) = 4.0; B(1,2) = 6.0; // Initialization of the second row
+
+ CompressedMatrix<float> C( 2, 3 ); // Empty row-major sparse single precision matrix
+ HybridMatrix<float> D( 3, 2, 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix
+
+ HybridMatrix<double,rowMajor> E( A ); // Creation of a new row-major matrix as a copy of A
+ HybridMatrix<double,columnMajor> F; // Creation of a default column-major matrix
+
+ E = A + B; // Matrix addition and assignment to a row-major matrix
+ F = A - C; // Matrix subtraction and assignment to a column-major matrix
+ F = A * D; // Matrix multiplication between two matrices of different element types
+
+ A *= 2.0; // In-place scaling of matrix A
+ E = 2.0 * B; // Scaling of matrix B
+ F = D * 2.0; // Scaling of matrix D
+
+ E += A - B; // Addition assignment
+ E -= A + C; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO = defaultStorageOrder > // Storage order
+class HybridMatrix : public DenseMatrix< HybridMatrix<Type,M,N,SO>, SO >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef HybridMatrix<Type,M,N,SO> This; //!< Type of this HybridMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this HybridMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef HybridMatrix<Type,M,N,!SO> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef HybridMatrix<Type,N,M,!SO> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Type* Pointer; //!< Pointer to a non-constant matrix value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant matrix value.
+
+ typedef DenseIterator<Type,usePadding> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,usePadding> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a HybridMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef HybridMatrix<ET,M,N,SO> Other; //!< The type of the other HybridMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the element type of the matrix is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline HybridMatrix();
+ explicit inline HybridMatrix( size_t m, size_t n );
+ explicit inline HybridMatrix( size_t m, size_t n, const Type& init );
+ explicit inline HybridMatrix( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other >
+ explicit inline HybridMatrix( size_t m, size_t n, const Other* array );
+
+ template< typename Other, size_t M2, size_t N2 >
+ explicit inline HybridMatrix( const Other (&array)[M2][N2] );
+
+ inline HybridMatrix( const HybridMatrix& m );
+ template< typename MT, bool SO2 > inline HybridMatrix( const Matrix<MT,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t i ) noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i ) noexcept;
+ inline ConstIterator begin ( size_t i ) const noexcept;
+ inline ConstIterator cbegin( size_t i ) const noexcept;
+ inline Iterator end ( size_t i ) noexcept;
+ inline ConstIterator end ( size_t i ) const noexcept;
+ inline ConstIterator cend ( size_t i ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline HybridMatrix& operator=( const Type& set );
+ inline HybridMatrix& operator=( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other, size_t M2, size_t N2 >
+ inline HybridMatrix& operator=( const Other (&array)[M2][N2] );
+
+ inline HybridMatrix& operator= ( const HybridMatrix& rhs );
+ template< typename MT, bool SO2 > inline HybridMatrix& operator= ( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline HybridMatrix& operator+=( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline HybridMatrix& operator-=( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline HybridMatrix& operator*=( const Matrix<MT,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, HybridMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, HybridMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline constexpr size_t spacing() const noexcept;
+ inline constexpr size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t m, size_t n, bool preserve=true );
+ inline void extend ( size_t m, size_t n, bool preserve=true );
+ inline HybridMatrix& transpose();
+ inline HybridMatrix& ctranspose();
+ template< typename Other > inline HybridMatrix& scale( const Other& scalar );
+ inline void swap( HybridMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Memory functions****************************************************************************
+ /*!\name Memory functions */
+ //@{
+ static inline void* operator new ( std::size_t size );
+ static inline void* operator new[]( std::size_t size );
+ static inline void* operator new ( std::size_t size, const std::nothrow_t& );
+ static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
+
+ static inline void operator delete ( void* ptr );
+ static inline void operator delete[]( void* ptr );
+ static inline void operator delete ( void* ptr, const std::nothrow_t& );
+ static inline void operator delete[]( void* ptr, const std::nothrow_t& );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ IsRowMajorMatrix<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDAdd< Type, ElementType_<MT> >::value &&
+ IsRowMajorMatrix<MT>::value &&
+ !IsDiagonal<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDSub< Type, ElementType_<MT> >::value &&
+ IsRowMajorMatrix<MT>::value &&
+ !IsDiagonal<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT, bool SO2 >
+ inline DisableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline EnableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT > inline void assign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,!SO>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline DisableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline EnableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,!SO>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline DisableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline EnableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,!SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Alignment adjustment.
+ enum : size_t { NN = ( usePadding )?( NextMultiple< SizeT<N>, SizeT<SIMDSIZE> >::value ):( N ) };
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ AlignedArray<Type,M*NN> v_; //!< The statically allocated matrix elements.
+ /*!< Access to the matrix elements is gained via the function call
+ operator. In case of row-major order the memory layout of the
+ elements is
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ N & N+1 & N+2 & \cdots & 2 \cdot N-1 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ M \cdot N-N & M \cdot N-N+1 & M \cdot N-N+2 & \cdots & M \cdot N-1 \\
+ \end{array}\right)\f]. */
+ size_t m_; //!< The current number of rows of the matrix.
+ size_t n_; //!< The current number of columns of the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_STATIC_ASSERT( !usePadding || NN % SIMDSIZE == 0UL );
+ BLAZE_STATIC_ASSERT( NN >= N );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for HybridMatrix.
+//
+// The size of a default constructed HybridMatrix is initially set to 0.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>::HybridMatrix()
+ : v_() // The statically allocated matrix elements
+ , m_( 0UL ) // The current number of rows of the matrix
+ , n_( 0UL ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<M*NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$. No element initialization is performed!
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This constructor creates a hybrid matrix of size \f$ m \times n \f$, but leaves the elements
+// uninitialized. In case \a m is larger than the maximum allowed number of rows (i.e. \a m > M)
+// or \a n is larger than the maximum allowed number of columns a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>::HybridMatrix( size_t m, size_t n )
+ : v_() // The statically allocated matrix elements
+ , m_( m ) // The current number of rows of the matrix
+ , n_( n ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<M*NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a homogenous initialization of all \f$ m \times n \f$ matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param init The initial value of the matrix elements.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This constructor creates a hybrid matrix of size \f$ m \times n \f$ and initializes all
+// matrix elements with the specified value. In case \a m is larger than the maximum allowed
+// number of rows (i.e. \a m > M) or \a n is larger than the maximum allowed number of columns
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>::HybridMatrix( size_t m, size_t n, const Type& init )
+ : v_() // The statically allocated matrix elements
+ , m_( m ) // The current number of rows of the matrix
+ , n_( n ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j )
+ v_[i*NN+j] = init;
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m; i<M; ++i )
+ for( size_t j=0UL; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the matrix by
+// means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::HybridMatrix<int,3,3,rowMajor> A{ { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all its elements are
+// initialized by the values of the given initializer list. Missing values are initialized as
+// default (as e.g. the value 6 in the example). Note that in case the size of the top-level
+// initializer list exceeds the number of rows or the size of any nested list exceeds the
+// number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>::HybridMatrix( initializer_list< initializer_list<Type> > list )
+ : v_() // The statically allocated matrix elements
+ , m_( list.size() ) // The current number of rows of the matrix
+ , n_( determineColumns( list ) ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( m_ > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n_ > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*NN ), v_+(i+1UL)*NN, Type() );
+ ++i;
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( ; i<M; ++i )
+ for( size_t j=0UL; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[20];
+ // ... Initialization of the dynamic array
+ blaze::HybridMatrix<int,4,5,rowMajor> v( 4UL, 5UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized according to the given size of the array and initialized with the values
+// from the given array. In case \a m is larger than the maximum allowed number of rows (i.e.
+// \a m > M) or \a n is larger than the maximum allowed number of columns a \a std::invalid_argument
+// exception is thrown. Note that it is expected that the given \a array has at least \a m by
+// \a n elements. Providing an array with less elements results in undefined behavior!
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the initialization array
+inline HybridMatrix<Type,M,N,SO>::HybridMatrix( size_t m, size_t n, const Other* array )
+ : v_() // The statically allocated matrix elements
+ , m_( m ) // The current number of rows of the matrix
+ , n_( n ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j )
+ v_[i*NN+j] = array[i*n+j];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m; i<M; ++i )
+ for( size_t j=0UL; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::HybridMatrix<int,3,3,rowMajor> A( init );
+ \endcode
+
+// The matrix is sized according to the size of the array and initialized with the values from
+// the given array. Missing values are initialized with default values (as e.g. the value 6 in
+// the example).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other // Data type of the initialization array
+ , size_t M2 // Number of rows of the initialization array
+ , size_t N2 > // Number of columns of the initialization array
+inline HybridMatrix<Type,M,N,SO>::HybridMatrix( const Other (&array)[M2][N2] )
+ : v_() // The statically allocated matrix elements
+ , m_( M2 ) // The current number of rows of the matrix
+ , n_( N2 ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( M2 <= M );
+ BLAZE_STATIC_ASSERT( N2 <= N );
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<M2; ++i ) {
+ for( size_t j=0UL; j<N2; ++j )
+ v_[i*NN+j] = array[i][j];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=N2; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=M2; i<M; ++i )
+ for( size_t j=0UL; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for HybridMatrix.
+//
+// \param m Matrix to be copied.
+//
+// The copy constructor is explicitly defined due to the required dynamic memory management
+// and in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>::HybridMatrix( const HybridMatrix& m )
+ : v_() // The statically allocated matrix elements
+ , m_( m.m_ ) // The current number of rows of the matrix
+ , n_( m.n_ ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*NN+j] = m.v_[i*NN+j];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n_; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m_; i<M; ++i )
+ for( size_t j=0UL; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of hybrid matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline HybridMatrix<Type,M,N,SO>::HybridMatrix( const Matrix<MT,SO2>& m )
+ : v_() // The statically allocated matrix elements
+ , m_( (~m).rows() ) // The current number of rows of the matrix
+ , n_( (~m).columns() ) // The current number of columns of the matrix
+{
+ using blaze::assign;
+
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( (~m).rows() > M || (~m).columns() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid matrix" );
+ }
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=( IsSparseMatrix<MT>::value ? 0UL : n_ );
+ j<( IsNumeric<Type>::value ? NN : n_ );
+ ++j ) {
+ v_[i*NN+j] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m_; i<M; ++i )
+ for( size_t j=0UL; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ assign( *this, ~m );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::Reference
+ HybridMatrix<Type,M,N,SO>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
+ return v_[i*NN+j];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return Reference-to-const to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::ConstReference
+ HybridMatrix<Type,M,N,SO>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
+ return v_[i*NN+j];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::Reference
+ HybridMatrix<Type,M,N,SO>::at( size_t i, size_t j )
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::ConstReference
+ HybridMatrix<Type,M,N,SO>::at( size_t i, size_t j ) const
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the hybrid matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The hybrid matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::Pointer
+ HybridMatrix<Type,M,N,SO>::data() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the hybrid matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The hybrid matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::ConstPointer
+ HybridMatrix<Type,M,N,SO>::data() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::Pointer
+ HybridMatrix<Type,M,N,SO>::data( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return v_ + i*NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::ConstPointer
+ HybridMatrix<Type,M,N,SO>::data( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return v_ + i*NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::Iterator
+ HybridMatrix<Type,M,N,SO>::begin( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return Iterator( v_ + i*NN );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::ConstIterator
+ HybridMatrix<Type,M,N,SO>::begin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*NN );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::ConstIterator
+ HybridMatrix<Type,M,N,SO>::cbegin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*NN );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::Iterator
+ HybridMatrix<Type,M,N,SO>::end( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return Iterator( v_ + i*NN + N );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::ConstIterator
+ HybridMatrix<Type,M,N,SO>::end( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*NN + N );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename HybridMatrix<Type,M,N,SO>::ConstIterator
+ HybridMatrix<Type,M,N,SO>::cend( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*NN + N );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Homogenous assignment to all matrix elements.
+//
+// \param set Scalar value to be assigned to all matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::operator=( const Type& set )
+{
+ BLAZE_INTERNAL_ASSERT( m_ <= M, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( n_ <= N, "Invalid number of columns detected" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*NN+j] = set;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the matrix
+// by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<int,rowMajor> A;
+ A = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix is resized according to the given initializer list and all its elements are
+// assigned the values from the given initializer list. Missing values are initialized as
+// default (as e.g. the value 6 in the example). Note that in case the size of the top-level
+// initializer list exceeds the number of rows or the size of any nested list exceeds the
+// number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>&
+ HybridMatrix<Type,M,N,SO>::operator=( initializer_list< initializer_list<Type> > list )
+{
+ const size_t m( list.size() );
+ const size_t n( determineColumns( list ) );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ resize( m, n, false );
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*NN ), v_+(i+1UL)*NN, Type() );
+ ++i;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array assignment to all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+//
+// This assignment operator offers the option to directly set all elements of the matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::HybridMatrix<int,3UL,3UL,rowMajor> A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other // Data type of the initialization array
+ , size_t M2 // Number of rows of the initialization array
+ , size_t N2 > // Number of columns of the initialization array
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::operator=( const Other (&array)[M2][N2] )
+{
+ BLAZE_STATIC_ASSERT( M2 <= M );
+ BLAZE_STATIC_ASSERT( N2 <= N );
+
+ resize( M2, N2 );
+
+ for( size_t i=0UL; i<M2; ++i )
+ for( size_t j=0UL; j<N2; ++j )
+ v_[i*NN+j] = array[i][j];
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for HybridMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// Explicit definition of a copy assignment operator for performance reasons.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::operator=( const HybridMatrix& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_INTERNAL_ASSERT( m_ <= M, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( n_ <= N, "Invalid number of columns detected" );
+
+ resize( rhs.rows(), rhs.columns() );
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to hybrid matrix.
+//
+// This constructor initializes the matrix as a copy of the given matrix. In case the
+// number of rows of the given matrix is not M or the number of columns is not N, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::operator=( const Matrix<MT,SO2>& rhs )
+{
+ using blaze::assign;
+
+ typedef TransExprTrait_<This> TT;
+ typedef CTransExprTrait_<This> CT;
+ typedef InvExprTrait_<This> IT;
+
+ if( (~rhs).rows() > M || (~rhs).columns() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to hybrid matrix" );
+ }
+
+ if( IsSame<MT,TT>::value && (~rhs).isAliased( this ) ) {
+ transpose();
+ }
+ else if( IsSame<MT,CT>::value && (~rhs).isAliased( this ) ) {
+ ctranspose();
+ }
+ else if( !IsSame<MT,IT>::value && (~rhs).canAlias( this ) ) {
+ HybridMatrix tmp( ~rhs );
+ resize( tmp.rows(), tmp.columns() );
+ assign( *this, tmp );
+ }
+ else {
+ resize( (~rhs).rows(), (~rhs).columns() );
+ if( IsSparseMatrix<MT>::value )
+ reset();
+ assign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::operator+=( const Matrix<MT,SO2>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ addAssign( *this, tmp );
+ }
+ else {
+ addAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::operator-=( const Matrix<MT,SO2>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ subAssign( *this, tmp );
+ }
+ else {
+ subAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::operator*=( const Matrix<MT,SO2>& rhs )
+{
+ if( n_ != (~rhs).rows() || (~rhs).columns() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const HybridMatrix tmp( *this * (~rhs) );
+ this->operator=( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, HybridMatrix<Type,M,N,SO> >&
+ HybridMatrix<Type,M,N,SO>::operator*=( Other rhs )
+{
+ using blaze::assign;
+
+ assign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, HybridMatrix<Type,M,N,SO> >&
+ HybridMatrix<Type,M,N,SO>::operator/=( Other rhs )
+{
+ using blaze::assign;
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ assign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline size_t HybridMatrix<Type,M,N,SO>::rows() const noexcept
+{
+ return m_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline size_t HybridMatrix<Type,M,N,SO>::columns() const noexcept
+{
+ return n_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the spacing between the beginning of two rows.
+//
+// \return The spacing between the beginning of two rows.
+//
+// This function returns the spacing between the beginning of two rows, i.e. the total number
+// of elements of a row.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline constexpr size_t HybridMatrix<Type,M,N,SO>::spacing() const noexcept
+{
+ return NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline constexpr size_t HybridMatrix<Type,M,N,SO>::capacity() const noexcept
+{
+ return M*NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline size_t HybridMatrix<Type,M,N,SO>::capacity( size_t i ) const noexcept
+{
+ UNUSED_PARAMETER( i );
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ return NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline size_t HybridMatrix<Type,M,N,SO>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ if( !isDefault( v_[i*NN+j] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline size_t HybridMatrix<Type,M,N,SO>::nonZeros( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t jend( i*NN + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=i*NN; j<jend; ++j )
+ if( !isDefault( v_[j] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::reset()
+{
+ using blaze::clear;
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ clear( v_[i*NN+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::reset( size_t i )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ for( size_t j=0UL; j<n_; ++j )
+ clear( v_[i*NN+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the hybrid matrix.
+//
+// \return void
+//
+// After the clear() function, the size of the matrix is 0.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::clear()
+{
+ resize( 0UL, 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the matrix.
+//
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. In case the given
+// number of rows \a m is larger than the maximum number of rows (i.e. if m > M) or in case the
+// given number of columns \a n is larger than the maximum number of column (i.e. if n > N) a
+// \a std::invalid_argument exception is thrown. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, during this operation all matrix elements are potentially changed. In
+// order to preserve the old matrix values, the \a preserve flag can be set to \a true.
+//
+// Note that in case the number of rows or columns is increased new matrix elements are not
+// initialized! The following example illustrates the resize operation of a \f$ 2 \times 4 \f$
+// matrix to a \f$ 4 \times 2 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & 4 \\
+ 5 & 6 & 7 & 8 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{2}{c}}
+ 1 & 2 \\
+ 5 & 6 \\
+ x & x \\
+ x & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+void HybridMatrix<Type,M,N,SO>::resize( size_t m, size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ if( IsVectorizable<Type>::value && n < n_ ) {
+ for( size_t i=0UL; i<m; ++i )
+ for( size_t j=n; j<n_; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ if( IsVectorizable<Type>::value && m < m_ ) {
+ for( size_t i=m; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ m_ = m;
+ n_ = n;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Extending the size of the matrix.
+//
+// \param m Number of additional rows.
+// \param n Number of additional columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a m rows and \a n columns. In case the resulting
+// number of rows or columns is larger than the maximum number of rows or columns (i.e. if m > M
+// or n > N) a \a std::invalid_argument exception is thrown. During this operation, all matrix
+// elements are potentially changed. In order to preserve the old matrix values, the \a preserve
+// flag can be set to \a true.\n
+// Note that new matrix elements are not initialized!
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::extend( size_t m, size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+ resize( m_+m, n_+n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::logic_error Impossible transpose operation.
+//
+// This function transposes the hybrid matrix in-place. Note that this function can only be used
+// on hybrid matrices whose current dimensions allow an in-place transpose operation. In case the
+// current number of rows is larger than the maximum number of columns or if the current number
+// of columns is larger than the maximum number of rows, an \a std::logic_error is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::transpose()
+{
+ using std::swap;
+
+ if( m_ > N || n_ > M ) {
+ BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
+ }
+
+ const size_t maxsize( max( m_, n_ ) );
+ for( size_t i=1UL; i<maxsize; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ swap( v_[i*NN+j], v_[j*NN+i] );
+ }
+ }
+
+ if( IsVectorizable<Type>::value && m_ < n_ ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=m_; j<n_; ++j ) {
+ v_[i*NN+j] = Type();
+ }
+ }
+ }
+
+ if( IsVectorizable<Type>::value && m_ > n_ ) {
+ for( size_t i=n_; i<m_; ++i ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ v_[i*NN+j] = Type();
+ }
+ }
+ }
+
+ swap( m_, n_ );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::logic_error Impossible transpose operation.
+//
+// This function transposes the hybrid matrix in-place. Note that this function can only be used
+// on hybrid matrices whose current dimensions allow an in-place transpose operation. In case the
+// current number of rows is larger than the maximum number of columns or if the current number
+// of columns is larger than the maximum number of rows, an \a std::logic_error is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::ctranspose()
+{
+ using std::swap;
+
+ if( m_ > N || n_ > M ) {
+ BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
+ }
+
+ const size_t maxsize( max( m_, n_ ) );
+ for( size_t i=0UL; i<maxsize; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ cswap( v_[i*NN+j], v_[j*NN+i] );
+ }
+ conjugate( v_[i*NN+i] );
+ }
+
+ if( IsVectorizable<Type>::value && m_ < n_ ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=m_; j<n_; ++j ) {
+ v_[i*NN+j] = Type();
+ }
+ }
+ }
+
+ if( IsVectorizable<Type>::value && m_ > n_ ) {
+ for( size_t i=n_; i<m_; ++i ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ v_[i*NN+j] = Type();
+ }
+ }
+ }
+
+ swap( m_, n_ );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A*=s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the scalar value
+inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<m_; ++i )
+ for( size_t j=0UL; j<n_; ++j )
+ v_[i*NN+j] *= scalar;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two hybrid matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::swap( HybridMatrix& m ) noexcept
+{
+ using std::swap;
+
+ const size_t maxrows( max( m_, m.m_ ) );
+ const size_t maxcols( max( n_, m.n_ ) );
+
+ for( size_t i=0UL; i<maxrows; ++i ) {
+ for( size_t j=0UL; j<maxcols; ++j ) {
+ swap( v_[i*NN+j], m(i,j) );
+ }
+ }
+
+ swap( m_, m.m_ );
+ swap( n_, m.n_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MEMORY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void* HybridMatrix<Type,M,N,SO>::operator new( std::size_t size )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" );
+
+ return allocate<HybridMatrix>( 1UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void* HybridMatrix<Type,M,N,SO>::operator new[]( std::size_t size )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridMatrix ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( HybridMatrix ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<HybridMatrix>( size/sizeof(HybridMatrix) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of the no-throw operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void* HybridMatrix<Type,M,N,SO>::operator new( std::size_t size, const std::nothrow_t& )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" );
+
+ return allocate<HybridMatrix>( 1UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of the no-throw operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void* HybridMatrix<Type,M,N,SO>::operator new[]( std::size_t size, const std::nothrow_t& )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridMatrix ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( HybridMatrix ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<HybridMatrix>( size/sizeof(HybridMatrix) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::operator delete( void* ptr )
+{
+ deallocate( static_cast<HybridMatrix*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::operator delete[]( void* ptr )
+{
+ deallocate( static_cast<HybridMatrix*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of no-throw operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::operator delete( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<HybridMatrix*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of no-throw operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void HybridMatrix<Type,M,N,SO>::operator delete[]( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<HybridMatrix*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the hybrid matrix are intact.
+//
+// \return \a true in case the hybrid matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the hybrid matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline bool HybridMatrix<Type,M,N,SO>::isIntact() const noexcept
+{
+ if( m_ > M || n_ > N )
+ return false;
+
+ if( IsNumeric<Type>::value )
+ {
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=n_; j<NN; ++j ) {
+ if( v_[i*NN+j] != Type() )
+ return false;
+ }
+ }
+
+ for( size_t i=m_; i<M; ++i ) {
+ for( size_t j=0UL; j<NN; ++j ) {
+ if( v_[i*NN+j] != Type() )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool HybridMatrix<Type,M,N,SO>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool HybridMatrix<Type,M,N,SO>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline bool HybridMatrix<Type,M,N,SO>::isAligned() const noexcept
+{
+ return ( usePadding || columns() % SIMDSIZE == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller then the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename HybridMatrix<Type,M,N,SO>::SIMDType
+ HybridMatrix<Type,M,N,SO>::load( size_t i, size_t j ) const noexcept
+{
+ if( usePadding )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename HybridMatrix<Type,M,N,SO>::SIMDType
+ HybridMatrix<Type,M,N,SO>::loada( size_t i, size_t j ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
+
+ return loada( &v_[i*NN+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename HybridMatrix<Type,M,N,SO>::SIMDType
+ HybridMatrix<Type,M,N,SO>::loadu( size_t i, size_t j ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+
+ return loadu( &v_[i*NN+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ HybridMatrix<Type,M,N,SO>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( usePadding )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ HybridMatrix<Type,M,N,SO>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
+
+ storea( &v_[i*NN+j], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ HybridMatrix<Type,M,N,SO>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+
+ storeu( &v_[i*NN+j], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the column index (in case of a
+// row-major matrix) or the row index (in case of a column-major matrix) must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ HybridMatrix<Type,M,N,SO>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
+
+ stream( &v_[i*NN+j], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename HybridMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ HybridMatrix<Type,M,N,SO>::assign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ v_[i*NN+j] = (~rhs)(i,j);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename HybridMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ HybridMatrix<Type,M,N,SO>::assign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ const size_t jpos( ( remainder )?( n_ & size_t(-SIMDSIZE) ):( n_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ store( i, j, (~rhs).load(i,j) );
+ }
+ for( ; remainder && j<n_; ++j ) {
+ v_[i*NN+j] = (~rhs)(i,j);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,SO>::assign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*NN+element->index()] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,SO>::assign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*NN+j] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename HybridMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ HybridMatrix<Type,M,N,SO>::addAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[i*NN+i] += (~rhs)(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ v_[i*NN+j] += (~rhs)(i,j);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename HybridMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ HybridMatrix<Type,M,N,SO>::addAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ store( i, j, load(i,j) + (~rhs).load(i,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ v_[i*NN+j] += (~rhs)(i,j);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,SO>::addAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*NN+element->index()] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,SO>::addAssign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*NN+j] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename HybridMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ HybridMatrix<Type,M,N,SO>::subAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[i*NN+i] -= (~rhs)(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ v_[i*NN+j] -= (~rhs)(i,j);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename HybridMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ HybridMatrix<Type,M,N,SO>::subAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ store( i, j, load(i,j) - (~rhs).load(i,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ v_[i*NN+j] -= (~rhs)(i,j);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,SO>::subAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*NN+element->index()] -= element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,SO>::subAssign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*NN+j] -= element->value();
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of HybridMatrix for column-major matrices.
+// \ingroup hybrid_matrix
+//
+// This specialization of HybridMatrix adapts the class template to the requirements of
+// column-major matrices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+class HybridMatrix<Type,M,N,true> : public DenseMatrix< HybridMatrix<Type,M,N,true>, true >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef HybridMatrix<Type,M,N,true> This; //!< Type of this HybridMatrix instance.
+ typedef DenseMatrix<This,true> BaseType; //!< Base type of this HybridMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef HybridMatrix<Type,M,N,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef HybridMatrix<Type,N,M,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Type* Pointer; //!< Pointer to a non-constant matrix value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant matrix value.
+
+ typedef DenseIterator<Type,usePadding> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,usePadding> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a HybridMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef HybridMatrix<ET,M,N,true> Other; //!< The type of the other HybridMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the element type of the matrix is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline HybridMatrix();
+ explicit inline HybridMatrix( size_t m, size_t n );
+ explicit inline HybridMatrix( size_t m, size_t n, const Type& init );
+ explicit inline HybridMatrix( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other >
+ explicit inline HybridMatrix( size_t m, size_t n, const Other* array );
+
+ template< typename Other, size_t M2, size_t N2 >
+ explicit inline HybridMatrix( const Other (&array)[M2][N2] );
+
+ inline HybridMatrix( const HybridMatrix& m );
+ template< typename MT, bool SO > inline HybridMatrix( const Matrix<MT,SO>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t j ) noexcept;
+ inline ConstPointer data ( size_t j ) const noexcept;
+ inline Iterator begin ( size_t j ) noexcept;
+ inline ConstIterator begin ( size_t j ) const noexcept;
+ inline ConstIterator cbegin( size_t j ) const noexcept;
+ inline Iterator end ( size_t j ) noexcept;
+ inline ConstIterator end ( size_t j ) const noexcept;
+ inline ConstIterator cend ( size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline HybridMatrix& operator=( const Type& set );
+ inline HybridMatrix& operator=( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other, size_t M2, size_t N2 >
+ inline HybridMatrix& operator=( const Other (&array)[M2][N2] );
+
+ inline HybridMatrix& operator= ( const HybridMatrix& rhs );
+ template< typename MT, bool SO > inline HybridMatrix& operator= ( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline HybridMatrix& operator+=( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline HybridMatrix& operator-=( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline HybridMatrix& operator*=( const Matrix<MT,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, HybridMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, HybridMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline constexpr size_t spacing() const noexcept;
+ inline constexpr size_t capacity() const noexcept;
+ inline size_t capacity( size_t j ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t j ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ void resize ( size_t m, size_t n, bool preserve=true );
+ inline void extend ( size_t m, size_t n, bool preserve=true );
+ inline HybridMatrix& transpose();
+ inline HybridMatrix& ctranspose();
+ template< typename Other > inline HybridMatrix& scale( const Other& scalar );
+ inline void swap( HybridMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Memory functions****************************************************************************
+ /*!\name Memory functions */
+ //@{
+ static inline void* operator new ( std::size_t size );
+ static inline void* operator new[]( std::size_t size );
+ static inline void* operator new ( std::size_t size, const std::nothrow_t& );
+ static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
+
+ static inline void operator delete ( void* ptr );
+ static inline void operator delete[]( void* ptr );
+ static inline void operator delete ( void* ptr, const std::nothrow_t& );
+ static inline void operator delete[]( void* ptr, const std::nothrow_t& );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ IsColumnMajorMatrix<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDAdd< Type, ElementType_<MT> >::value &&
+ IsColumnMajorMatrix<MT>::value &&
+ !IsDiagonal<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDSub< Type, ElementType_<MT> >::value &&
+ IsColumnMajorMatrix<MT>::value &&
+ !IsDiagonal<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT, bool SO >
+ inline DisableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT, bool SO >
+ inline EnableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void assign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,false>& rhs );
+
+ template< typename MT, bool SO >
+ inline DisableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT, bool SO >
+ inline EnableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,false>& rhs );
+
+ template< typename MT, bool SO >
+ inline DisableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT, bool SO >
+ inline EnableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Alignment adjustment.
+ enum : size_t { MM = ( usePadding )?( NextMultiple< SizeT<M>, SizeT<SIMDSIZE> >::value ):( M ) };
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ AlignedArray<Type,MM*N> v_; //!< The statically allocated matrix elements.
+ /*!< Access to the matrix elements is gained via the
+ function call operator. */
+ size_t m_; //!< The current number of rows of the matrix.
+ size_t n_; //!< The current number of columns of the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_STATIC_ASSERT( !usePadding || MM % SIMDSIZE == 0UL );
+ BLAZE_STATIC_ASSERT( MM >= M );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for HybridMatrix.
+//
+// All matrix elements are initialized to the default value (i.e. 0 for integral data types).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>::HybridMatrix()
+ : v_() // The statically allocated matrix elements
+ , m_( 0UL ) // The current number of rows of the matrix
+ , n_( 0UL ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<MM*N; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ m \times n \f$. No element initialization is performed!
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This constructor creates a hybrid matrix of size \f$ m \times n \f$, but leaves the elements
+// uninitialized. In case \a m is larger than the maximum allowed number of rows (i.e. \a m > M)
+// or \a n is larger than the maximum allowed number of columns a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>::HybridMatrix( size_t m, size_t n )
+ : v_() // The statically allocated matrix elements
+ , m_( m ) // The current number of rows of the matrix
+ , n_( n ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<MM*N; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a homogenous initialization of all \f$ m \times n \f$ matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param init The initial value of the matrix elements.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This constructor creates a hybrid matrix of size \f$ m \times n \f$ and initializes all
+// matrix elements with the specified value. In case \a m is larger than the maximum allowed
+// number of rows (i.e. \a m > M) or \a n is larger than the maximum allowed number of columns
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>::HybridMatrix( size_t m, size_t n, const Type& init )
+ : v_() // The statically allocated matrix elements
+ , m_( m ) // The current number of rows of the matrix
+ , n_( n ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ for( size_t i=0UL; i<m; ++i )
+ v_[i+j*MM] = init;
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n; j<N; ++j )
+ for( size_t i=0UL; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the matrix by
+// means of an initializer list:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::HybridMatrix<int,3,3,columnMajor> A{ { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix is sized according to the size of the initializer list and all its elements are
+// initialized by the values of the given initializer list. Missing values are initialized as
+// default (as e.g. the value 6 in the example). Note that in case the size of the top-level
+// initializer list exceeds the number of rows or the size of any nested list exceeds the
+// number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>::HybridMatrix( initializer_list< initializer_list<Type> > list )
+ : v_() // The statically allocated matrix elements
+ , m_( list.size() ) // The current number of rows of the matrix
+ , n_( determineColumns( list ) ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( m_ > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n_ > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ v_[i+j*MM] = element;
+ ++j;
+ }
+ if( IsNumeric<Type>::value ) {
+ for( ; j<N; ++j ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+ ++i;
+ }
+
+ BLAZE_INTERNAL_ASSERT( i == m_, "Invalid number of elements detected" );
+
+ if( IsNumeric<Type>::value ) {
+ for( ; i<MM; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a dynamic array:
+
+ \code
+ using blaze::columnMajor;
+
+ int* array = new int[20];
+ // ... Initialization of the dynamic array
+ blaze::HybridMatrix<int,4,5,columnMajor> v( 4UL, 5UL, array );
+ delete[] array;
+ \endcode
+
+// The matrix is sized according to the given size of the array and initialized with the values
+// from the given array. In case \a m is larger than the maximum allowed number of rows (i.e.
+// \a m > M) or \a n is larger than the maximum allowed number of columns a \a std::invalid_argument
+// exception is thrown. Note that it is expected that the given \a array has at least \a m by
+// \a n elements. Providing an array with less elements results in undefined behavior!
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the initialization array
+inline HybridMatrix<Type,M,N,true>::HybridMatrix( size_t m, size_t n, const Other* array )
+ : v_() // The statically allocated matrix elements
+ , m_( m ) // The current number of rows of the matrix
+ , n_( n ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ for( size_t i=0UL; i<m; ++i )
+ v_[i+j*MM] = array[i+j*m];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n; j<N; ++j )
+ for( size_t i=0UL; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a static array:
+
+ \code
+ using blaze::columnMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::HybridMatrix<int,3,3,columnMajor> A( init );
+ \endcode
+
+// The matrix is sized according to the size of the array and initialized with the values from
+// the given array. Missing values are initialized with default values (as e.g. the value 6 in
+// the example).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other // Data type of the initialization array
+ , size_t M2 // Number of rows of the initialization array
+ , size_t N2 > // Number of columns of the initialization array
+inline HybridMatrix<Type,M,N,true>::HybridMatrix( const Other (&array)[M2][N2] )
+ : v_() // The statically allocated matrix elements
+ , m_( M2 ) // The current number of rows of the matrix
+ , n_( N2 ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( M2 <= M );
+ BLAZE_STATIC_ASSERT( N2 <= N );
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ for( size_t j=0UL; j<N2; ++j ) {
+ for( size_t i=0UL; i<M2; ++i )
+ v_[i+j*MM] = array[i][j];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=M2; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=N2; j<N; ++j )
+ for( size_t i=0UL; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for HybridMatrix.
+//
+// \param m Matrix to be copied.
+//
+// The copy constructor is explicitly defined due to the required dynamic memory management
+// and in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>::HybridMatrix( const HybridMatrix& m )
+ : v_() // The statically allocated matrix elements
+ , m_( m.m_ ) // The current number of rows of the matrix
+ , n_( m.n_ ) // The current number of columns of the matrix
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*MM] = m.v_[i+j*MM];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m_; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n_; j<N; ++j )
+ for( size_t i=0UL; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of hybrid matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline HybridMatrix<Type,M,N,true>::HybridMatrix( const Matrix<MT,SO2>& m )
+ : v_() // The statically allocated matrix elements
+ , m_( (~m).rows() ) // The current number of rows of the matrix
+ , n_( (~m).columns() ) // The current number of columns of the matrix
+{
+ using blaze::assign;
+
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( (~m).rows() > M || (~m).columns() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid matrix" );
+ }
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=( IsSparseMatrix<MT>::value ? 0UL : m_ );
+ i<( IsNumeric<Type>::value ? MM : m_ );
+ ++i ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n_; j<N; ++j )
+ for( size_t i=0UL; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ assign( *this, ~m );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::Reference
+ HybridMatrix<Type,M,N,true>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
+ return v_[i+j*MM];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return Reference-to-const to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::ConstReference
+ HybridMatrix<Type,M,N,true>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
+ return v_[i+j*MM];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::Reference
+ HybridMatrix<Type,M,N,true>::at( size_t i, size_t j )
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::ConstReference
+ HybridMatrix<Type,M,N,true>::at( size_t i, size_t j ) const
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the hybrid matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The hybrid matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a column are given by the \c columns() member functions, the total number
+// of elements including padding is given by the \c spacing() member function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::Pointer
+ HybridMatrix<Type,M,N,true>::data() noexcept
+{
+ return v_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the hybrid matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The hybrid matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a column are given by the \c columns() member functions, the total number
+// of elements including padding is given by the \c spacing() member function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::ConstPointer
+ HybridMatrix<Type,M,N,true>::data() const noexcept
+{
+ return v_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::Pointer
+ HybridMatrix<Type,M,N,true>::data( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return v_ + j*MM;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::ConstPointer
+ HybridMatrix<Type,M,N,true>::data( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return v_ + j*MM;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::Iterator
+ HybridMatrix<Type,M,N,true>::begin( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return Iterator( v_ + j*MM );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::ConstIterator
+ HybridMatrix<Type,M,N,true>::begin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*MM );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::ConstIterator
+ HybridMatrix<Type,M,N,true>::cbegin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*MM );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::Iterator
+ HybridMatrix<Type,M,N,true>::end( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return Iterator( v_ + j*MM + M );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::ConstIterator
+ HybridMatrix<Type,M,N,true>::end( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*MM + M );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename HybridMatrix<Type,M,N,true>::ConstIterator
+ HybridMatrix<Type,M,N,true>::cend( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*MM + M );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all matrix elements.
+//
+// \param set Scalar value to be assigned to all matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>&
+ HybridMatrix<Type,M,N,true>::operator=( const Type& set )
+{
+ BLAZE_INTERNAL_ASSERT( m_ <= M, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( n_ <= N, "Invalid number of columns detected" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*MM] = set;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid number of rows for hybrid matrix.
+// \exception std::invalid_argument Invalid number of columns for hybrid matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the matrix
+// by means of an initializer list:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::HybridMatrix<int,3,3,columnMajor> A;
+ A = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix is resized according to the given initializer list and all its elements are
+// assigned the values from the given initializer list. Missing values are initialized as
+// default (as e.g. the value 6 in the example). Note that in case the size of the top-level
+// initializer list exceeds the number of rows or the size of any nested list exceeds the
+// number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>&
+ HybridMatrix<Type,M,N,true>::operator=( initializer_list< initializer_list<Type> > list )
+{
+ const size_t m( list.size() );
+ const size_t n( determineColumns( list ) );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ resize( m, n, false );
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ v_[i+j*MM] = element;
+ ++j;
+ }
+ for( ; j<n_; ++j ) {
+ v_[i+j*MM] = Type();
+ }
+ ++i;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+//
+// This assignment operator offers the option to directly set all elements of the matrix:
+
+ \code
+ using blaze::columnMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::HybridMatrix<int,3UL,3UL,columnMajor> A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other // Data type of the initialization array
+ , size_t M2 // Number of rows of the initialization array
+ , size_t N2 > // Number of columns of the initialization array
+inline HybridMatrix<Type,M,N,true>&
+ HybridMatrix<Type,M,N,true>::operator=( const Other (&array)[M2][N2] )
+{
+ BLAZE_STATIC_ASSERT( M2 <= M );
+ BLAZE_STATIC_ASSERT( N2 <= N );
+
+ resize( M2, N2 );
+
+ for( size_t j=0UL; j<N2; ++j )
+ for( size_t i=0UL; i<M2; ++i )
+ v_[i+j*MM] = array[i][j];
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for HybridMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// Explicit definition of a copy assignment operator for performance reasons.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>&
+ HybridMatrix<Type,M,N,true>::operator=( const HybridMatrix& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_INTERNAL_ASSERT( m_ <= M, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( n_ <= N, "Invalid number of columns detected" );
+
+ resize( rhs.rows(), rhs.columns() );
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to hybrid matrix.
+//
+// This constructor initializes the matrix as a copy of the given matrix. In case the
+// number of rows of the given matrix is not M or the number of columns is not N, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::operator=( const Matrix<MT,SO>& rhs )
+{
+ using blaze::assign;
+
+ typedef TransExprTrait_<This> TT;
+ typedef CTransExprTrait_<This> CT;
+ typedef InvExprTrait_<This> IT;
+
+ if( (~rhs).rows() > M || (~rhs).columns() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to hybrid matrix" );
+ }
+
+ if( IsSame<MT,TT>::value && (~rhs).isAliased( this ) ) {
+ transpose();
+ }
+ else if( IsSame<MT,CT>::value && (~rhs).isAliased( this ) ) {
+ ctranspose();
+ }
+ else if( !IsSame<MT,IT>::value && (~rhs).canAlias( this ) ) {
+ HybridMatrix tmp( ~rhs );
+ resize( tmp.rows(), tmp.columns() );
+ assign( *this, tmp );
+ }
+ else {
+ resize( (~rhs).rows(), (~rhs).columns() );
+ if( IsSparseMatrix<MT>::value )
+ reset();
+ assign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::operator+=( const Matrix<MT,SO>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ addAssign( *this, tmp );
+ }
+ else {
+ addAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::operator-=( const Matrix<MT,SO>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ subAssign( *this, tmp );
+ }
+ else {
+ subAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::operator*=( const Matrix<MT,SO>& rhs )
+{
+ if( n_ != (~rhs).rows() || (~rhs).columns() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const HybridMatrix tmp( *this * (~rhs) );
+ this->operator=( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, HybridMatrix<Type,M,N,true> >&
+ HybridMatrix<Type,M,N,true>::operator*=( Other rhs )
+{
+ using blaze::assign;
+
+ assign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, HybridMatrix<Type,M,N,true> >&
+ HybridMatrix<Type,M,N,true>::operator/=( Other rhs )
+{
+ using blaze::assign;
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ assign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline size_t HybridMatrix<Type,M,N,true>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline size_t HybridMatrix<Type,M,N,true>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two columns.
+//
+// \return The spacing between the beginning of two columns.
+//
+// This function returns the spacing between the beginning of two column, i.e. the total number
+// of elements of a column.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline constexpr size_t HybridMatrix<Type,M,N,true>::spacing() const noexcept
+{
+ return MM;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline constexpr size_t HybridMatrix<Type,M,N,true>::capacity() const noexcept
+{
+ return MM*N;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified column.
+//
+// \param j The index of the column.
+// \return The current capacity of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline size_t HybridMatrix<Type,M,N,true>::capacity( size_t j ) const noexcept
+{
+ UNUSED_PARAMETER( j );
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return MM;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the dense matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline size_t HybridMatrix<Type,M,N,true>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ if( !isDefault( v_[i+j*MM] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified column.
+//
+// \param j The index of the column.
+// \return The number of non-zero elements of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline size_t HybridMatrix<Type,M,N,true>::nonZeros( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t iend( j*MM + m_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=j*MM; i<iend; ++i )
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::reset()
+{
+ using blaze::clear;
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ clear( v_[i+j*MM] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified column to the default initial values.
+//
+// \param j The index of the column.
+// \return void
+//
+// This function reset the values in the specified column to their default value. Note that
+// the capacity of the column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::reset( size_t j )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ for( size_t i=0UL; i<m_; ++i )
+ clear( v_[i+j*MM] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the hybrid matrix.
+//
+// \return void
+//
+// After the clear() function, the size of the matrix is 0.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::clear()
+{
+ resize( 0UL, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the matrix.
+//
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. In case the given
+// number of rows \a m is larger than the maximum number of rows (i.e. if m > M) or in case the
+// given number of columns \a n is larger than the maximum number of column (i.e. if n > N) a
+// \a std::invalid_argument exception is thrown. Note that this function may invalidate all
+// existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
+// matrix. Additionally, during this operation all matrix elements are potentially changed. In
+// order to preserve the old matrix values, the \a preserve flag can be set to \a true.
+//
+// Note that in case the number of rows or columns is increased new matrix elements are not
+// initialized! The following example illustrates the resize operation of a \f$ 2 \times 4 \f$
+// matrix to a \f$ 4 \times 2 \f$ matrix. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & 3 & 4 \\
+ 5 & 6 & 7 & 8 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{2}{c}}
+ 1 & 2 \\
+ 5 & 6 \\
+ x & x \\
+ x & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+void HybridMatrix<Type,M,N,true>::resize( size_t m, size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+
+ if( m > M ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
+ }
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
+ }
+
+ if( IsVectorizable<Type>::value && m < m_ ) {
+ for( size_t j=0UL; j<n; ++j )
+ for( size_t i=m; i<m_; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ if( IsVectorizable<Type>::value && n < n_ ) {
+ for( size_t j=n; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ m_ = m;
+ n_ = n;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Extending the size of the matrix.
+//
+// \param m Number of additional rows.
+// \param n Number of additional columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function increases the matrix size by \a m rows and \a n columns. In case the resulting
+// number of rows or columns is larger than the maximum number of rows or columns (i.e. if m > M
+// or n > N) a \a std::invalid_argument exception is thrown. During this operation, all matrix
+// elements are potentially changed. In order to preserve the old matrix values, the \a preserve
+// flag can be set to \a true.\n
+// Note that new matrix elements are not initialized!
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::extend( size_t m, size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+ resize( m_+m, n_+n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::logic_error Impossible transpose operation.
+//
+// This function transposes the hybrid matrix in-place. Note that this function can only be used
+// on hybrid matrices whose current dimensions allow an in-place transpose operation. In case the
+// current number of rows is larger than the maximum number of columns or if the current number
+// of columns is larger than the maximum number of rows, an \a std::logic_error is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::transpose()
+{
+ using std::swap;
+
+ if( m_ > N || n_ > M ) {
+ BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
+ }
+
+ const size_t maxsize( max( m_, n_ ) );
+ for( size_t j=1UL; j<maxsize; ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ swap( v_[i+j*MM], v_[j+i*MM] );
+ }
+ }
+
+ if( IsVectorizable<Type>::value && n_ < m_ ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=n_; i<m_; ++i ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+ }
+
+ if( IsVectorizable<Type>::value && n_ > m_ ) {
+ for( size_t j=m_; j<n_; ++j ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+ }
+
+ swap( m_, n_ );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::logic_error Impossible transpose operation.
+//
+// This function transposes the hybrid matrix in-place. Note that this function can only be used
+// on hybrid matrices whose current dimensions allow an in-place transpose operation. In case the
+// current number of rows is larger than the maximum number of columns or if the current number
+// of columns is larger than the maximum number of rows, an \a std::logic_error is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::ctranspose()
+{
+ using std::swap;
+
+ if( m_ > N || n_ > M ) {
+ BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
+ }
+
+ const size_t maxsize( max( m_, n_ ) );
+ for( size_t j=0UL; j<maxsize; ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ cswap( v_[i+j*MM], v_[j+i*MM] );
+ }
+ conjugate( v_[j+j*MM] );
+ }
+
+ if( IsVectorizable<Type>::value && n_ < m_ ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=n_; i<m_; ++i ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+ }
+
+ if( IsVectorizable<Type>::value && n_ > m_ ) {
+ for( size_t j=m_; j<n_; ++j ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+ }
+
+ swap( m_, n_ );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A*=s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the scalar value
+inline HybridMatrix<Type,M,N,true>&
+ HybridMatrix<Type,M,N,true>::scale( const Other& scalar )
+{
+ for( size_t j=0UL; j<n_; ++j )
+ for( size_t i=0UL; i<m_; ++i )
+ v_[i+j*MM] *= scalar;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two hybrid matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::swap( HybridMatrix& m ) noexcept
+{
+ using std::swap;
+
+ const size_t maxrows( max( m_, m.m_ ) );
+ const size_t maxcols( max( n_, m.n_ ) );
+
+ for( size_t j=0UL; j<maxcols; ++j ) {
+ for( size_t i=0UL; i<maxrows; ++i ) {
+ swap( v_[i+j*MM], m(i,j) );
+ }
+ }
+
+ swap( m_, m.m_ );
+ swap( n_, m.n_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MEMORY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void* HybridMatrix<Type,M,N,true>::operator new( std::size_t size )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" );
+
+ return allocate<HybridMatrix>( 1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void* HybridMatrix<Type,M,N,true>::operator new[]( std::size_t size )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridMatrix ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( HybridMatrix ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<HybridMatrix>( size/sizeof(HybridMatrix) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of the no-throw operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void* HybridMatrix<Type,M,N,true>::operator new( std::size_t size, const std::nothrow_t& )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" );
+
+ return allocate<HybridMatrix>( 1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of the no-throw operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void* HybridMatrix<Type,M,N,true>::operator new[]( std::size_t size, const std::nothrow_t& )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridMatrix ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( HybridMatrix ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<HybridMatrix>( size/sizeof(HybridMatrix) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::operator delete( void* ptr )
+{
+ deallocate( static_cast<HybridMatrix*>( ptr ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::operator delete[]( void* ptr )
+{
+ deallocate( static_cast<HybridMatrix*>( ptr ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of no-throw operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::operator delete( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<HybridMatrix*>( ptr ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of no-throw operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void HybridMatrix<Type,M,N,true>::operator delete[]( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<HybridMatrix*>( ptr ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the hybrid matrix are intact.
+//
+// \return \a true in case the hybrid matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the hybrid matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline bool HybridMatrix<Type,M,N,true>::isIntact() const noexcept
+{
+ if( m_ > M || n_ > N )
+ return false;
+
+ if( IsNumeric<Type>::value )
+ {
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=m_; i<MM; ++i ) {
+ if( v_[i+j*MM] != Type() )
+ return false;
+ }
+ }
+
+ for( size_t j=n_; j<N; ++j ) {
+ for( size_t i=0UL; i<MM; ++i ) {
+ if( v_[i+j*MM] != Type() )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the foreign expression
+inline bool HybridMatrix<Type,M,N,true>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the foreign expression
+inline bool HybridMatrix<Type,M,N,true>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each column of the matrix are guaranteed to conform to
+// the alignment restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline bool HybridMatrix<Type,M,N,true>::isAligned() const noexcept
+{
+ return ( usePadding || rows() % SIMDSIZE == 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the row index must be a multiple of the number of values inside
+// the SIMD element. This function must \b NOT be called explicitly! It is used internally
+// for the performance optimized evaluation of expression templates. Calling this function
+// explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE typename HybridMatrix<Type,M,N,true>::SIMDType
+ HybridMatrix<Type,M,N,true>::load( size_t i, size_t j ) const noexcept
+{
+ if( usePadding )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE typename HybridMatrix<Type,M,N,true>::SIMDType
+ HybridMatrix<Type,M,N,true>::loada( size_t i, size_t j ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
+
+ return loada( &v_[i+j*MM] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE typename HybridMatrix<Type,M,N,true>::SIMDType
+ HybridMatrix<Type,M,N,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+
+ return loadu( &v_[i+j*MM] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller then the number
+// of columns. Additionally, the row index must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE void
+ HybridMatrix<Type,M,N,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( usePadding )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE void
+ HybridMatrix<Type,M,N,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
+
+ storea( &v_[i+j*MM], value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE void
+ HybridMatrix<Type,M,N,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+
+ storeu( &v_[i+j*MM], value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the row index must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE void
+ HybridMatrix<Type,M,N,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
+
+ stream( &v_[i+j*MM], value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename HybridMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ HybridMatrix<Type,M,N,true>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ v_[i+j*MM] = (~rhs)(i,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename HybridMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ HybridMatrix<Type,M,N,true>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ const size_t ipos( ( remainder )?( m_ & size_t(-SIMDSIZE) ):( m_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, j, (~rhs).load(i,j) );
+ }
+ for( ; remainder && i<m_; ++i ) {
+ v_[i+j*MM] = (~rhs)(i,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,true>::assign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*MM] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,true>::assign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*MM] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename HybridMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ HybridMatrix<Type,M,N,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[j+j*MM] += (~rhs)(j,j);
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ v_[i+j*MM] += (~rhs)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename HybridMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ HybridMatrix<Type,M,N,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, j, load(i,j) + (~rhs).load(i,j) );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ v_[i+j*MM] += (~rhs)(i,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,true>::addAssign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*MM] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,true>::addAssign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*MM] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename HybridMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ HybridMatrix<Type,M,N,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[j+j*MM] -= (~rhs)(j,j);
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ v_[i+j*MM] -= (~rhs)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename HybridMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ HybridMatrix<Type,M,N,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, j, load(i,j) - (~rhs).load(i,j) );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ v_[i+j*MM] -= (~rhs)(i,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,true>::subAssign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ typedef ConstIterator_<MT> RhsConstIterator;
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( RhsConstIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*MM] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void HybridMatrix<Type,M,N,true>::subAssign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
+
+ typedef ConstIterator_<MT> RhsConstIterator;
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( RhsConstIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*MM] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// UNDEFINED CLASS TEMPLATE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of HybridMatrix for zero columns.
+// \ingroup hybrid_matrix
+//
+// This specialization of the HybridMatrix class template is left undefined and therefore
+// prevents the instantiation for zero columns.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , bool SO > // Storage order
+class HybridMatrix<Type,M,0UL,SO>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of HybridMatrix for zero rows.
+// \ingroup hybrid_matrix
+//
+// This specialization of the HybridMatrix class template is left undefined and therefore
+// prevents the instantiation for zero rows.
+*/
+template< typename Type // Data type of the matrix
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+class HybridMatrix<Type,0UL,N,SO>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of HybridMatrix for 0 rows and 0 columns.
+// \ingroup hybrid_matrix
+//
+// This specialization of the HybridMatrix class template is left undefined and therefore
+// prevents the instantiation for 0 rows and 0 columns.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+class HybridMatrix<Type,0UL,0UL,SO>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// STATICMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name HybridMatrix operators */
+//@{
+template< typename Type, size_t M, size_t N, bool SO >
+inline void reset( HybridMatrix<Type,M,N,SO>& m );
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline void reset( HybridMatrix<Type,M,N,SO>& m, size_t i );
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline void clear( HybridMatrix<Type,M,N,SO>& m );
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline bool isDefault( const HybridMatrix<Type,M,N,SO>& m );
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline bool isIntact( const HybridMatrix<Type,M,N,SO>& m ) noexcept;
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline void swap( HybridMatrix<Type,M,N,SO>& a, HybridMatrix<Type,M,N,SO>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given hybrid matrix.
+// \ingroup hybrid_matrix
+//
+// \param m The matrix to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void reset( HybridMatrix<Type,M,N,SO>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column of the given hybrid matrix.
+// \ingroup hybrid_matrix
+//
+// \param m The matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given hybrid matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void reset( HybridMatrix<Type,M,N,SO>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given hybrid matrix.
+// \ingroup hybrid_matrix
+//
+// \param m The matrix to be cleared.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void clear( HybridMatrix<Type,M,N,SO>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given hybrid matrix is in default state.
+// \ingroup hybrid_matrix
+//
+// \param m The hybrid matrix to be tested for its default state.
+// \return \a true in case the given matrix's rows and columns are zero, \a false otherwise.
+//
+// This function checks whether the hybrid matrix is in default (constructed) state, i.e. if
+// it's number of rows and columns is 0. In case it is in default state, the function returns
+// \a true, else it will return \a false. The following example demonstrates the use of the
+// \a isDefault() function:
+
+ \code
+ blaze::HybridMatrix<double,3,5> A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline bool isDefault( const HybridMatrix<Type,M,N,SO>& m )
+{
+ return ( m.rows() == 0UL && m.columns() == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given hybrid matrix are intact.
+// \ingroup hybrid_matrix
+//
+// \param m The hybrid matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the hybrid matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::HybridMatrix<double,3,5> A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline bool isIntact( const HybridMatrix<Type,M,N,SO>& m ) noexcept
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two hybrid matrices.
+// \ingroup hybrid_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void swap( HybridMatrix<Type,M,N,SO>& a, HybridMatrix<Type,M,N,SO>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct HasConstDataAccess< HybridMatrix<T,M,N,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct HasMutableDataAccess< HybridMatrix<T,M,N,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct IsAligned< HybridMatrix<T,M,N,SO> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct IsPadded< HybridMatrix<T,M,N,SO> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct IsResizable< HybridMatrix<T,M,N,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M1, size_t N1, bool SO, typename T2, size_t M2, size_t N2 >
+struct AddTrait< HybridMatrix<T1,M1,N1,SO>, StaticMatrix<T2,M2,N2,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M2, N2, SO >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct AddTrait< HybridMatrix<T1,M1,N1,SO1>, StaticMatrix<T2,M2,N2,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M2, N2, false >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO, typename T2, size_t M2, size_t N2 >
+struct AddTrait< StaticMatrix<T1,M1,N1,SO>, HybridMatrix<T2,M2,N2,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M2, N2, SO >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct AddTrait< StaticMatrix<T1,M1,N1,SO1>, HybridMatrix<T2,M2,N2,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M2, N2, false >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO, typename T2, size_t M2, size_t N2 >
+struct AddTrait< HybridMatrix<T1,M1,N1,SO>, HybridMatrix<T2,M2,N2,SO> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, ( M1 < M2 )?( M1 ):( M2 ), ( N1 < N2 )?( N1 ):( N2 ), SO >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct AddTrait< HybridMatrix<T1,M1,N1,SO1>, HybridMatrix<T2,M2,N2,SO2> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, ( M1 < M2 )?( M1 ):( M2 ), ( N1 < N2 )?( N1 ):( N2 ), false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M1, size_t N1, bool SO, typename T2, size_t M2, size_t N2 >
+struct SubTrait< HybridMatrix<T1,M1,N1,SO>, StaticMatrix<T2,M2,N2,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M2, N2, SO >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct SubTrait< HybridMatrix<T1,M1,N1,SO1>, StaticMatrix<T2,M2,N2,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M2, N2, false >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO, typename T2, size_t M2, size_t N2 >
+struct SubTrait< StaticMatrix<T1,M1,N1,SO>, HybridMatrix<T2,M2,N2,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M2, N2, SO >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct SubTrait< StaticMatrix<T1,M1,N1,SO1>, HybridMatrix<T2,M2,N2,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M2, N2, false >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO, typename T2, size_t M2, size_t N2 >
+struct SubTrait< HybridMatrix<T1,M1,N1,SO>, HybridMatrix<T2,M2,N2,SO> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, ( M1 < M2 )?( M1 ):( M2 ), ( N1 < N2 )?( N1 ):( N2 ), SO >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct SubTrait< HybridMatrix<T1,M1,N1,SO1>, HybridMatrix<T2,M2,N2,SO2> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, ( M1 < M2 )?( M1 ):( M2 ), ( N1 < N2 )?( N1 ):( N2 ), false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MultTrait< HybridMatrix<T1,M,N,SO>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = HybridMatrix< MultTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< T1, HybridMatrix<T2,M,N,SO>, EnableIf_<IsNumeric<T1> > >
+{
+ using Type = HybridMatrix< MultTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, size_t K >
+struct MultTrait< HybridMatrix<T1,M,N,SO>, StaticVector<T2,K,false> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, size_t K, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< StaticVector<T1,K,true>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, size_t K >
+struct MultTrait< HybridMatrix<T1,M,N,SO>, HybridVector<T2,K,false> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, size_t K, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< HybridVector<T1,K,true>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MultTrait< HybridMatrix<T1,M,N,SO>, DynamicVector<T2,false> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< DynamicVector<T1,true>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF >
+struct MultTrait< HybridMatrix<T1,M,N,SO>, CustomVector<T2,AF,PF,false> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< CustomVector<T1,AF,PF,true>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MultTrait< HybridMatrix<T1,M,N,SO>, CompressedVector<T2,false> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< CompressedVector<T1,true>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct MultTrait< HybridMatrix<T1,M1,N1,SO1>, StaticMatrix<T2,M2,N2,SO2> >
+{
+ using Type = HybridMatrix< MultTrait_<T1,T2>, M1, N2, SO1 >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct MultTrait< StaticMatrix<T1,M1,N1,SO1>, HybridMatrix<T2,M2,N2,SO2> >
+{
+ using Type = HybridMatrix< MultTrait_<T1,T2>, M1, N2, SO1 >;
+};
+
+template< typename T1, size_t M1, size_t N1, bool SO1, typename T2, size_t M2, size_t N2, bool SO2 >
+struct MultTrait< HybridMatrix<T1,M1,N1,SO1>, HybridMatrix<T2,M2,N2,SO2> >
+{
+ using Type = HybridMatrix< MultTrait_<T1,T2>, M1, N2, SO1 >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct DivTrait< HybridMatrix<T1,M,N,SO>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = HybridMatrix< DivTrait_<T1,T2>, M, N, SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MathTrait< HybridMatrix<T1,M,N,SO>, HybridMatrix<T2,M,N,SO> >
+{
+ using HighType = HybridMatrix< typename MathTrait<T1,T2>::HighType, M, N, SO >;
+ using LowType = HybridMatrix< typename MathTrait<T1,T2>::LowType , M, N, SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO >
+struct SubmatrixTrait< HybridMatrix<T1,M,N,SO> >
+{
+ using Type = HybridMatrix<T1,M,N,SO>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO >
+struct RowTrait< HybridMatrix<T1,M,N,SO> >
+{
+ using Type = HybridVector<T1,N,true>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO >
+struct ColumnTrait< HybridMatrix<T1,M,N,SO> >
+{
+ using Type = HybridVector<T1,M,false>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/HybridVector.h b/src/cpu/blaze/math/dense/HybridVector.h
new file mode 100644
index 00000000..5c2d4c6f
--- /dev/null
+++ b/src/cpu/blaze/math/dense/HybridVector.h
@@ -0,0 +1,3015 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/HybridVector.h
+// \brief Header file for the HybridVector class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+//
+// * The names of its contributors may not be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_HYBRIDVECTOR_H_
+#define _BLAZE_MATH_DENSE_HYBRIDVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/dense/DenseIterator.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/TransposeFlag.h>
+#include <blaze/util/AlignedArray.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/mpl/NextMultiple.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup hybrid_vector HybridVector
+// \ingroup dense_vector
+*/
+/*!\brief Efficient implementation of a dynamically sized vector with static memory.
+// \ingroup hybrid_vector
+//
+// The HybridVector class template combines the flexibility of a dynamically sized vector with
+// the efficiency and performance of a fixed-size vector. It is implemented as a crossing between
+// the blaze::StaticVector and the blaze::DynamicVector class templates: Similar to the static
+// vector it uses static stack memory instead of dynamically allocated memory and similar to the
+// dynamic vector it can be resized (within the extend of the static memory). The type of the
+// elements, the maximum number of elements and the transpose flag of the vector can be specified
+// via the three template parameters:
+
+ \code
+ template< typename Type, size_t N, bool TF >
+ class HybridVector;
+ \endcode
+
+// - Type: specifies the type of the vector elements. HybridVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - N : specifies the maximum number of vector elements, i.e. the maximum size of the vector.
+// It is expected that HybridVector is only used for tiny and small vectors.
+// - TF : specifies whether the vector is a row vector (\a blaze::rowVector) or a column
+// vector (\a blaze::columnVector). The default value is \a blaze::columnVector.
+//
+// These contiguously stored elements can be directly accessed with the subscript operator. The
+// numbering of the vector elements is
+
+ \f[\left(\begin{array}{*{4}{c}}
+ 0 & 1 & \cdots & N-1 \\
+ \end{array}\right)\f]
+
+// The use of HybridVector is very natural and intuitive. All operations (addition, subtraction,
+// multiplication, scaling, ...) can be performed on all possible combinations of dense and sparse
+// vectors with fitting element types. The following example gives an impression of the use of a
+// 2-dimensional HybridVector:
+
+ \code
+ using blaze::HybridVector;
+ using blaze::CompressedVector;
+ using blaze::StaticMatrix;
+
+ HybridVector<double,2UL> a( 2 ); // Non-initialized 2D vector of size 2
+ a[0] = 1.0; // Initialization of the first element
+ a[1] = 2.0; // Initialization of the second element
+
+ HybridVector<double,2UL> b( 2, 2.0 ); // Directly, homogeneously initialized 2D vector
+ CompressedVector<float> c( 2 ); // Empty sparse single precision vector
+ HybridVector<double,2UL> d; // Default constructed hybrid vector
+ StaticMatrix<double,2UL,2UL> A; // Default constructed static row-major matrix
+
+ d = a + b; // Vector addition between vectors of equal element type
+ d = a - c; // Vector subtraction between a dense and sparse vector with different element types
+ d = a * b; // Component-wise vector multiplication
+
+ a *= 2.0; // In-place scaling of vector
+ d = a * 2.0; // Scaling of vector a
+ d = 2.0 * a; // Scaling of vector a
+
+ d += a - b; // Addition assignment
+ d -= a + c; // Subtraction assignment
+ d *= a * b; // Multiplication assignment
+
+ double scalar = trans( a ) * b; // Scalar/dot/inner product between two vectors
+
+ A = a * trans( b ); // Outer product between two vectors
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF = defaultTransposeFlag > // Transpose flag
+class HybridVector : public DenseVector< HybridVector<Type,N,TF>, TF >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef HybridVector<Type,N,TF> This; //!< Type of this HybridVector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this HybridVector instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef HybridVector<Type,N,!TF> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the vector elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the vector elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const HybridVector& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant vector value.
+ typedef const Type& ConstReference; //!< Reference to a constant vector value.
+ typedef Type* Pointer; //!< Pointer to a non-constant vector value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant vector value.
+
+ typedef DenseIterator<Type,aligned> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,aligned> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a HybridVector with different data/element type.
+ */
+ template< typename ET > // Data type of the other vector
+ struct Rebind {
+ typedef HybridVector<ET,N,TF> Other; //!< The type of the other HybridVector.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
+ in can be optimized via SIMD operations. In case the element type of the vector is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline HybridVector();
+ explicit inline HybridVector( size_t n );
+ explicit inline HybridVector( size_t n, const Type& init );
+ explicit inline HybridVector( initializer_list<Type> list );
+
+ template< typename Other >
+ explicit inline HybridVector( size_t n, const Other* array );
+
+ template< typename Other, size_t M >
+ explicit inline HybridVector( const Other (&array)[M] );
+
+ inline HybridVector( const HybridVector& v );
+ template< typename VT > inline HybridVector( const Vector<VT,TF>& v );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) noexcept;
+ inline ConstReference operator[]( size_t index ) const noexcept;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin () noexcept;
+ inline ConstIterator begin () const noexcept;
+ inline ConstIterator cbegin() const noexcept;
+ inline Iterator end () noexcept;
+ inline ConstIterator end () const noexcept;
+ inline ConstIterator cend () const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline HybridVector& operator=( const Type& rhs );
+ inline HybridVector& operator=( initializer_list<Type> list );
+
+ template< typename Other, size_t M >
+ inline HybridVector& operator=( const Other (&array)[M] );
+
+ inline HybridVector& operator= ( const HybridVector& rhs );
+ template< typename VT > inline HybridVector& operator= ( const Vector<VT,TF>& rhs );
+ template< typename VT > inline HybridVector& operator+=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline HybridVector& operator-=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline HybridVector& operator*=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline HybridVector& operator/=( const DenseVector<VT,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, HybridVector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, HybridVector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline void clear();
+ inline void resize( size_t n, bool preserve=true );
+ inline void extend( size_t n, bool preserve=true );
+ template< typename Other > inline HybridVector& scale( const Other& scalar );
+ inline void swap( HybridVector& v ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Memory functions****************************************************************************
+ /*!\name Memory functions */
+ //@{
+ static inline void* operator new ( std::size_t size );
+ static inline void* operator new[]( std::size_t size );
+ static inline void* operator new ( std::size_t size, const std::nothrow_t& );
+ static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
+
+ static inline void operator delete ( void* ptr );
+ static inline void operator delete[]( void* ptr );
+ static inline void operator delete ( void* ptr, const std::nothrow_t& );
+ static inline void operator delete[]( void* ptr, const std::nothrow_t& );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDAdd< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDSub< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDMult< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDDiv< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Alignment adjustment.
+ enum : size_t { NN = ( usePadding )?( NextMultiple< SizeT<N>, SizeT<SIMDSIZE> >::value ):( N ) };
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ AlignedArray<Type,NN> v_; //!< The statically allocated vector elements.
+ /*!< Access to the vector values is gained via the subscript
+ operator. The order of the elements is
+ \f[\left(\begin{array}{*{4}{c}}
+ 0 & 1 & \cdots & N-1 \\
+ \end{array}\right)\f] */
+ size_t size_; //!< The current size/dimension of the vector.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_STATIC_ASSERT( !usePadding || NN % SIMDSIZE == 0UL );
+ BLAZE_STATIC_ASSERT( NN >= N );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for HybridVector.
+//
+// The size of a default constructed HybridVector is initially set to 0.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline HybridVector<Type,N,TF>::HybridVector()
+ : v_ () // The statically allocated vector elements
+ , size_( 0UL ) // The current size/dimension of the vector
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a vector of size \a n.
+//
+// \param n The size of the vector.
+// \exception std::invalid_argument Invalid size for hybrid vector.
+//
+// This constructor creates a hybrid vector of size \a n and initializes all vector elements to
+// the default value (for instance 0 for integral types). In case \a n is larger than the maximum
+// allowed number of elements (i.e. \a n > N) a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline HybridVector<Type,N,TF>::HybridVector( size_t n )
+ : v_ () // The statically allocated vector elements
+ , size_( n ) // The current size/dimension of the vector
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size for hybrid vector" );
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a homogeneous initialization of all \a n vector elements.
+//
+// \param n The size of the vector.
+// \param init The initial value of the vector elements.
+// \exception std::invalid_argument Invalid size for hybrid vector.
+//
+// This constructor creates a hybrid vector of size \a n and initializes all vector elements with
+// the specified value. In case \a n is larger than the maximum allowed number of elements (i.e.
+// \a n > N) a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline HybridVector<Type,N,TF>::HybridVector( size_t n, const Type& init )
+ : v_ () // The statically allocated vector elements
+ , size_( n ) // The current size/dimension of the vector
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size for hybrid vector" );
+ }
+
+ for( size_t i=0UL; i<n; ++i )
+ v_[i] = init;
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=n; i<NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List initialization of all vector elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of hybrid vector.
+//
+// This constructor provides the option to explicitly initialize the elements of the vector by
+// means of an initializer list:
+
+ \code
+ blaze::HybridVector<double,6UL> v1{ 4.2, 6.3, -1.2 };
+ \endcode
+
+// The vector is sized according to the size of the initializer list and all its elements are
+// initialized by the values of the given initializer list. In case the size of the given list
+// exceeds the maximum size of the hybrid vector (i.e. is larger than \a N), a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline HybridVector<Type,N,TF>::HybridVector( initializer_list<Type> list )
+ : v_ () // The statically allocated vector elements
+ , size_( list.size() ) // The current size/dimension of the vector
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( size_ > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid vector" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), v_.data() ), v_.data()+NN, Type() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all vector elements.
+//
+// \param n The size of the vector.
+// \param array Dynamic array for the initialization.
+// \exception std::invalid_argument Invalid size for hybrid vector.
+//
+// This assignment operator offers the option to directly initialize the elements of the vector
+// with a dynamic array:
+
+ \code
+ double* array = new double[6];
+ // ... Initialization of the dynamic array
+ blaze::HybridVector<double,6> v( array, 6UL );
+ delete[] array;
+ \endcode
+
+// The vector is sized according to the size of the array and initialized with the values from
+// the given array. In case the size of the given array exceeds the maximum size of the hybrid
+// vector (i.e. is larger than \a N), a \a std::invalid_argument exception is thrown.\n
+// Note that it is expected that the given \a array has at least \a n elements. Providing an
+// array with less elements results in undefined behavior!
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the initialization array
+inline HybridVector<Type,N,TF>::HybridVector( size_t n, const Other* array )
+ : v_ () // The statically allocated vector elements
+ , size_( n ) // The current size/dimension of the vector
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid vector" );
+ }
+
+ for( size_t i=0UL; i<n; ++i )
+ v_[i] = array[i];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=n; i<NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all vector elements.
+//
+// \param array M-dimensional array for the initialization.
+//
+// This assignment operator offers the option to directly initialize the elements of the vector
+// with a static array:
+
+ \code
+ const double init[2] = { 1.0, 2.0 };
+ blaze::HybridVector<double,4> v( init );
+ \endcode
+
+// The vector is sized according to the size of the array and initialized with the values from
+// the given array. This constructor only works for arrays with a size smaller-or-equal than the
+// maximum number of elements of the hybrid vector (i.e. M <= N). The attempt to use a larger
+// array will result in a compile time error.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other // Data type of the initialization array
+ , size_t M > // Number of elements of the initialization array
+inline HybridVector<Type,N,TF>::HybridVector( const Other (&array)[M] )
+ : v_ () // The statically allocated vector elements
+ , size_( M ) // The current size/dimension of the vector
+{
+ BLAZE_STATIC_ASSERT( M <= N );
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<M; ++i )
+ v_[i] = array[i];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=M; i<NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for HybridVector.
+//
+// \param v Vector to be copied.
+//
+// The copy constructor is explicitly defined in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline HybridVector<Type,N,TF>::HybridVector( const HybridVector& v )
+ : v_ () // The statically allocated vector elements
+ , size_( v.size_ ) // The current size/dimension of the vector
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] = v.v_[i];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=size_; i<NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different vectors.
+//
+// \param v Vector to be copied.
+// \exception std::invalid_argument Invalid setup of hybrid vector.
+//
+// This constructor initializes the hybrid vector from the given vector. In case the size of
+// the given vector exceeds the maximum size of the hybrid vector (i.e. is larger than \a N),
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the foreign vector
+inline HybridVector<Type,N,TF>::HybridVector( const Vector<VT,TF>& v )
+ : v_ () // The statically allocated vector elements
+ , size_( (~v).size() ) // The current size/dimension of the vector
+{
+ using blaze::assign;
+
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( (~v).size() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid vector" );
+ }
+
+ for( size_t i=( IsSparseVector<VT>::value ? 0UL : size_ );
+ i<( IsNumeric<Type>::value ? NN : size_ ); ++i ) {
+ v_[i] = Type();
+ }
+
+ assign( *this, ~v );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::Reference
+ HybridVector<Type,N,TF>::operator[]( size_t index ) noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference-to-const to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::ConstReference
+ HybridVector<Type,N,TF>::operator[]( size_t index ) const noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::Reference
+ HybridVector<Type,N,TF>::at( size_t index )
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::ConstReference
+ HybridVector<Type,N,TF>::at( size_t index ) const
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the hybrid vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::Pointer HybridVector<Type,N,TF>::data() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the hybrid vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::ConstPointer HybridVector<Type,N,TF>::data() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the hybrid vector.
+//
+// \return Iterator to the first element of the hybrid vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::Iterator HybridVector<Type,N,TF>::begin() noexcept
+{
+ return Iterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the hybrid vector.
+//
+// \return Iterator to the first element of the hybrid vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::ConstIterator HybridVector<Type,N,TF>::begin() const noexcept
+{
+ return ConstIterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the hybrid vector.
+//
+// \return Iterator to the first element of the hybrid vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::ConstIterator HybridVector<Type,N,TF>::cbegin() const noexcept
+{
+ return ConstIterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the hybrid vector.
+//
+// \return Iterator just past the last element of the hybrid vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::Iterator HybridVector<Type,N,TF>::end() noexcept
+{
+ BLAZE_INTERNAL_ASSERT( size_ <= N, "Invalid size detected" );
+ return Iterator( v_ + size_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the hybrid vector.
+//
+// \return Iterator just past the last element of the hybrid vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::ConstIterator HybridVector<Type,N,TF>::end() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( size_ <= N, "Invalid size detected" );
+ return ConstIterator( v_ + size_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the hybrid vector.
+//
+// \return Iterator just past the last element of the hybrid vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename HybridVector<Type,N,TF>::ConstIterator HybridVector<Type,N,TF>::cend() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( size_ <= N, "Invalid size detected" );
+ return ConstIterator( v_ + size_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Homogenous assignment to all vector elements.
+//
+// \param rhs Scalar value to be assigned to all vector elements.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator=( const Type& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ <= N, "Invalid size detected" );
+
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] = rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List assignment to all vector elements.
+//
+// \param list The initializer list.
+// \exception Invalid assignment to hybrid vector.
+//
+// This assignment operator offers the option to directly assign to all elements of the vector
+// by means of an initializer list:
+
+ \code
+ blaze::HybridVector<double,6UL> v;
+ v = { 4.2, 6.3, -1.2 };
+ \endcode
+
+// The vector is resized according to the size of the initializer list and all its elements are
+// assigned the values from the given initializer list. In case the size of the given list exceeds
+// the maximum size of the hybrid vector (i.e. is larger than \a N), a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator=( initializer_list<Type> list )
+{
+ if( list.size() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to hybrid vector" );
+ }
+
+ resize( list.size(), false );
+ std::copy( list.begin(), list.end(), v_.data() );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array assignment to all vector elements.
+//
+// \param array M-dimensional array for the assignment.
+// \return Reference to the assigned vector.
+//
+// This assignment operator offers the option to directly set all elements of the vector:
+
+ \code
+ const double init[2] = { 1.0, 2.0 };
+ blaze::HybridVector<double,4> v;
+ v = init;
+ \endcode
+
+// The vector is sized according to the size of the array and assigned the values of the given
+// array. This assignment operator only works for arrays with a size smaller-or-equal than the
+// maximum number of elements of the hybrid vector. (i.e. M<= N). The attempt to use a larger
+// array will result in a compile time error.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other // Data type of the initialization array
+ , size_t M > // Number of elements of the initialization array
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator=( const Other (&array)[M] )
+{
+ BLAZE_STATIC_ASSERT( M <= N );
+
+ resize( M, false );
+
+ for( size_t i=0UL; i<M; ++i )
+ v_[i] = array[i];
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for HybridVector.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+//
+// Explicit definition of a copy assignment operator for performance reasons.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator=( const HybridVector& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_INTERNAL_ASSERT( size_ <= N, "Invalid size detected" );
+
+ resize( rhs.size() );
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+// \exception std::invalid_argument Invalid assignment to hybrid vector.
+//
+// This constructor initializes the vector as a copy of the given vector. In case the size
+// of the given vector is larger than \a N, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator=( const Vector<VT,TF>& rhs )
+{
+ using blaze::assign;
+
+ if( (~rhs).size() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to hybrid vector" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ HybridVector tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( (~rhs).size(), false );
+ if( IsSparseVector<VT>::value )
+ reset();
+ assign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator+=( const Vector<VT,TF>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ addAssign( *this, tmp );
+ }
+ else {
+ addAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator-=( const Vector<VT,TF>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<VT> tmp( ~rhs );
+ subAssign( *this, tmp );
+ }
+ else {
+ subAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator*=( const Vector<VT,TF>& rhs )
+{
+ using blaze::multAssign;
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( IsSparseVector<VT>::value || (~rhs).canAlias( this ) ) {
+ const HybridVector tmp( *this * (~rhs) );
+ this->operator=( tmp );
+ }
+ else {
+ multAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::operator/=( const DenseVector<VT,TF>& rhs )
+{
+ using blaze::divAssign;
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const HybridVector tmp( *this / (~rhs) );
+ this->operator=( tmp );
+ }
+ else {
+ divAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a vector and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, HybridVector<Type,N,TF> >&
+ HybridVector<Type,N,TF>::operator*=( Other rhs )
+{
+ using blaze::assign;
+
+ assign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a vector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, HybridVector<Type,N,TF> >&
+ HybridVector<Type,N,TF>::operator/=( Other rhs )
+{
+ using blaze::assign;
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ assign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the vector.
+//
+// \return The size of the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline size_t HybridVector<Type,N,TF>::size() const noexcept
+{
+ return size_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the vector.
+//
+// \return The capacity of the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline size_t HybridVector<Type,N,TF>::capacity() const noexcept
+{
+ return NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the vector.
+//
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline size_t HybridVector<Type,N,TF>::nonZeros() const
+{
+ size_t nonzeros( 0 );
+
+ for( size_t i=0UL; i<size_; ++i ) {
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+ }
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::reset()
+{
+ using blaze::clear;
+ for( size_t i=0UL; i<size_; ++i )
+ clear( v_[i] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the vector.
+//
+// \return void
+//
+// After the clear() function, the size of the vector is 0.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::clear()
+{
+ resize( 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the vector.
+//
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid size for hybrid vector.
+//
+// This function resizes the vector to the given size \a n. In case the given size \a n is larger
+// than the maximum number of vector elements (i.e. if n > N) a \a std::invalid_argument exception
+// is thrown. Note that this function may invalidate all existing views (subvectors, ...) on the
+// vector if it used to shrink the vector. Additionally, during this operation all vector elements
+// are potentially changed. In order to preserve the old vector values, the \a preserve flag can be
+// set to \a true.
+//
+// Note that in case the size of the vector is increased new vector elements are not initialized!
+// This is illustrated by the following example, which demonstrates the resizing of a vector of
+// size 2 to a vector of size 4. The new, uninitialized elements are marked with \a x:
+
+ \f[
+ \left(\begin{array}{*{2}{c}}
+ 1 & 2 \\
+ \end{array}\right)
+
+ \Longrightarrow
+
+ \left(\begin{array}{*{4}{c}}
+ 1 & 2 & x & x \\
+ \end{array}\right)
+ \f]
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::resize( size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size for hybrid vector" );
+ }
+
+ if( IsVectorizable<Type>::value && n < size_ ) {
+ for( size_t i=n; i<size_; ++i )
+ v_[i] = Type();
+ }
+
+ size_ = n;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Extending the size of the vector.
+//
+// \param n Number of additional vector elements.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+//
+// This function increases the vector size by \a n elements. In case the resulting size
+// of the vector is larger than the maximum number of vector elements (i.e. if n > N) a
+// \a std::invalid_argument exception is thrown. During this operation, all vector elements
+// are potentially changed. In order to preserve the old vector values, the \a preserve flag
+// can be set to \a true.\n
+// Note that new vector elements are not initialized!
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::extend( size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+ resize( size_+n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}*=s \f$).
+//
+// \param scalar The scalar value for the vector scaling.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline HybridVector<Type,N,TF>& HybridVector<Type,N,TF>::scale( const Other& scalar )
+{
+ for( size_t i=0; i<size_; ++i )
+ v_[i] *= scalar;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two hybrid vectors.
+//
+// \param v The vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::swap( HybridVector& v ) noexcept
+{
+ using std::swap;
+
+ const size_t maxsize( max( size_, v.size_ ) );
+ for( size_t i=0UL; i<maxsize; ++i )
+ swap( v_[i], v.v_[i] );
+ swap( size_, v.size_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MEMORY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticVector class template.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void* HybridVector<Type,N,TF>::operator new( std::size_t size )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( HybridVector ), "Invalid number of bytes detected" );
+
+ return allocate<HybridVector>( 1UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridVector class template.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void* HybridVector<Type,N,TF>::operator new[]( std::size_t size )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridVector ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( HybridVector ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<HybridVector>( size/sizeof(HybridVector) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of the no-throw operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridVector class template.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void* HybridVector<Type,N,TF>::operator new( std::size_t size, const std::nothrow_t& )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( HybridVector ), "Invalid number of bytes detected" );
+
+ return allocate<HybridVector>( 1UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of the no-throw operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the HybridVector class template.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void* HybridVector<Type,N,TF>::operator new[]( std::size_t size, const std::nothrow_t& )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridVector ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( HybridVector ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<HybridVector>( size/sizeof(HybridVector) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::operator delete( void* ptr )
+{
+ deallocate( static_cast<HybridVector*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::operator delete[]( void* ptr )
+{
+ deallocate( static_cast<HybridVector*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of no-throw operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::operator delete( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<HybridVector*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of no-throw operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void HybridVector<Type,N,TF>::operator delete[]( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<HybridVector*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the hybrid vector are intact.
+//
+// \return \a true in case the hybrid vector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the hybrid vector are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline bool HybridVector<Type,N,TF>::isIntact() const noexcept
+{
+ if( size_ > N )
+ return false;
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=size_; i<NN; ++i ) {
+ if( v_[i] != Type() )
+ return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address can alias with the vector. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool HybridVector<Type,N,TF>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address is aliased with the vector. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool HybridVector<Type,N,TF>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is properly aligned in memory.
+//
+// \return \a true in case the vector is aligned, \a false if not.
+//
+// This function returns whether the vector is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of the vector are guaranteed to conform to the alignment
+// restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline bool HybridVector<Type,N,TF>::isAligned() const noexcept
+{
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename HybridVector<Type,N,TF>::SIMDType
+ HybridVector<Type,N,TF>::load( size_t index ) const noexcept
+{
+ return loada( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename HybridVector<Type,N,TF>::SIMDType
+ HybridVector<Type,N,TF>::loada( size_t index ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
+
+ return loada( &v_[index] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename HybridVector<Type,N,TF>::SIMDType
+ HybridVector<Type,N,TF>::loadu( size_t index ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+
+ return loadu( &v_[index] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ HybridVector<Type,N,TF>::store( size_t index, const SIMDType& value ) noexcept
+{
+ storea( index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ HybridVector<Type,N,TF>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
+
+ storea( &v_[index], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense vector.
+// The index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ HybridVector<Type,N,TF>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+
+ storeu( &v_[index], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense vector. The index must be smaller than the number of vector elements and it must be
+// a multiple of the number of values inside the SIMD element. This function must \b NOT be
+// called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ HybridVector<Type,N,TF>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
+
+ stream( &v_[index], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ HybridVector<Type,N,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] = (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ HybridVector<Type,N,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, (~rhs).load(i) );
+ }
+ for( ; remainder && i<size_; ++i ) {
+ v_[i] = (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void HybridVector<Type,N,TF>::assign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ HybridVector<Type,N,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] += (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ HybridVector<Type,N,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, load(i) + (~rhs).load(i) );
+ }
+ for( ; remainder && i<size_; ++i ) {
+ v_[i] += (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void HybridVector<Type,N,TF>::addAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ HybridVector<Type,N,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] -= (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ HybridVector<Type,N,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, load(i) - (~rhs).load(i) );
+ }
+ for( ; remainder && i<size_; ++i ) {
+ v_[i] -= (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void HybridVector<Type,N,TF>::subAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] -= element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ HybridVector<Type,N,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] *= (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ HybridVector<Type,N,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( size_ & size_t(-SIMDSIZE) ):( size_ ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, load(i) * (~rhs).load(i) );
+ }
+ for( ; remainder && i<size_; ++i ) {
+ v_[i] *= (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void HybridVector<Type,N,TF>::multAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ const HybridVector tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = tmp[element->index()] * element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ HybridVector<Type,N,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<size_; ++i )
+ v_[i] /= (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename HybridVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ HybridVector<Type,N,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, load(i) / (~rhs).load(i) );
+ }
+ for( ; i<size_; ++i ) {
+ v_[i] /= (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// UNDEFINED CLASS TEMPLATE SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of HybridVector for 0 elements.
+// \ingroup hybrid_vector
+//
+// This specialization of the HybridVector class template is left undefined and therefore
+// prevents the instantiation for 0 elements.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+class HybridVector<Type,0UL,TF>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// HYBRIDVECTOR OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name HybridVector operators */
+//@{
+template< typename Type, size_t N, bool TF >
+inline void reset( HybridVector<Type,N,TF>& v );
+
+template< typename Type, size_t N, bool TF >
+inline void clear( HybridVector<Type,N,TF>& v );
+
+template< typename Type, size_t N, bool TF >
+inline bool isDefault( const HybridVector<Type,N,TF>& v );
+
+template< typename Type, size_t N, bool TF >
+inline bool isIntact( const HybridVector<Type,N,TF>& v );
+
+template< typename Type, size_t N, bool TF >
+inline void swap( HybridVector<Type,N,TF>& a, HybridVector<Type,N,TF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given hybrid vector.
+// \ingroup hybrid_vector
+//
+// \param v The vector to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void reset( HybridVector<Type,N,TF>& v )
+{
+ v.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given hybrid vector.
+// \ingroup hybrid_vector
+//
+// \param v The vector to be cleared.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void clear( HybridVector<Type,N,TF>& v )
+{
+ v.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given hybrid vector is in default state.
+// \ingroup hybrid_vector
+//
+// \param v The hybrid vector to be tested for its default state.
+// \return \a true in case the given vector's size is zero, \a false otherwise.
+//
+// This function checks whether the hybrid vector is in default (constructed) state, i.e. if
+// it's size is 0. In case it is in default state, the function returns \a true, else it will
+// return \a false. The following example demonstrates the use of the \a isDefault() function:
+
+ \code
+ blaze::HybridVector<double,3> a;
+ // ... Resizing and initialization
+ if( isDefault( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline bool isDefault( const HybridVector<Type,N,TF>& v )
+{
+ return ( v.size() == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given hybrid vector are intact.
+// \ingroup hybrid_vector
+//
+// \param v The hybrid vector to be tested.
+// \return \a true in case the given vector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the hybrid vector are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::HybridVector<double,3> a;
+ // ... Resizing and initialization
+ if( isIntact( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline bool isIntact( const HybridVector<Type,N,TF>& v )
+{
+ return v.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two hybrid vectors.
+// \ingroup hybrid_vector
+//
+// \param a The first vector to be swapped.
+// \param b The second vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void swap( HybridVector<Type,N,TF>& a, HybridVector<Type,N,TF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct HasConstDataAccess< HybridVector<T,N,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct HasMutableDataAccess< HybridVector<T,N,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct IsAligned< HybridVector<T,N,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct IsPadded< HybridVector<T,N,TF> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct IsResizable< HybridVector<T,N,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct AddTrait< HybridVector<T1,M,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct AddTrait< StaticVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, M, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct AddTrait< HybridVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< AddTrait_<T1,T2>, ( M < N )?( M ):( N ), TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct SubTrait< HybridVector<T1,M,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct SubTrait< StaticVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, M, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct SubTrait< HybridVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< SubTrait_<T1,T2>, ( M < N )?( M ):( N ), TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MultTrait< HybridVector<T1,N,TF>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, typename T2, size_t N, bool TF >
+struct MultTrait< T1, HybridVector<T2,N,TF>, EnableIf_<IsNumeric<T1> > >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct MultTrait< HybridVector<T1,M,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t M, typename T2, size_t N >
+struct MultTrait< HybridVector<T1,M,false>, StaticVector<T2,N,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t M, typename T2, size_t N >
+struct MultTrait< HybridVector<T1,M,true>, StaticVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct MultTrait< StaticVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, M, TF >;
+};
+
+template< typename T1, size_t M, typename T2, size_t N >
+struct MultTrait< StaticVector<T1,M,false>, HybridVector<T2,N,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t M, typename T2, size_t N >
+struct MultTrait< StaticVector<T1,M,true>, HybridVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct MultTrait< HybridVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< MultTrait_<T1,T2>, ( M < N )?( M ):( N ), TF >;
+};
+
+template< typename T1, size_t M, typename T2, size_t N >
+struct MultTrait< HybridVector<T1,M,false>, HybridVector<T2,N,true> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t M, typename T2, size_t N >
+struct MultTrait< HybridVector<T1,M,true>, HybridVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CROSSTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct CrossTrait< HybridVector<T1,N,TF>, StaticVector<T2,3UL,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct CrossTrait< StaticVector<T1,3UL,TF>, HybridVector<T2,N,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct CrossTrait< HybridVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct DivTrait< HybridVector<T1,N,TF>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = HybridVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct DivTrait< HybridVector<T1,M,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct DivTrait< StaticVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = StaticVector< DivTrait_<T1,T2>, M, TF >;
+};
+
+template< typename T1, size_t M, bool TF, typename T2, size_t N >
+struct DivTrait< HybridVector<T1,M,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< DivTrait_<T1,T2>, ( M < N )?( M ):( N ), TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MathTrait< HybridVector<T1,N,TF>, HybridVector<T2,N,TF> >
+{
+ using HighType = StaticVector< typename MathTrait<T1,T2>::HighType, N, TF >;
+ using LowType = StaticVector< typename MathTrait<T1,T2>::LowType , N, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF >
+struct SubvectorTrait< HybridVector<T1,N,TF> >
+{
+ using Type = HybridVector<T1,N,TF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/Inversion.h b/src/cpu/blaze/math/dense/Inversion.h
new file mode 100644
index 00000000..9880b6a4
--- /dev/null
+++ b/src/cpu/blaze/math/dense/Inversion.h
@@ -0,0 +1,1126 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/Inversion.h
+// \brief Header file for the dense matrix in-place inversion kernels
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_INVERSION_H_
+#define _BLAZE_MATH_DENSE_INVERSION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/StrictlyTriangular.h>
+#include <blaze/math/dense/StaticMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InversionFlag.h>
+#include <blaze/math/lapack/getrf.h>
+#include <blaze/math/lapack/getri.h>
+#include <blaze/math/lapack/hetrf.h>
+#include <blaze/math/lapack/hetri.h>
+#include <blaze/math/lapack/potrf.h>
+#include <blaze/math/lapack/potri.h>
+#include <blaze/math/lapack/sytrf.h>
+#include <blaze/math/lapack/sytri.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDivisor.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// INVERSION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Inversion functions */
+//@{
+template< typename MT, bool SO >
+inline void invert( DenseMatrix<MT,SO>& dm );
+
+template< InversionFlag IF, typename MT, bool SO >
+inline void invert( DenseMatrix<MT,SO>& dm );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given general dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The general dense matrix to be inverted.
+// \return void
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given general dense \f$ 2 \times 2 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::runtime_error exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert2x2( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 2UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ MT& A( ~dm );
+
+ const ET det( A(0,0)*A(1,1) - A(0,1)*A(1,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ const ET idet( ET(1) / det );
+ const ET a11( A(0,0) * idet );
+
+ A(0,0) = A(1,1) * idet;
+ A(1,0) = -A(1,0) * idet;
+ A(0,1) = -A(0,1) * idet;
+ A(1,1) = a11;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( ~dm ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given general dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The general dense matrix to be inverted.
+// \return void
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given general dense \f$ 3 \times 3 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::runtime_error exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert3x3( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 3UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,3UL,3UL,SO> A( ~dm );
+ MT& B( ~dm );
+
+ B(0,0) = A(1,1)*A(2,2) - A(1,2)*A(2,1);
+ B(1,0) = A(1,2)*A(2,0) - A(1,0)*A(2,2);
+ B(2,0) = A(1,0)*A(2,1) - A(1,1)*A(2,0);
+
+ const ET det( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B(0,1) = A(0,2)*A(2,1) - A(0,1)*A(2,2);
+ B(1,1) = A(0,0)*A(2,2) - A(0,2)*A(2,0);
+ B(2,1) = A(0,1)*A(2,0) - A(0,0)*A(2,1);
+ B(0,2) = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ B(1,2) = A(0,2)*A(1,0) - A(0,0)*A(1,2);
+ B(2,2) = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( ~dm ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given general dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The general dense matrix to be inverted.
+// \return void
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given general dense \f$ 4 \times 4 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::runtime_error exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert4x4( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,4UL,4UL,SO> A( ~dm );
+ MT& B( ~dm );
+
+ ET tmp1( A(2,2)*A(3,3) - A(2,3)*A(3,2) );
+ ET tmp2( A(2,1)*A(3,3) - A(2,3)*A(3,1) );
+ ET tmp3( A(2,1)*A(3,2) - A(2,2)*A(3,1) );
+
+ B(0,0) = A(1,1)*tmp1 - A(1,2)*tmp2 + A(1,3)*tmp3;
+ B(0,1) = A(0,2)*tmp2 - A(0,1)*tmp1 - A(0,3)*tmp3;
+
+ ET tmp4( A(2,0)*A(3,3) - A(2,3)*A(3,0) );
+ ET tmp5( A(2,0)*A(3,2) - A(2,2)*A(3,0) );
+
+ B(1,0) = A(1,2)*tmp4 - A(1,0)*tmp1 - A(1,3)*tmp5;
+ B(1,1) = A(0,0)*tmp1 - A(0,2)*tmp4 + A(0,3)*tmp5;
+
+ tmp1 = A(2,0)*A(3,1) - A(2,1)*A(3,0);
+
+ B(2,0) = A(1,0)*tmp2 - A(1,1)*tmp4 + A(1,3)*tmp1;
+ B(2,1) = A(0,1)*tmp4 - A(0,0)*tmp2 - A(0,3)*tmp1;
+ B(3,0) = A(1,1)*tmp5 - A(1,0)*tmp3 - A(1,2)*tmp1;
+ B(3,1) = A(0,0)*tmp3 - A(0,1)*tmp5 + A(0,2)*tmp1;
+
+ tmp1 = A(0,2)*A(1,3) - A(0,3)*A(1,2);
+ tmp2 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp3 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+
+ B(0,2) = A(3,1)*tmp1 - A(3,2)*tmp2 + A(3,3)*tmp3;
+ B(0,3) = A(2,2)*tmp2 - A(2,1)*tmp1 - A(2,3)*tmp3;
+
+ tmp4 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp5 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+
+ B(1,2) = A(3,2)*tmp4 - A(3,0)*tmp1 - A(3,3)*tmp5;
+ B(1,3) = A(2,0)*tmp1 - A(2,2)*tmp4 + A(2,3)*tmp5;
+
+ tmp1 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+
+ B(2,2) = A(3,0)*tmp2 - A(3,1)*tmp4 + A(3,3)*tmp1;
+ B(2,3) = A(2,1)*tmp4 - A(2,0)*tmp2 - A(2,3)*tmp1;
+ B(3,2) = A(3,1)*tmp5 - A(3,0)*tmp3 - A(3,2)*tmp1;
+ B(3,3) = A(2,0)*tmp3 - A(2,1)*tmp5 + A(2,2)*tmp1;
+
+ const ET det( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) + A(0,3)*B(3,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( ~dm ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given general dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The general dense matrix to be inverted.
+// \return void
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given general dense \f$ 5 \times 5 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::runtime_error exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert5x5( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,5UL,5UL,SO> A( ~dm );
+ MT& B( ~dm );
+
+ ET tmp1 ( A(3,3)*A(4,4) - A(3,4)*A(4,3) );
+ ET tmp2 ( A(3,2)*A(4,4) - A(3,4)*A(4,2) );
+ ET tmp3 ( A(3,2)*A(4,3) - A(3,3)*A(4,2) );
+ ET tmp4 ( A(3,1)*A(4,4) - A(3,4)*A(4,1) );
+ ET tmp5 ( A(3,1)*A(4,3) - A(3,3)*A(4,1) );
+ ET tmp6 ( A(3,1)*A(4,2) - A(3,2)*A(4,1) );
+ ET tmp7 ( A(3,0)*A(4,4) - A(3,4)*A(4,0) );
+ ET tmp8 ( A(3,0)*A(4,3) - A(3,3)*A(4,0) );
+ ET tmp9 ( A(3,0)*A(4,2) - A(3,2)*A(4,0) );
+ ET tmp10( A(3,0)*A(4,1) - A(3,1)*A(4,0) );
+
+ ET tmp11( A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3 );
+ ET tmp12( A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5 );
+ ET tmp13( A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6 );
+ ET tmp14( A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6 );
+ ET tmp15( A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8 );
+ ET tmp16( A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9 );
+ ET tmp17( A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9 );
+
+ B(0,0) = A(1,1)*tmp11 - A(1,2)*tmp12 + A(1,3)*tmp13 - A(1,4)*tmp14;
+ B(0,1) = - A(0,1)*tmp11 + A(0,2)*tmp12 - A(0,3)*tmp13 + A(0,4)*tmp14;
+ B(1,0) = - A(1,0)*tmp11 + A(1,2)*tmp15 - A(1,3)*tmp16 + A(1,4)*tmp17;
+ B(1,1) = A(0,0)*tmp11 - A(0,2)*tmp15 + A(0,3)*tmp16 - A(0,4)*tmp17;
+
+ ET tmp18( A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10 );
+ ET tmp19( A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10 );
+ ET tmp20( A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10 );
+
+ B(2,0) = A(1,0)*tmp12 - A(1,1)*tmp15 + A(1,3)*tmp18 - A(1,4)*tmp19;
+ B(2,1) = - A(0,0)*tmp12 + A(0,1)*tmp15 - A(0,3)*tmp18 + A(0,4)*tmp19;
+ B(3,0) = - A(1,0)*tmp13 + A(1,1)*tmp16 - A(1,2)*tmp18 + A(1,4)*tmp20;
+ B(3,1) = A(0,0)*tmp13 - A(0,1)*tmp16 + A(0,2)*tmp18 - A(0,4)*tmp20;
+ B(4,0) = A(1,0)*tmp14 - A(1,1)*tmp17 + A(1,2)*tmp19 - A(1,3)*tmp20;
+ B(4,1) = - A(0,0)*tmp14 + A(0,1)*tmp17 - A(0,2)*tmp19 + A(0,3)*tmp20;
+
+ tmp11 = A(1,2)*tmp1 - A(1,3)*tmp2 + A(1,4)*tmp3;
+ tmp12 = A(1,1)*tmp1 - A(1,3)*tmp4 + A(1,4)*tmp5;
+ tmp13 = A(1,1)*tmp2 - A(1,2)*tmp4 + A(1,4)*tmp6;
+ tmp14 = A(1,1)*tmp3 - A(1,2)*tmp5 + A(1,3)*tmp6;
+ tmp15 = A(1,0)*tmp1 - A(1,3)*tmp7 + A(1,4)*tmp8;
+ tmp16 = A(1,0)*tmp2 - A(1,2)*tmp7 + A(1,4)*tmp9;
+ tmp17 = A(1,0)*tmp3 - A(1,2)*tmp8 + A(1,3)*tmp9;
+ tmp18 = A(1,0)*tmp4 - A(1,1)*tmp7 + A(1,4)*tmp10;
+ tmp19 = A(1,0)*tmp5 - A(1,1)*tmp8 + A(1,3)*tmp10;
+
+ B(0,2) = A(0,1)*tmp11 - A(0,2)*tmp12 + A(0,3)*tmp13 - A(0,4)*tmp14;
+ B(1,2) = - A(0,0)*tmp11 + A(0,2)*tmp15 - A(0,3)*tmp16 + A(0,4)*tmp17;
+ B(2,2) = A(0,0)*tmp12 - A(0,1)*tmp15 + A(0,3)*tmp18 - A(0,4)*tmp19;
+
+ tmp1 = A(0,2)*A(1,3) - A(0,3)*A(1,2);
+ tmp2 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp3 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ tmp4 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp5 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+ tmp6 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+ tmp7 = A(0,2)*A(1,4) - A(0,4)*A(1,2);
+ tmp8 = A(0,1)*A(1,4) - A(0,4)*A(1,1);
+ tmp9 = A(0,0)*A(1,4) - A(0,4)*A(1,0);
+ tmp10 = A(0,3)*A(1,4) - A(0,4)*A(1,3);
+
+ tmp11 = A(2,2)*tmp10 - A(2,3)*tmp7 + A(2,4)*tmp1;
+ tmp12 = A(2,1)*tmp10 - A(2,3)*tmp8 + A(2,4)*tmp2;
+ tmp13 = A(2,1)*tmp7 - A(2,2)*tmp8 + A(2,4)*tmp3;
+ tmp14 = A(2,1)*tmp1 - A(2,2)*tmp2 + A(2,3)*tmp3;
+ tmp15 = A(2,0)*tmp10 - A(2,3)*tmp9 + A(2,4)*tmp4;
+ tmp16 = A(2,0)*tmp7 - A(2,2)*tmp9 + A(2,4)*tmp5;
+ tmp17 = A(2,0)*tmp1 - A(2,2)*tmp4 + A(2,3)*tmp5;
+
+ B(0,3) = A(4,1)*tmp11 - A(4,2)*tmp12 + A(4,3)*tmp13 - A(4,4)*tmp14;
+ B(0,4) = - A(3,1)*tmp11 + A(3,2)*tmp12 - A(3,3)*tmp13 + A(3,4)*tmp14;
+ B(1,3) = - A(4,0)*tmp11 + A(4,2)*tmp15 - A(4,3)*tmp16 + A(4,4)*tmp17;
+ B(1,4) = A(3,0)*tmp11 - A(3,2)*tmp15 + A(3,3)*tmp16 - A(3,4)*tmp17;
+
+ tmp18 = A(2,0)*tmp8 - A(2,1)*tmp9 + A(2,4)*tmp6;
+ tmp19 = A(2,0)*tmp2 - A(2,1)*tmp4 + A(2,3)*tmp6;
+ tmp20 = A(2,0)*tmp3 - A(2,1)*tmp5 + A(2,2)*tmp6;
+
+ B(2,3) = A(4,0)*tmp12 - A(4,1)*tmp15 + A(4,3)*tmp18 - A(4,4)*tmp19;
+ B(2,4) = - A(3,0)*tmp12 + A(3,1)*tmp15 - A(3,3)*tmp18 + A(3,4)*tmp19;
+ B(3,3) = - A(4,0)*tmp13 + A(4,1)*tmp16 - A(4,2)*tmp18 + A(4,4)*tmp20;
+ B(3,4) = A(3,0)*tmp13 - A(3,1)*tmp16 + A(3,2)*tmp18 - A(3,4)*tmp20;
+ B(4,3) = A(4,0)*tmp14 - A(4,1)*tmp17 + A(4,2)*tmp19 - A(4,3)*tmp20;
+ B(4,4) = - A(3,0)*tmp14 + A(3,1)*tmp17 - A(3,2)*tmp19 + A(3,3)*tmp20;
+
+ tmp11 = A(3,1)*tmp7 - A(3,2)*tmp8 + A(3,4)*tmp3;
+ tmp12 = A(3,0)*tmp7 - A(3,2)*tmp9 + A(3,4)*tmp5;
+ tmp13 = A(3,0)*tmp8 - A(3,1)*tmp9 + A(3,4)*tmp6;
+ tmp14 = A(3,0)*tmp3 - A(3,1)*tmp5 + A(3,2)*tmp6;
+
+ tmp15 = A(3,1)*tmp1 - A(3,2)*tmp2 + A(3,3)*tmp3;
+ tmp16 = A(3,0)*tmp1 - A(3,2)*tmp4 + A(3,3)*tmp5;
+ tmp17 = A(3,0)*tmp2 - A(3,1)*tmp4 + A(3,3)*tmp6;
+
+ B(3,2) = A(4,0)*tmp11 - A(4,1)*tmp12 + A(4,2)*tmp13 - A(4,4)*tmp14;
+ B(4,2) = - A(4,0)*tmp15 + A(4,1)*tmp16 - A(4,2)*tmp17 + A(4,3)*tmp14;
+
+ const ET det( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) + A(0,3)*B(3,0) + A(0,4)*B(4,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( ~dm ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given general dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The general dense matrix to be inverted.
+// \return void
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given general dense \f$ 6 \times 6 \f$ matrix via the rule of Sarrus.
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case a
+// \a std::runtime_error exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert6x6( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ const StaticMatrix<ET,6UL,6UL,SO> A( ~dm );
+ MT& B( ~dm );
+
+ ET tmp1 ( A(4,4)*A(5,5) - A(4,5)*A(5,4) );
+ ET tmp2 ( A(4,3)*A(5,5) - A(4,5)*A(5,3) );
+ ET tmp3 ( A(4,3)*A(5,4) - A(4,4)*A(5,3) );
+ ET tmp4 ( A(4,2)*A(5,5) - A(4,5)*A(5,2) );
+ ET tmp5 ( A(4,2)*A(5,4) - A(4,4)*A(5,2) );
+ ET tmp6 ( A(4,2)*A(5,3) - A(4,3)*A(5,2) );
+ ET tmp7 ( A(4,1)*A(5,5) - A(4,5)*A(5,1) );
+ ET tmp8 ( A(4,1)*A(5,4) - A(4,4)*A(5,1) );
+ ET tmp9 ( A(4,1)*A(5,3) - A(4,3)*A(5,1) );
+ ET tmp10( A(4,1)*A(5,2) - A(4,2)*A(5,1) );
+ ET tmp11( A(4,0)*A(5,5) - A(4,5)*A(5,0) );
+ ET tmp12( A(4,0)*A(5,4) - A(4,4)*A(5,0) );
+ ET tmp13( A(4,0)*A(5,3) - A(4,3)*A(5,0) );
+ ET tmp14( A(4,0)*A(5,2) - A(4,2)*A(5,0) );
+ ET tmp15( A(4,0)*A(5,1) - A(4,1)*A(5,0) );
+
+ ET tmp16( A(3,3)*tmp1 - A(3,4)*tmp2 + A(3,5)*tmp3 );
+ ET tmp17( A(3,2)*tmp1 - A(3,4)*tmp4 + A(3,5)*tmp5 );
+ ET tmp18( A(3,2)*tmp2 - A(3,3)*tmp4 + A(3,5)*tmp6 );
+ ET tmp19( A(3,2)*tmp3 - A(3,3)*tmp5 + A(3,4)*tmp6 );
+ ET tmp20( A(3,1)*tmp1 - A(3,4)*tmp7 + A(3,5)*tmp8 );
+ ET tmp21( A(3,1)*tmp2 - A(3,3)*tmp7 + A(3,5)*tmp9 );
+ ET tmp22( A(3,1)*tmp3 - A(3,3)*tmp8 + A(3,4)*tmp9 );
+ ET tmp23( A(3,1)*tmp4 - A(3,2)*tmp7 + A(3,5)*tmp10 );
+ ET tmp24( A(3,1)*tmp5 - A(3,2)*tmp8 + A(3,4)*tmp10 );
+ ET tmp25( A(3,1)*tmp6 - A(3,2)*tmp9 + A(3,3)*tmp10 );
+ ET tmp26( A(3,0)*tmp1 - A(3,4)*tmp11 + A(3,5)*tmp12 );
+ ET tmp27( A(3,0)*tmp2 - A(3,3)*tmp11 + A(3,5)*tmp13 );
+ ET tmp28( A(3,0)*tmp3 - A(3,3)*tmp12 + A(3,4)*tmp13 );
+ ET tmp29( A(3,0)*tmp4 - A(3,2)*tmp11 + A(3,5)*tmp14 );
+ ET tmp30( A(3,0)*tmp5 - A(3,2)*tmp12 + A(3,4)*tmp14 );
+ ET tmp31( A(3,0)*tmp6 - A(3,2)*tmp13 + A(3,3)*tmp14 );
+ ET tmp32( A(3,0)*tmp7 - A(3,1)*tmp11 + A(3,5)*tmp15 );
+ ET tmp33( A(3,0)*tmp8 - A(3,1)*tmp12 + A(3,4)*tmp15 );
+ ET tmp34( A(3,0)*tmp9 - A(3,1)*tmp13 + A(3,3)*tmp15 );
+ ET tmp35( A(3,0)*tmp10 - A(3,1)*tmp14 + A(3,2)*tmp15 );
+
+ ET tmp36( A(2,2)*tmp16 - A(2,3)*tmp17 + A(2,4)*tmp18 - A(2,5)*tmp19 );
+ ET tmp37( A(2,1)*tmp16 - A(2,3)*tmp20 + A(2,4)*tmp21 - A(2,5)*tmp22 );
+ ET tmp38( A(2,1)*tmp17 - A(2,2)*tmp20 + A(2,4)*tmp23 - A(2,5)*tmp24 );
+ ET tmp39( A(2,1)*tmp18 - A(2,2)*tmp21 + A(2,3)*tmp23 - A(2,5)*tmp25 );
+ ET tmp40( A(2,1)*tmp19 - A(2,2)*tmp22 + A(2,3)*tmp24 - A(2,4)*tmp25 );
+ ET tmp41( A(2,0)*tmp16 - A(2,3)*tmp26 + A(2,4)*tmp27 - A(2,5)*tmp28 );
+ ET tmp42( A(2,0)*tmp17 - A(2,2)*tmp26 + A(2,4)*tmp29 - A(2,5)*tmp30 );
+ ET tmp43( A(2,0)*tmp18 - A(2,2)*tmp27 + A(2,3)*tmp29 - A(2,5)*tmp31 );
+ ET tmp44( A(2,0)*tmp19 - A(2,2)*tmp28 + A(2,3)*tmp30 - A(2,4)*tmp31 );
+
+ B(0,0) = A(1,1)*tmp36 - A(1,2)*tmp37 + A(1,3)*tmp38 - A(1,4)*tmp39 + A(1,5)*tmp40;
+ B(0,1) = - A(0,1)*tmp36 + A(0,2)*tmp37 - A(0,3)*tmp38 + A(0,4)*tmp39 - A(0,5)*tmp40;
+ B(1,0) = - A(1,0)*tmp36 + A(1,2)*tmp41 - A(1,3)*tmp42 + A(1,4)*tmp43 - A(1,5)*tmp44;
+ B(1,1) = A(0,0)*tmp36 - A(0,2)*tmp41 + A(0,3)*tmp42 - A(0,4)*tmp43 + A(0,5)*tmp44;
+
+ ET tmp45( A(2,0)*tmp20 - A(2,1)*tmp26 + A(2,4)*tmp32 - A(2,5)*tmp33 );
+ ET tmp46( A(2,0)*tmp21 - A(2,1)*tmp27 + A(2,3)*tmp32 - A(2,5)*tmp34 );
+ ET tmp47( A(2,0)*tmp22 - A(2,1)*tmp28 + A(2,3)*tmp33 - A(2,4)*tmp34 );
+ ET tmp48( A(2,0)*tmp23 - A(2,1)*tmp29 + A(2,2)*tmp32 - A(2,5)*tmp35 );
+ ET tmp49( A(2,0)*tmp24 - A(2,1)*tmp30 + A(2,2)*tmp33 - A(2,4)*tmp35 );
+
+ B(2,0) = A(1,0)*tmp37 - A(1,1)*tmp41 + A(1,3)*tmp45 - A(1,4)*tmp46 + A(1,5)*tmp47;
+ B(2,1) = - A(0,0)*tmp37 + A(0,1)*tmp41 - A(0,3)*tmp45 + A(0,4)*tmp46 - A(0,5)*tmp47;
+ B(3,0) = - A(1,0)*tmp38 + A(1,1)*tmp42 - A(1,2)*tmp45 + A(1,4)*tmp48 - A(1,5)*tmp49;
+ B(3,1) = A(0,0)*tmp38 - A(0,1)*tmp42 + A(0,2)*tmp45 - A(0,4)*tmp48 + A(0,5)*tmp49;
+
+ ET tmp50( A(2,0)*tmp25 - A(2,1)*tmp31 + A(2,2)*tmp34 - A(2,3)*tmp35 );
+
+ B(4,0) = A(1,0)*tmp39 - A(1,1)*tmp43 + A(1,2)*tmp46 - A(1,3)*tmp48 + A(1,5)*tmp50;
+ B(4,1) = - A(0,0)*tmp39 + A(0,1)*tmp43 - A(0,2)*tmp46 + A(0,3)*tmp48 - A(0,5)*tmp50;
+ B(5,0) = - A(1,0)*tmp40 + A(1,1)*tmp44 - A(1,2)*tmp47 + A(1,3)*tmp49 - A(1,4)*tmp50;
+ B(5,1) = A(0,0)*tmp40 - A(0,1)*tmp44 + A(0,2)*tmp47 - A(0,3)*tmp49 + A(0,4)*tmp50;
+
+ tmp36 = A(1,2)*tmp16 - A(1,3)*tmp17 + A(1,4)*tmp18 - A(1,5)*tmp19;
+ tmp37 = A(1,1)*tmp16 - A(1,3)*tmp20 + A(1,4)*tmp21 - A(1,5)*tmp22;
+ tmp38 = A(1,1)*tmp17 - A(1,2)*tmp20 + A(1,4)*tmp23 - A(1,5)*tmp24;
+ tmp39 = A(1,1)*tmp18 - A(1,2)*tmp21 + A(1,3)*tmp23 - A(1,5)*tmp25;
+ tmp40 = A(1,1)*tmp19 - A(1,2)*tmp22 + A(1,3)*tmp24 - A(1,4)*tmp25;
+ tmp41 = A(1,0)*tmp16 - A(1,3)*tmp26 + A(1,4)*tmp27 - A(1,5)*tmp28;
+ tmp42 = A(1,0)*tmp17 - A(1,2)*tmp26 + A(1,4)*tmp29 - A(1,5)*tmp30;
+ tmp43 = A(1,0)*tmp18 - A(1,2)*tmp27 + A(1,3)*tmp29 - A(1,5)*tmp31;
+ tmp44 = A(1,0)*tmp19 - A(1,2)*tmp28 + A(1,3)*tmp30 - A(1,4)*tmp31;
+ tmp45 = A(1,0)*tmp20 - A(1,1)*tmp26 + A(1,4)*tmp32 - A(1,5)*tmp33;
+ tmp46 = A(1,0)*tmp21 - A(1,1)*tmp27 + A(1,3)*tmp32 - A(1,5)*tmp34;
+ tmp47 = A(1,0)*tmp22 - A(1,1)*tmp28 + A(1,3)*tmp33 - A(1,4)*tmp34;
+ tmp48 = A(1,0)*tmp23 - A(1,1)*tmp29 + A(1,2)*tmp32 - A(1,5)*tmp35;
+ tmp49 = A(1,0)*tmp24 - A(1,1)*tmp30 + A(1,2)*tmp33 - A(1,4)*tmp35;
+ tmp50 = A(1,0)*tmp25 - A(1,1)*tmp31 + A(1,2)*tmp34 - A(1,3)*tmp35;
+
+ B(0,2) = A(0,1)*tmp36 - A(0,2)*tmp37 + A(0,3)*tmp38 - A(0,4)*tmp39 + A(0,5)*tmp40;
+ B(1,2) = - A(0,0)*tmp36 + A(0,2)*tmp41 - A(0,3)*tmp42 + A(0,4)*tmp43 - A(0,5)*tmp44;
+ B(2,2) = A(0,0)*tmp37 - A(0,1)*tmp41 + A(0,3)*tmp45 - A(0,4)*tmp46 + A(0,5)*tmp47;
+ B(3,2) = - A(0,0)*tmp38 + A(0,1)*tmp42 - A(0,2)*tmp45 + A(0,4)*tmp48 - A(0,5)*tmp49;
+ B(4,2) = A(0,0)*tmp39 - A(0,1)*tmp43 + A(0,2)*tmp46 - A(0,3)*tmp48 + A(0,5)*tmp50;
+ B(5,2) = - A(0,0)*tmp40 + A(0,1)*tmp44 - A(0,2)*tmp47 + A(0,3)*tmp49 - A(0,4)*tmp50;
+
+ tmp1 = A(0,3)*A(1,4) - A(0,4)*A(1,3);
+ tmp2 = A(0,2)*A(1,4) - A(0,4)*A(1,2);
+ tmp3 = A(0,2)*A(1,3) - A(0,3)*A(1,2);
+ tmp4 = A(0,1)*A(1,4) - A(0,4)*A(1,1);
+ tmp5 = A(0,1)*A(1,3) - A(0,3)*A(1,1);
+ tmp6 = A(0,1)*A(1,2) - A(0,2)*A(1,1);
+ tmp7 = A(0,0)*A(1,4) - A(0,4)*A(1,0);
+ tmp8 = A(0,0)*A(1,3) - A(0,3)*A(1,0);
+ tmp9 = A(0,0)*A(1,2) - A(0,2)*A(1,0);
+ tmp10 = A(0,0)*A(1,1) - A(0,1)*A(1,0);
+ tmp11 = A(0,3)*A(1,5) - A(0,5)*A(1,3);
+ tmp12 = A(0,2)*A(1,5) - A(0,5)*A(1,2);
+ tmp13 = A(0,1)*A(1,5) - A(0,5)*A(1,1);
+ tmp14 = A(0,0)*A(1,5) - A(0,5)*A(1,0);
+ tmp15 = A(0,4)*A(1,5) - A(0,5)*A(1,4);
+
+ tmp16 = A(2,3)*tmp15 - A(2,4)*tmp11 + A(2,5)*tmp1;
+ tmp17 = A(2,2)*tmp15 - A(2,4)*tmp12 + A(2,5)*tmp2;
+ tmp18 = A(2,2)*tmp11 - A(2,3)*tmp12 + A(2,5)*tmp3;
+ tmp19 = A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3;
+ tmp20 = A(2,1)*tmp15 - A(2,4)*tmp13 + A(2,5)*tmp4;
+ tmp21 = A(2,1)*tmp11 - A(2,3)*tmp13 + A(2,5)*tmp5;
+ tmp22 = A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5;
+ tmp23 = A(2,1)*tmp12 - A(2,2)*tmp13 + A(2,5)*tmp6;
+ tmp24 = A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6;
+ tmp25 = A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6;
+ tmp26 = A(2,0)*tmp15 - A(2,4)*tmp14 + A(2,5)*tmp7;
+ tmp27 = A(2,0)*tmp11 - A(2,3)*tmp14 + A(2,5)*tmp8;
+ tmp28 = A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8;
+ tmp29 = A(2,0)*tmp12 - A(2,2)*tmp14 + A(2,5)*tmp9;
+ tmp30 = A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9;
+ tmp31 = A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9;
+ tmp32 = A(2,0)*tmp13 - A(2,1)*tmp14 + A(2,5)*tmp10;
+ tmp33 = A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10;
+ tmp34 = A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10;
+ tmp35 = A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10;
+
+ tmp36 = A(3,2)*tmp16 - A(3,3)*tmp17 + A(3,4)*tmp18 - A(3,5)*tmp19;
+ tmp37 = A(3,1)*tmp16 - A(3,3)*tmp20 + A(3,4)*tmp21 - A(3,5)*tmp22;
+ tmp38 = A(3,1)*tmp17 - A(3,2)*tmp20 + A(3,4)*tmp23 - A(3,5)*tmp24;
+ tmp39 = A(3,1)*tmp18 - A(3,2)*tmp21 + A(3,3)*tmp23 - A(3,5)*tmp25;
+ tmp40 = A(3,1)*tmp19 - A(3,2)*tmp22 + A(3,3)*tmp24 - A(3,4)*tmp25;
+ tmp41 = A(3,0)*tmp16 - A(3,3)*tmp26 + A(3,4)*tmp27 - A(3,5)*tmp28;
+ tmp42 = A(3,0)*tmp17 - A(3,2)*tmp26 + A(3,4)*tmp29 - A(3,5)*tmp30;
+ tmp43 = A(3,0)*tmp18 - A(3,2)*tmp27 + A(3,3)*tmp29 - A(3,5)*tmp31;
+ tmp44 = A(3,0)*tmp19 - A(3,2)*tmp28 + A(3,3)*tmp30 - A(3,4)*tmp31;
+
+ B(0,4) = - A(5,1)*tmp36 + A(5,2)*tmp37 - A(5,3)*tmp38 + A(5,4)*tmp39 - A(5,5)*tmp40;
+ B(0,5) = A(4,1)*tmp36 - A(4,2)*tmp37 + A(4,3)*tmp38 - A(4,4)*tmp39 + A(4,5)*tmp40;
+ B(1,4) = A(5,0)*tmp36 - A(5,2)*tmp41 + A(5,3)*tmp42 - A(5,4)*tmp43 + A(5,5)*tmp44;
+ B(1,5) = - A(4,0)*tmp36 + A(4,2)*tmp41 - A(4,3)*tmp42 + A(4,4)*tmp43 - A(4,5)*tmp44;
+
+ tmp45 = A(3,0)*tmp20 - A(3,1)*tmp26 + A(3,4)*tmp32 - A(3,5)*tmp33;
+ tmp46 = A(3,0)*tmp21 - A(3,1)*tmp27 + A(3,3)*tmp32 - A(3,5)*tmp34;
+ tmp47 = A(3,0)*tmp22 - A(3,1)*tmp28 + A(3,3)*tmp33 - A(3,4)*tmp34;
+ tmp48 = A(3,0)*tmp23 - A(3,1)*tmp29 + A(3,2)*tmp32 - A(3,5)*tmp35;
+ tmp49 = A(3,0)*tmp24 - A(3,1)*tmp30 + A(3,2)*tmp33 - A(3,4)*tmp35;
+
+ B(2,4) = - A(5,0)*tmp37 + A(5,1)*tmp41 - A(5,3)*tmp45 + A(5,4)*tmp46 - A(5,5)*tmp47;
+ B(2,5) = A(4,0)*tmp37 - A(4,1)*tmp41 + A(4,3)*tmp45 - A(4,4)*tmp46 + A(4,5)*tmp47;
+ B(3,4) = A(5,0)*tmp38 - A(5,1)*tmp42 + A(5,2)*tmp45 - A(5,4)*tmp48 + A(5,5)*tmp49;
+ B(3,5) = - A(4,0)*tmp38 + A(4,1)*tmp42 - A(4,2)*tmp45 + A(4,4)*tmp48 - A(4,5)*tmp49;
+
+ tmp50 = A(3,0)*tmp25 - A(3,1)*tmp31 + A(3,2)*tmp34 - A(3,3)*tmp35;
+
+ B(4,4) = - A(5,0)*tmp39 + A(5,1)*tmp43 - A(5,2)*tmp46 + A(5,3)*tmp48 - A(5,5)*tmp50;
+ B(4,5) = A(4,0)*tmp39 - A(4,1)*tmp43 + A(4,2)*tmp46 - A(4,3)*tmp48 + A(4,5)*tmp50;
+ B(5,4) = A(5,0)*tmp40 - A(5,1)*tmp44 + A(5,2)*tmp47 - A(5,3)*tmp49 + A(5,4)*tmp50;
+ B(5,5) = - A(4,0)*tmp40 + A(4,1)*tmp44 - A(4,2)*tmp47 + A(4,3)*tmp49 - A(4,4)*tmp50;
+
+ tmp36 = A(4,2)*tmp16 - A(4,3)*tmp17 + A(4,4)*tmp18 - A(4,5)*tmp19;
+ tmp37 = A(4,1)*tmp16 - A(4,3)*tmp20 + A(4,4)*tmp21 - A(4,5)*tmp22;
+ tmp38 = A(4,1)*tmp17 - A(4,2)*tmp20 + A(4,4)*tmp23 - A(4,5)*tmp24;
+ tmp39 = A(4,1)*tmp18 - A(4,2)*tmp21 + A(4,3)*tmp23 - A(4,5)*tmp25;
+ tmp40 = A(4,1)*tmp19 - A(4,2)*tmp22 + A(4,3)*tmp24 - A(4,4)*tmp25;
+ tmp41 = A(4,0)*tmp16 - A(4,3)*tmp26 + A(4,4)*tmp27 - A(4,5)*tmp28;
+ tmp42 = A(4,0)*tmp17 - A(4,2)*tmp26 + A(4,4)*tmp29 - A(4,5)*tmp30;
+ tmp43 = A(4,0)*tmp18 - A(4,2)*tmp27 + A(4,3)*tmp29 - A(4,5)*tmp31;
+ tmp44 = A(4,0)*tmp19 - A(4,2)*tmp28 + A(4,3)*tmp30 - A(4,4)*tmp31;
+ tmp45 = A(4,0)*tmp20 - A(4,1)*tmp26 + A(4,4)*tmp32 - A(4,5)*tmp33;
+ tmp46 = A(4,0)*tmp21 - A(4,1)*tmp27 + A(4,3)*tmp32 - A(4,5)*tmp34;
+ tmp47 = A(4,0)*tmp22 - A(4,1)*tmp28 + A(4,3)*tmp33 - A(4,4)*tmp34;
+ tmp48 = A(4,0)*tmp23 - A(4,1)*tmp29 + A(4,2)*tmp32 - A(4,5)*tmp35;
+ tmp49 = A(4,0)*tmp24 - A(4,1)*tmp30 + A(4,2)*tmp33 - A(4,4)*tmp35;
+ tmp50 = A(4,0)*tmp25 - A(4,1)*tmp31 + A(4,2)*tmp34 - A(4,3)*tmp35;
+
+ B(0,3) = A(5,1)*tmp36 - A(5,2)*tmp37 + A(5,3)*tmp38 - A(5,4)*tmp39 + A(5,5)*tmp40;
+ B(1,3) = - A(5,0)*tmp36 + A(5,2)*tmp41 - A(5,3)*tmp42 + A(5,4)*tmp43 - A(5,5)*tmp44;
+ B(2,3) = A(5,0)*tmp37 - A(5,1)*tmp41 + A(5,3)*tmp45 - A(5,4)*tmp46 + A(5,5)*tmp47;
+ B(3,3) = - A(5,0)*tmp38 + A(5,1)*tmp42 - A(5,2)*tmp45 + A(5,4)*tmp48 - A(5,5)*tmp49;
+ B(4,3) = A(5,0)*tmp39 - A(5,1)*tmp43 + A(5,2)*tmp46 - A(5,3)*tmp48 + A(5,5)*tmp50;
+ B(5,3) = - A(5,0)*tmp40 + A(5,1)*tmp44 - A(5,2)*tmp47 + A(5,3)*tmp49 - A(5,4)*tmp50;
+
+ const ET det( A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0) +
+ A(0,3)*B(3,0) + A(0,4)*B(4,0) + A(0,5)*B(5,0) );
+
+ if( !isDivisor( det ) ) {
+ BLAZE_THROW_DIVISION_BY_ZERO( "Inversion of singular matrix failed" );
+ }
+
+ B /= det;
+
+ BLAZE_INTERNAL_ASSERT( isIntact( ~dm ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given dense matrix by means of the most suited matrix inversion
+// algorithm. The matrix inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByDefault( DenseMatrix<MT,SO>& dm )
+{
+ invertByLU( ~dm );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place LU-based inversion of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given dense matrix by means of an LU decomposition. The matrix
+// inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLU( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ const size_t n( min( (~dm).rows(), (~dm).columns() ) );
+ const std::unique_ptr<int[]> ipiv( new int[n] );
+
+ getrf( ~dm, ipiv.get() );
+ getri( ~dm, ipiv.get() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given symmetric dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense matrix by means of a Bunch-Kaufman decomposition.
+// The matrix inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLDLT( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_USER_ASSERT( isSymmetric( ~dm ), "Invalid non-symmetric matrix detected" );
+
+ const char uplo( ( SO )?( 'L' ):( 'U' ) );
+ const std::unique_ptr<int[]> ipiv( new int[(~dm).rows()] );
+
+ sytrf( ~dm, uplo, ipiv.get() );
+ sytri( ~dm, uplo, ipiv.get() );
+
+ if( SO ) {
+ for( size_t i=1UL; i<(~dm).rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ (~dm)(j,i) = (~dm)(i,j);
+ }
+ }
+ }
+ else {
+ for( size_t j=1UL; j<(~dm).columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ (~dm)(j,i) = (~dm)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given symmetric dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given symmetric dense matrix by means of a Bunch-Kaufman decomposition.
+// The matrix inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline EnableIf_<IsBuiltin< ElementType_<MT> > >
+ invertByLDLH( DenseMatrix<MT,SO>& dm )
+{
+ invertByLDLT( ~dm );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Bunch-Kaufman-based inversion of the given Hermitian dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given Hermitian dense matrix by means of a Bunch-Kaufman decomposition.
+// The matrix inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline EnableIf_<IsComplex< ElementType_<MT> > >
+ invertByLDLH( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_USER_ASSERT( isHermitian( ~dm ), "Invalid non-Hermitian matrix detected" );
+
+ const char uplo( ( SO )?( 'L' ):( 'U' ) );
+ const std::unique_ptr<int[]> ipiv( new int[(~dm).rows()] );
+
+ hetrf( ~dm, uplo, ipiv.get() );
+ hetri( ~dm, uplo, ipiv.get() );
+
+ if( SO ) {
+ for( size_t i=1UL; i<(~dm).rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ (~dm)(j,i) = conj( (~dm)(i,j) );
+ }
+ }
+ }
+ else {
+ for( size_t j=1UL; j<(~dm).columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ (~dm)(j,i) = conj( (~dm)(i,j) );
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place Cholesky-based inversion of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given dense matrix by means of a Cholesky decomposition. The matrix
+// inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertByLLH( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_USER_ASSERT( isHermitian( ~dm ), "Invalid non-symmetric matrix detected" );
+
+ const char uplo( ( SO )?( 'L' ):( 'U' ) );
+
+ potrf( ~dm, uplo );
+ potri( ~dm, uplo );
+
+ if( SO ) {
+ for( size_t i=1UL; i<(~dm).rows(); ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ (~dm)(j,i) = conj( (~dm)(i,j) );
+ }
+ }
+ }
+ else {
+ for( size_t j=1UL; j<(~dm).columns(); ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ (~dm)(j,i) = conj( (~dm)(i,j) );
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given dense square matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given dense square matrix via the specified matrix inversion
+// algorithm \a IF:
+
+ \code
+ invertNxN<byLU>( A ); // Inversion of a general matrix
+ invertNxN<byLDLT>( A ); // Inversion of a symmetric indefinite matrix
+ invertNxN<byLDLH>( A ); // Inversion of a Hermitian indefinite matrix
+ invertNxN<byLLH>( A ); // Inversion of a Hermitian positive definite matrix
+ \endcode
+
+// The matrix inversion fails if the given matrix is singular and not invertible. In this case
+// a \a std::runtime_error exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< InversionFlag IF // Inversion algorithm
+ , typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invertNxN( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( ~dm ), "Non-square matrix detected" );
+
+ switch( IF ) {
+ case byDefault: invertByDefault( ~dm ); break;
+ case byLU : invertByLU ( ~dm ); break;
+ case byLDLT : invertByLDLT ( ~dm ); break;
+ case byLDLH : invertByLDLH ( ~dm ); break;
+ case byLLH : invertByLLH ( ~dm ); break;
+ default: BLAZE_INTERNAL_ASSERT( false, "Unhandled case detected" );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( ~dm ), "Broken invariant detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given dense square matrix. The matrix inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert( DenseMatrix<MT,SO>& dm )
+{
+ invert<byDefault>( ~dm );
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function inverts the given dense matrix by means of the specified matrix inversion
+// algorithm \c IF:
+
+ \code
+ invert<byLU>( A ); // Inversion of a general matrix
+ invert<byLDLT>( A ); // Inversion of a symmetric indefinite matrix
+ invert<byLDLH>( A ); // Inversion of a Hermitian indefinite matrix
+ invert<byLLH>( A ); // Inversion of a Hermitian positive definite matrix
+ \endcode
+
+// The matrix inversion fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases either a compilation error is created if the failure can be predicted at
+// compile time or an exception is thrown.
+//
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a dm may already have been modified.
+*/
+template< InversionFlag IF // Inversion algorithm
+ , typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void invert( DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ if( !isSquare( ~dm ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ switch( (~dm).rows() ) {
+ case 0UL: break;
+ case 1UL: invert( (~dm)(0,0) ); break;
+ case 2UL: invert2x2 ( ~dm ); break;
+ case 3UL: invert3x3 ( ~dm ); break;
+ case 4UL: invert4x4 ( ~dm ); break;
+ case 5UL: invert5x5 ( ~dm ); break;
+ case 6UL: invert6x6 ( ~dm ); break;
+ default : invertNxN<IF>( ~dm ); break;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( ~dm ), "Broken invariant detected" );
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/LLH.h b/src/cpu/blaze/math/dense/LLH.h
new file mode 100644
index 00000000..45b111ce
--- /dev/null
+++ b/src/cpu/blaze/math/dense/LLH.h
@@ -0,0 +1,175 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/LLH.h
+// \brief Header file for the dense matrix in-place Cholesky (LLH) decomposition
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_LLH_H_
+#define _BLAZE_MATH_DENSE_LLH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/StrictlyTriangular.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/potrf.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LLH DECOMPOSITION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LLH decomposition functions */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+void llh( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& L );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Cholesky (LLH) decomposition of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param A The matrix to be decomposed.
+// \param L The resulting lower triangular matrix.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Dimensions of fixed size matrix do not match.
+// \exception std::invalid_argument Decomposition of singular matrix failed.
+//
+// This function performs the dense matrix Cholesky (LLH) decomposition of a positive definite
+// n-by-n matrix. The resulting decomposition has the form
+
+ \f[ A = L \cdot L^{H}, \f]
+
+// where \c L is a lower triangular n-by-n matrix. The decomposition is written to the matrix
+// \c L, which is resized to the correct dimensions (if possible and necessary).
+//
+// The function fails if ...
+//
+// - ... \a A is not a square matrix;
+// - ... \a L is a fixed size matrix and the dimensions don't match \a A.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Example:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::columnMajor> A( 32, 32 );
+ // ... Initialization of A as positive definite matrix
+
+ blaze::DynamicMatrix<double,blaze::columnMajor> L( 32, 32 );
+
+ llh( A, L );
+
+ assert( A == L * trans( L ) );
+ \endcode
+
+// \note This function only works for matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with matrices of any other
+// element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a L may already have been modified.
+*/
+template< typename MT1 // Type of matrix A
+ , bool SO1 // Storage order of matrix A
+ , typename MT2 // Type of matrix L
+ , bool SO2 > // Storage order of matrix L
+void llh( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& L )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t n( (~A).rows() );
+
+ if( ( !IsResizable<MT2>::value && ( (~L).rows() != n || (~L).columns() != n ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" );
+ }
+
+ DerestrictTrait_<MT2> l( derestrict( ~L ) );
+
+ resize( ~L, n, n );
+ reset( l );
+
+ if( IsRowMajorMatrix<MT2>::value ) {
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<=i; ++j ) {
+ l(i,j) = (~A)(i,j);
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<n; ++j ) {
+ for( size_t i=j; i<n; ++i ) {
+ l(i,j) = (~A)(i,j);
+ }
+ }
+ }
+
+ potrf( l, 'L' );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/LQ.h b/src/cpu/blaze/math/dense/LQ.h
new file mode 100644
index 00000000..99ad8b90
--- /dev/null
+++ b/src/cpu/blaze/math/dense/LQ.h
@@ -0,0 +1,246 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/LQ.h
+// \brief Header file for the dense matrix in-place LQ decomposition
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_LQ_H_
+#define _BLAZE_MATH_DENSE_LQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/StrictlyTriangular.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/gelqf.h>
+#include <blaze/math/lapack/orglq.h>
+#include <blaze/math/lapack/unglq.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/util/EnableIf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LQ DECOMPOSITION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LQ decomposition functions */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2, typename MT3, bool SO3 >
+void lq( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& Q, DenseMatrix<MT3,SO3>& R );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the LQ decomposition.
+// \ingroup dense_matrix
+//
+// \param A The LQ decomposed column-major matrix.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix LQ decomposition. It performs the
+// reconstruction of the \c Q matrix from the RQ decomposition.
+*/
+template< typename MT1 > // Type of matrix A
+inline EnableIf_<IsBuiltin< ElementType_<MT1> > >
+ lq_backend( MT1& A, const ElementType_<MT1>* tau )
+{
+ orglq( A, tau );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the LQ decomposition.
+// \ingroup dense_matrix
+//
+// \param A The LQ decomposed column-major matrix.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix LQ decomposition. It performs the
+// reconstruction of the \c Q matrix from the RQ decomposition.
+*/
+template< typename MT1 > // Type of matrix A
+inline EnableIf_<IsComplex< ElementType_<MT1> > >
+ lq_backend( MT1& A, const ElementType_<MT1>* tau )
+{
+ unglq( A, tau );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LQ decomposition of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param A The matrix to be decomposed.
+// \param L The resulting \c L matrix.
+// \param Q The resulting \c Q matrix.
+// \return void
+// \exception std::invalid_argument Dimensions of fixed size matrix do not match.
+// \exception std::invalid_argument Square matrix cannot be resized to \a m-by-\a n.
+//
+// This function performs the dense matrix LQ decomposition of a general \a m-by-\a n matrix.
+// The resulting decomposition has the form
+
+ \f[ A = L \cdot Q, \f]
+
+// where \c L is a lower trapezoidal \a m-by-min(\a m,\a n) matrix and \c Q is a general
+// min(\a m,\a n)-by-\a n matrix. The decomposition is written to the two distinct matrices
+// \c L and \c Q, which are resized to the correct dimensions (if possible and necessary).
+//
+// The function fails if ...
+//
+// - ... either \a L or \a Q are fixed size matrices and the dimensions don't match;
+// - ... \a L is a compile time square matrix, but is required to be non-square.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Example:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::columnMajor> A( 32, 16 );
+ // ... Initialization of A
+
+ blaze::DynamicMatrix<double,blaze::columnMajor> L( 32, 16 );
+ blaze::DynamicMatrix<double,blaze::columnMajor> Q( 16, 16 );
+
+ lq( A, L, Q );
+
+ assert( A == L * Q );
+ \endcode
+
+// \note This function only works for matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with matrices of any other
+// element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of matrix A
+ , bool SO1 // Storage order of matrix A
+ , typename MT2 // Type of matrix L
+ , bool SO2 // Storage order of matrix L
+ , typename MT3 // Type of matrix Q
+ , bool SO3 > // Storage order of matrix Q
+void lq( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& L, DenseMatrix<MT3,SO3>& Q )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT3> );
+
+ typedef ElementType_<MT1> ET1;
+
+ const size_t m( (~A).rows() );
+ const size_t n( (~A).columns() );
+ const size_t mindim( min( m, n ) );
+
+ if( ( !IsResizable<MT2>::value && ( (~L).rows() != m || (~L).columns() != mindim ) ) ||
+ ( !IsResizable<MT3>::value && ( (~Q).rows() != mindim || (~Q).columns() != n ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" );
+ }
+
+ if( IsSquare<MT2>::value && m != mindim ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to m-by-min(m,n)" );
+ }
+
+ const std::unique_ptr<ET1[]> tau( new ET1[mindim] );
+ DerestrictTrait_<MT3> l( derestrict( ~L ) );
+
+ if( m < n )
+ {
+ (~Q) = A;
+ gelqf( ~Q, tau.get() );
+
+ resize( ~L, m, m );
+ reset( l );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<min(i+1UL,n); ++j ) {
+ l(i,j) = (~Q)(i,j);
+ }
+ }
+
+ lq_backend( ~Q, tau.get() );
+ }
+ else
+ {
+ l = A;
+ gelqf( l, tau.get() );
+ (~Q) = submatrix( l, 0UL, 0UL, n, n );
+ lq_backend( ~Q, tau.get() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=i+1UL; j<n; ++j ) {
+ reset( l(i,j) );
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/LU.h b/src/cpu/blaze/math/dense/LU.h
new file mode 100644
index 00000000..d8e47a55
--- /dev/null
+++ b/src/cpu/blaze/math/dense/LU.h
@@ -0,0 +1,329 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/LU.h
+// \brief Header file for the dense matrix in-place LU decomposition
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_LU_H_
+#define _BLAZE_MATH_DENSE_LU_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/StrictlyTriangular.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/getrf.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/typetraits/IsResizable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LU DECOMPOSITION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LU decomposition functions */
+//@{
+template< typename MT1, bool SO1, typename MT2, typename MT3, typename MT4, bool SO2 >
+void lu( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO1>& L,
+ DenseMatrix<MT3,SO1>& U, Matrix<MT4,SO2>& P );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the LU decomposition of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param A The matrix to be decomposed.
+// \param P The resulting permutation matrix.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix LU decomposition. It performs an
+// in-place LU decomposition on the given matrix \c A and reconstructs the permutation matrix
+// \c P.
+*/
+template< typename MT1 // Type of matrix A
+ , bool SO1 // Storage order of dense matrix A
+ , typename MT2 // Type of matrix P
+ , bool SO2 > // Storage order of matrix P
+void lu( DenseMatrix<MT1,SO1>& A, Matrix<MT2,SO2>& P )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+
+ typedef ElementType_<MT2> ET;
+
+ const size_t m( (~A).rows() );
+ const size_t n( (~A).columns() );
+ const size_t mindim( min( m, n ) );
+ const size_t size( SO1 ? m : n );
+
+ const std::unique_ptr<int[]> helper( new int[mindim + size] );
+ int* ipiv ( helper.get() );
+ int* permut( ipiv + mindim );
+
+ getrf( ~A, ipiv );
+
+ for( size_t i=0UL; i<size; ++i ) {
+ permut[i] = i;
+ }
+
+ for( int i=0; i<mindim; ++i ) {
+ --ipiv[i];
+ if( ipiv[i] != i ) {
+ std::swap( permut[ipiv[i]], permut[i] );
+ }
+ }
+
+ resize( ~P, size, size );
+ reset( ~P );
+ for( size_t i=0UL; i<size; ++i ) {
+ (~P)( ( SO1 ? permut[i] : i ), ( SO1 ? i : permut[i] ) ) = ET(1);
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LU decomposition of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param A The matrix to be decomposed.
+// \param L The resulting lower triangular matrix.
+// \param U The resulting upper triangular matrix.
+// \param P The resulting permutation matrix.
+// \return void
+// \exception std::invalid_argument Dimensions of fixed size matrix do not match.
+// \exception std::invalid_argument Square matrix cannot be resized to \a m-by-\a n.
+//
+// This function performs the dense matrix (P)LU decomposition of a general \a m-by-\a n matrix.
+// The resulting decomposition is written to the three distinct matrices \c L, \c U, and \c P,
+// which are resized to the correct dimensions (if possible and necessary).
+//
+// In case of a column-major matrix the algorithm performs the decomposition using partial pivoting
+// with row interchanges. The resulting decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is an m-by-m permutation matrix, which represents the pivoting indices for the applied
+// row interchanges, \c L is a lower triangular matrix (lower trapezoidal if \a m > \a n), and \c U
+// is an upper triangular matrix (upper trapezoidal if \a m < \a n).
+//
+// In case of a row-major matrix the algorithm performs the decomposition using partial pivoting
+// with column interchanges. The resulting decomposition has the form
+
+ \f[ A = L \cdot U \cdot P, \f]
+
+// where \c L is a lower triangular matrix (lower trapezoidal if \a m > \a n), \c U is an upper
+// triangular matrix (upper trapezoidal if \a m < \a n), and \c P is an n-by-n permutation matrix,
+// which represents the pivoting indices for the applied column interchanges.
+//
+// The function fails if ...
+//
+// - ... either \a L, \a U, and \a P are fixed size matrices and the dimensions don't match;
+// - ... \a A is a non-square m-by-n matrix, but \a L or \a U is a compile time square matrix.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::rowMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::rowMajor> L, U, P;
+
+ lu( A, L, U, P ); // LU decomposition of a row-major matrix
+
+ assert( A == L * U * P );
+ \endcode
+
+ \code
+ blaze::DynamicMatrix<double,blaze::columnMajor> A;
+ // ... Resizing and initialization
+
+ blaze::DynamicMatrix<double,blaze::columnMajor> L, U, P;
+
+ lu( A, L, U, P ); // LU decomposition of a column-major matrix
+
+ assert( A == P * L * U );
+ \endcode
+
+// \note This function only works for matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with matrices of any other
+// element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note The LU decomposition will never fail, even for singular matrices. However, in case of a
+// singular matrix the resulting decomposition cannot be used for a matrix inversion or solving
+// a linear system of equations.
+*/
+template< typename MT1 // Type of matrix A
+ , bool SO1 // Storage order of matrix A, L and U
+ , typename MT2 // Type of matrix L
+ , typename MT3 // Type of matrix U
+ , typename MT4 // Type of matrix P
+ , bool SO2 > // Storage order of matrix P
+void lu( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO1>& L,
+ DenseMatrix<MT3,SO1>& U, Matrix<MT4,SO2>& P )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT2 );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE( MT3 );
+
+ typedef ElementType_<MT2> ET2;
+ typedef ElementType_<MT3> ET3;
+
+ const size_t m( (~A).rows() );
+ const size_t n( (~A).columns() );
+ const size_t mindim( min( m, n ) );
+ const size_t size( SO1 ? m : n );
+
+ if( ( !IsResizable<MT2>::value && ( (~L).rows() != m || (~L).columns() != mindim ) ) ||
+ ( !IsResizable<MT3>::value && ( (~U).rows() != mindim || (~U).columns() != n ) ) ||
+ ( !IsResizable<MT4>::value && ( (~P).rows() != size || (~P).columns() != size ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" );
+ }
+
+ if( ( IsSquare<MT2>::value && n < m ) || ( IsSquare<MT3>::value && m < n ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to m-by-n" );
+ }
+
+ DerestrictTrait_<MT2> l( derestrict( ~L ) );
+ DerestrictTrait_<MT3> u( derestrict( ~U ) );
+
+ if( m < n )
+ {
+ u = (~A);
+ lu( u, ~P );
+
+ resize( ~L, m, m );
+ reset( l );
+
+ if( SO1 == rowMajor )
+ {
+ for( size_t i=0UL; i<m; ++i )
+ {
+ for( size_t j=0UL; j<i; ++j ) {
+ l(i,j) = u(i,j);
+ reset( u(i,j) );
+ }
+
+ l(i,i) = u(i,i);
+ u(i,i) = ET3(1);
+ }
+ }
+ else
+ {
+ for( size_t j=0UL; j<m; ++j )
+ {
+ l(j,j) = ET2(1);
+
+ for( size_t i=j+1UL; i<m; ++i ) {
+ l(i,j) = u(i,j);
+ reset( u(i,j) );
+ }
+ }
+ }
+ }
+ else
+ {
+ l = (~A);
+ lu( l, ~P );
+
+ resize( ~U, n, n );
+ reset( u );
+
+ if( SO1 == rowMajor )
+ {
+ for( size_t i=0UL; i<n; ++i )
+ {
+ u(i,i) = ET3(1);
+
+ for( size_t j=i+1UL; j<n; ++j ) {
+ u(i,j) = l(i,j);
+ reset( l(i,j) );
+ }
+ }
+ }
+ else
+ {
+ for( size_t j=0UL; j<n; ++j )
+ {
+ for( size_t i=0UL; i<j; ++i ) {
+ u(i,j) = l(i,j);
+ reset( l(i,j) );
+ }
+
+ u(j,j) = l(j,j);
+ l(j,j) = ET2(1);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/QL.h b/src/cpu/blaze/math/dense/QL.h
new file mode 100644
index 00000000..7f1ef5fa
--- /dev/null
+++ b/src/cpu/blaze/math/dense/QL.h
@@ -0,0 +1,247 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/QL.h
+// \brief Header file for the dense matrix in-place QL decomposition
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_QL_H_
+#define _BLAZE_MATH_DENSE_QL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/StrictlyTriangular.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/constraints/Upper.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/geqlf.h>
+#include <blaze/math/lapack/orgql.h>
+#include <blaze/math/lapack/ungql.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/util/EnableIf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// QL DECOMPOSITION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name QL decomposition functions */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2, typename MT3, bool SO3 >
+void ql( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& Q, DenseMatrix<MT3,SO3>& L );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the QL decomposition.
+// \ingroup dense_matrix
+//
+// \param A The QL decomposed column-major matrix.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix QL decomposition. It performs the
+// reconstruction of the \c Q matrix from the QL decomposition.
+*/
+template< typename MT1 > // Type of matrix A
+inline EnableIf_<IsBuiltin< ElementType_<MT1> > >
+ ql_backend( MT1& A, const ElementType_<MT1>* tau )
+{
+ orgql( A, tau );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the QL decomposition.
+// \ingroup dense_matrix
+//
+// \param A The QL decomposed column-major matrix.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix QL decomposition. It performs the
+// reconstruction of the \c Q matrix from the QL decomposition.
+*/
+template< typename MT1 > // Type of matrix A
+inline EnableIf_<IsComplex< ElementType_<MT1> > >
+ ql_backend( MT1& A, const ElementType_<MT1>* tau )
+{
+ ungql( A, tau );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief QL decomposition of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param A The matrix to be decomposed.
+// \param Q The resulting \c Q matrix.
+// \param L The resulting \c L matrix.
+// \return void
+// \exception std::invalid_argument Dimensions of fixed size matrix do not match.
+// \exception std::invalid_argument Square matrix cannot be resized to \a m-by-\a n.
+//
+// This function performs the dense matrix QL decomposition of a general \a m-by-\a n matrix.
+// The resulting decomposition has the form
+
+ \f[ A = Q \cdot L, \f]
+
+// where \c Q is a general \a m-by-min(\a m,\a n) matrix and \c L is a lower trapezoidal
+// \a min(\a m,\a n)-by-\a n matrix. The decomposition is written to the two distinct matrices
+// \c Q and \c L, which are resized to the correct dimensions (if possible and necessary).
+//
+// The function fails if ...
+//
+// - ... either \a Q or \a L are fixed size matrices and the dimensions don't match;
+// - ... \a L is a compile time square matrix, but is required to be non-square.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Example:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::columnMajor> A( 32, 16 );
+ // ... Initialization of A
+
+ blaze::DynamicMatrix<double,blaze::columnMajor> Q( 32, 16 );
+ blaze::DynamicMatrix<double,blaze::columnMajor> L( 16, 16 );
+
+ ql( A, Q, L );
+
+ assert( A == Q * L );
+ \endcode
+
+// \note This function only works for matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with matrices of any other
+// element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of matrix A
+ , bool SO1 // Storage order of matrix A
+ , typename MT2 // Type of matrix Q
+ , bool SO2 // Storage order of matrix Q
+ , typename MT3 // Type of matrix L
+ , bool SO3 > // Storage order of matrix L
+void ql( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& Q, DenseMatrix<MT3,SO3>& L )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT3> );
+
+ typedef ElementType_<MT1> ET1;
+
+ const size_t m( (~A).rows() );
+ const size_t n( (~A).columns() );
+ const size_t mindim( min( m, n ) );
+
+ if( ( !IsResizable<MT2>::value && ( (~Q).rows() != m || (~Q).columns() != mindim ) ) ||
+ ( !IsResizable<MT3>::value && ( (~L).rows() != mindim || (~L).columns() != n ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" );
+ }
+
+ if( IsSquare<MT3>::value && mindim != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to min(m,n)-by-n" );
+ }
+
+ const std::unique_ptr<ET1[]> tau( new ET1[mindim] );
+ DerestrictTrait_<MT2> l( derestrict( ~L ) );
+
+ if( m < n )
+ {
+ l = A;
+ geqlf( l, tau.get() );
+ (~Q) = submatrix( l, 0UL, n-m, m, m );
+ ql_backend( ~Q, tau.get() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=i+n-m+1UL; j<n; ++j ) {
+ reset( l(i,j) );
+ }
+ }
+ }
+ else
+ {
+ (~Q) = A;
+ geqlf( ~Q, tau.get() );
+
+ resize( ~L, n, n );
+ reset( l );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=0UL; j<i+1UL; ++j ) {
+ l(i,j) = (~Q)(i+m-n,j);
+ }
+ }
+
+ ql_backend( ~Q, tau.get() );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/QR.h b/src/cpu/blaze/math/dense/QR.h
new file mode 100644
index 00000000..eb074fd5
--- /dev/null
+++ b/src/cpu/blaze/math/dense/QR.h
@@ -0,0 +1,246 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/QR.h
+// \brief Header file for the dense matrix in-place QR decomposition
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_QR_H_
+#define _BLAZE_MATH_DENSE_QR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/StrictlyTriangular.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/geqrf.h>
+#include <blaze/math/lapack/orgqr.h>
+#include <blaze/math/lapack/ungqr.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/util/EnableIf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// QR DECOMPOSITION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name QR decomposition functions */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2, typename MT3, bool SO3 >
+void qr( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& Q, DenseMatrix<MT3,SO3>& R );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the QR decomposition.
+// \ingroup dense_matrix
+//
+// \param A The QR decomposed column-major matrix.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix QR decomposition. It performs the
+// reconstruction of the \c Q matrix from the RQ decomposition.
+*/
+template< typename MT1 > // Type of matrix A
+inline EnableIf_<IsBuiltin< ElementType_<MT1> > >
+ qr_backend( MT1& A, const ElementType_<MT1>* tau )
+{
+ orgqr( A, tau );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the QR decomposition.
+// \ingroup dense_matrix
+//
+// \param A The QR decomposed column-major matrix.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix QR decomposition. It performs the
+// reconstruction of the \c Q matrix from the RQ decomposition.
+*/
+template< typename MT1 > // Type of matrix A
+inline EnableIf_<IsComplex< ElementType_<MT1> > >
+ qr_backend( MT1& A, const ElementType_<MT1>* tau )
+{
+ ungqr( A, tau );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief QR decomposition of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param A The matrix to be decomposed.
+// \param Q The resulting \c Q matrix.
+// \param R The resulting \c R matrix.
+// \return void
+// \exception std::invalid_argument Dimensions of fixed size matrix do not match.
+// \exception std::invalid_argument Square matrix cannot be resized to m-by-n.
+//
+// This function performs the dense matrix QR decomposition of a general \a m-by-\a n matrix.
+// The resulting decomposition has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where \c Q is a general \a m-by-min(\a m,\a n) matrix and \c R is an upper trapezoidal
+// min(\a m,\a n)-by-\a n matrix. The decomposition is written to the two distinct matrices
+// \c Q and \c R, which are resized to the correct dimensions (if possible and necessary).
+//
+// The function fails if ...
+//
+// - ... either \a Q or \a R are fixed size matrices and the dimensions don't match;
+// - ... \a R is a compile time square matrix, but is required to be non-square.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Example:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::columnMajor> A( 32, 16 );
+ // ... Initialization of A
+
+ blaze::DynamicMatrix<double,blaze::columnMajor> Q( 32, 16 );
+ blaze::DynamicMatrix<double,blaze::columnMajor> R( 16, 16 );
+
+ qr( A, Q, R );
+
+ assert( A == Q * R );
+ \endcode
+
+// \note This function only works for matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with matrices of any other
+// element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of matrix A
+ , bool SO1 // Storage order of matrix A
+ , typename MT2 // Type of matrix Q
+ , bool SO2 // Storage order of matrix Q
+ , typename MT3 // Type of matrix R
+ , bool SO3 > // Storage order of matrix R
+void qr( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& Q, DenseMatrix<MT3,SO3>& R )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT3> );
+
+ typedef ElementType_<MT1> ET1;
+
+ const size_t m( (~A).rows() );
+ const size_t n( (~A).columns() );
+ const size_t mindim( min( m, n ) );
+
+ if( ( !IsResizable<MT2>::value && ( (~Q).rows() != m || (~Q).columns() != mindim ) ) ||
+ ( !IsResizable<MT3>::value && ( (~R).rows() != mindim || (~R).columns() != n ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" );
+ }
+
+ if( IsSquare<MT3>::value && mindim != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to min(m,n)-by-n" );
+ }
+
+ const std::unique_ptr<ET1[]> tau( new ET1[mindim] );
+ DerestrictTrait_<MT3> r( derestrict( ~R ) );
+
+ if( m < n )
+ {
+ r = A;
+ geqrf( r, tau.get() );
+ (~Q) = submatrix( r, 0UL, 0UL, m, m );
+ qr_backend( ~Q, tau.get() );
+
+ for( size_t i=1UL; i<m; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ reset( r(i,j) );
+ }
+ }
+ }
+ else
+ {
+ (~Q) = A;
+ geqrf( ~Q, tau.get() );
+
+ resize( ~R, n, n );
+ reset( r );
+
+ for( size_t i=0UL; i<n; ++i ) {
+ for( size_t j=i; j<n; ++j ) {
+ r(i,j) = (~Q)(i,j);
+ }
+ }
+
+ qr_backend( ~Q, tau.get() );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/RQ.h b/src/cpu/blaze/math/dense/RQ.h
new file mode 100644
index 00000000..46f7a4d2
--- /dev/null
+++ b/src/cpu/blaze/math/dense/RQ.h
@@ -0,0 +1,248 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/RQ.h
+// \brief Header file for the dense matrix in-place RQ decomposition
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_RQ_H_
+#define _BLAZE_MATH_DENSE_RQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Hermitian.h>
+#include <blaze/math/constraints/Lower.h>
+#include <blaze/math/constraints/StrictlyTriangular.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/lapack/gerqf.h>
+#include <blaze/math/lapack/orgrq.h>
+#include <blaze/math/lapack/ungrq.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/views/Submatrix.h>
+#include <blaze/util/EnableIf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RQ DECOMPOSITION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name RQ decomposition functions */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2, typename MT3, bool SO3 >
+void rq( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& R, DenseMatrix<MT3,SO3>& Q );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the RQ decomposition.
+// \ingroup dense_matrix
+//
+// \param A The RQ decomposed column-major matrix.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix RQ decomposition. It performs the
+// reconstruction of the \c Q matrix from the RQ decomposition.
+*/
+template< typename MT1 > // Type of matrix A
+inline EnableIf_<IsBuiltin< ElementType_<MT1> > >
+ rq_backend( MT1& A, const ElementType_<MT1>* tau )
+{
+ orgrq( A, tau );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary function for the RQ decomposition.
+// \ingroup dense_matrix
+//
+// \param A The RQ decomposed column-major matrix.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+//
+// This function is an auxiliary helper for the dense matrix RQ decomposition. It performs the
+// reconstruction of the \c Q matrix from the RQ decomposition.
+*/
+template< typename MT1 > // Type of matrix A
+inline EnableIf_<IsComplex< ElementType_<MT1> > >
+ rq_backend( MT1& A, const ElementType_<MT1>* tau )
+{
+ ungrq( A, tau );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief RQ decomposition of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param A The matrix to be decomposed.
+// \param R The resulting \c R matrix.
+// \param Q The resulting \c Q matrix.
+// \return void
+// \exception std::invalid_argument Dimensions of fixed size matrix do not match.
+// \exception std::invalid_argument Square matrix cannot be resized to \a m-by-\a n.
+//
+// This function performs the dense matrix RQ decomposition of a general \a m-by-\a n matrix.
+// The resulting decomposition has the form
+
+ \f[ A = R \cdot Q, \f]
+
+// where \c R is an upper trapezoidal \a m-by-min(\a m,\a n) matrix and \c Q is a general
+// min(\a m,\a n)-by-\a n matrix. The decomposition is written to the two distinct matrices
+// \c R and \c Q, which are resized to the correct dimensions (if possible and necessary).
+//
+// The function fails if ...
+//
+// - ... either \a R or \a Q are fixed size matrices and the dimensions don't match;
+// - ... \a R is a compile time square matrix, but is required to be non-square.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Example:
+
+ \code
+ blaze::DynamicMatrix<double,blaze::columnMajor> A( 32, 16 );
+ // ... Initialization of A
+
+ blaze::DynamicMatrix<double,blaze::columnMajor> R( 32, 16 );
+ blaze::DynamicMatrix<double,blaze::columnMajor> Q( 16, 16 );
+
+
+ rq( A, R, Q );
+
+ assert( A == R * Q );
+ \endcode
+
+// \note This function only works for matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with matrices of any other
+// element type results in a compile time error!
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of matrix A
+ , bool SO1 // Storage order of matrix A
+ , typename MT2 // Type of matrix R
+ , bool SO2 // Storage order of matrix R
+ , typename MT3 // Type of matrix Q
+ , bool SO3 > // Storage order of matrix Q
+void rq( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& R, DenseMatrix<MT3,SO3>& Q )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT3 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT3> );
+
+ typedef ElementType_<MT1> ET1;
+
+ const size_t m( (~A).rows() );
+ const size_t n( (~A).columns() );
+ const size_t mindim( min( m, n ) );
+
+ if( ( !IsResizable<MT2>::value && ( (~R).rows() != m || (~R).columns() != mindim ) ) ||
+ ( !IsResizable<MT3>::value && ( (~Q).rows() != mindim || (~Q).columns() != n ) ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" );
+ }
+
+ if( IsSquare<MT2>::value && m != mindim ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to m-by-min(m,n)" );
+ }
+
+ const std::unique_ptr<ET1[]> tau( new ET1[mindim] );
+ DerestrictTrait_<MT2> r( derestrict( ~R ) );
+
+ if( m < n )
+ {
+ (~Q) = A;
+ gerqf( ~Q, tau.get() );
+
+ resize( ~R, m, m );
+ reset( r );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=i; j<m; ++j ) {
+ r(i,j) = (~Q)(i,j+n-m);
+ }
+ }
+
+ rq_backend( ~Q, tau.get() );
+ }
+ else
+ {
+ r = A;
+ gerqf( r, tau.get() );
+ (~Q) = submatrix( r, m-n, 0UL, n, n );
+ rq_backend( ~Q, tau.get() );
+
+ for( size_t i=m-n; i<m; ++i ) {
+ for( size_t j=0UL; j<i+n-m; ++j ) {
+ reset( r(i,j) );
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/StaticMatrix.h b/src/cpu/blaze/math/dense/StaticMatrix.h
new file mode 100644
index 00000000..5e67711d
--- /dev/null
+++ b/src/cpu/blaze/math/dense/StaticMatrix.h
@@ -0,0 +1,6270 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/StaticMatrix.h
+// \brief Header file for the implementation of a fixed-size matrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_STATICMATRIX_H_
+#define _BLAZE_MATH_DENSE_STATICMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/Diagonal.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/dense/DenseIterator.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/InvExprTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/StorageOrder.h>
+#include <blaze/util/AlignedArray.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/mpl/NextMultiple.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup static_matrix StaticMatrix
+// \ingroup dense_matrix
+*/
+/*!\brief Efficient implementation of a fixed-sized matrix.
+// \ingroup static_matrix
+//
+// The StaticMatrix class template is the representation of a fixed-size matrix with statically
+// allocated elements of arbitrary type. The type of the elements, the number of rows and columns
+// and the storage order of the matrix can be specified via the four template parameters:
+
+ \code
+ template< typename Type, size_t M, size_t N, bool SO >
+ class StaticMatrix;
+ \endcode
+
+// - Type: specifies the type of the matrix elements. StaticMatrix can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - M : specifies the total number of rows of the matrix.
+// - N : specifies the total number of columns of the matrix. Note that it is expected
+// that StaticMatrix is only used for tiny and small matrices.
+// - SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// Depending on the storage order, the matrix elements are either stored in a row-wise fashion
+// or in a column-wise fashion. Given the 2x3 matrix
+
+ \f[\left(\begin{array}{*{3}{c}}
+ 1 & 2 & 3 \\
+ 4 & 5 & 6 \\
+ \end{array}\right)\f]\n
+
+// in case of row-major order the elements are stored in the order
+
+ \f[\left(\begin{array}{*{6}{c}}
+ 1 & 2 & 3 & 4 & 5 & 6. \\
+ \end{array}\right)\f]
+
+// In case of column-major order the elements are stored in the order
+
+ \f[\left(\begin{array}{*{6}{c}}
+ 1 & 4 & 2 & 5 & 3 & 6. \\
+ \end{array}\right)\f]
+
+// The use of StaticMatrix is very natural and intuitive. All operations (addition, subtraction,
+// multiplication, scaling, ...) can be performed on all possible combination of row-major and
+// column-major dense and sparse matrices with fitting element types. The following example gives
+// an impression of the use of StaticMatrix:
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ StaticMatrix<double,2UL,3UL,rowMajor> A; // Default constructed, non-initialized, row-major 2x3 matrix
+ A(0,0) = 1.0; A(0,1) = 2.0; A(0,2) = 3.0; // Initialization of the first row
+ A(1,0) = 4.0; A(1,1) = 5.0; A(1,2) = 6.0; // Initialization of the second row
+
+ DynamicMatrix<float,2UL,3UL,columnMajor> B; // Default constructed column-major single precision 2x3 matrix
+ B(0,0) = 1.0; B(0,1) = 3.0; B(0,2) = 5.0; // Initialization of the first row
+ B(1,0) = 2.0; B(1,1) = 4.0; B(1,2) = 6.0; // Initialization of the second row
+
+ CompressedMatrix<float> C( 2, 3 ); // Empty row-major sparse single precision matrix
+ StaticMatrix<float,3UL,2UL> D( 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix
+
+ StaticMatrix<double,2UL,3UL,rowMajor> E( A ); // Creation of a new row-major matrix as a copy of A
+ StaticMatrix<double,2UL,2UL,columnMajor> F; // Creation of a default column-major matrix
+
+ E = A + B; // Matrix addition and assignment to a row-major matrix
+ F = A - C; // Matrix subtraction and assignment to a column-major matrix
+ F = A * D; // Matrix multiplication between two matrices of different element types
+
+ A *= 2.0; // In-place scaling of matrix A
+ E = 2.0 * B; // Scaling of matrix B
+ E = B * 2.0; // Scaling of matrix B
+
+ E += A - B; // Addition assignment
+ E -= A + C; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO = defaultStorageOrder > // Storage order
+class StaticMatrix : public DenseMatrix< StaticMatrix<Type,M,N,SO>, SO >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef StaticMatrix<Type,M,N,SO> This; //!< Type of this StaticMatrix instance.
+ typedef DenseMatrix<This,SO> BaseType; //!< Base type of this StaticMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef StaticMatrix<Type,M,N,!SO> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef StaticMatrix<Type,N,M,!SO> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Type* Pointer; //!< Pointer to a non-constant matrix value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant matrix value.
+
+ typedef DenseIterator<Type,usePadding> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,usePadding> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a StaticMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef StaticMatrix<ET,M,N,SO> Other; //!< The type of the other StaticMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the element type of the matrix is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StaticMatrix();
+ explicit inline StaticMatrix( const Type& init );
+ explicit inline StaticMatrix( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other >
+ explicit inline StaticMatrix( size_t m, size_t n, const Other* array );
+
+ template< typename Other >
+ explicit inline StaticMatrix( const Other (&array)[M][N] );
+
+ inline StaticMatrix( const StaticMatrix& m );
+ template< typename Other, bool SO2 > inline StaticMatrix( const StaticMatrix<Other,M,N,SO2>& m );
+ template< typename MT , bool SO2 > inline StaticMatrix( const Matrix<MT,SO2>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t i ) noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i ) noexcept;
+ inline ConstIterator begin ( size_t i ) const noexcept;
+ inline ConstIterator cbegin( size_t i ) const noexcept;
+ inline Iterator end ( size_t i ) noexcept;
+ inline ConstIterator end ( size_t i ) const noexcept;
+ inline ConstIterator cend ( size_t i ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline StaticMatrix& operator=( const Type& set );
+ inline StaticMatrix& operator=( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other >
+ inline StaticMatrix& operator=( const Other (&array)[M][N] );
+
+ inline StaticMatrix& operator= ( const StaticMatrix& rhs );
+ template< typename Other, bool SO2 > inline StaticMatrix& operator= ( const StaticMatrix<Other,M,N,SO2>& rhs );
+ template< typename MT , bool SO2 > inline StaticMatrix& operator= ( const Matrix<MT,SO2>& rhs );
+ template< typename MT , bool SO2 > inline StaticMatrix& operator+=( const Matrix<MT,SO2>& rhs );
+ template< typename MT , bool SO2 > inline StaticMatrix& operator-=( const Matrix<MT,SO2>& rhs );
+ template< typename MT , bool SO2 > inline StaticMatrix& operator*=( const Matrix<MT,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, StaticMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, StaticMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline constexpr size_t rows() const noexcept;
+ inline constexpr size_t columns() const noexcept;
+ inline constexpr size_t spacing() const noexcept;
+ inline constexpr size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline StaticMatrix& transpose();
+ inline StaticMatrix& ctranspose();
+ template< typename Other > inline StaticMatrix& scale( const Other& scalar );
+ inline void swap( StaticMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Memory functions****************************************************************************
+ /*!\name Memory functions */
+ //@{
+ static inline void* operator new ( std::size_t size );
+ static inline void* operator new[]( std::size_t size );
+ static inline void* operator new ( std::size_t size, const std::nothrow_t& );
+ static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
+
+ static inline void operator delete ( void* ptr );
+ static inline void operator delete[]( void* ptr );
+ static inline void operator delete ( void* ptr, const std::nothrow_t& );
+ static inline void operator delete[]( void* ptr, const std::nothrow_t& );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ IsRowMajorMatrix<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDAdd< Type, ElementType_<MT> >::value &&
+ IsRowMajorMatrix<MT>::value &&
+ !IsDiagonal<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDSub< Type, ElementType_<MT> >::value &&
+ IsRowMajorMatrix<MT>::value &&
+ !IsDiagonal<MT>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT, bool SO2 >
+ inline DisableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline EnableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT > inline void assign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,!SO>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline DisableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline EnableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,!SO>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline DisableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT, bool SO2 >
+ inline EnableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO2>& rhs );
+
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,!SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ inline void transpose ( TrueType );
+ inline void transpose ( FalseType );
+ inline void ctranspose( TrueType );
+ inline void ctranspose( FalseType );
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Alignment adjustment.
+ enum : size_t { NN = ( usePadding )?( NextMultiple< SizeT<N>, SizeT<SIMDSIZE> >::value ):( N ) };
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ AlignedArray<Type,M*NN> v_; //!< The statically allocated matrix elements.
+ /*!< Access to the matrix elements is gained via the function call
+ operator. In case of row-major order the memory layout of the
+ elements is
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ N & N+1 & N+2 & \cdots & 2 \cdot N-1 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ M \cdot N-N & M \cdot N-N+1 & M \cdot N-N+2 & \cdots & M \cdot N-1 \\
+ \end{array}\right)\f]. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_STATIC_ASSERT( !usePadding || NN % SIMDSIZE == 0UL );
+ BLAZE_STATIC_ASSERT( NN >= N );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for StaticMatrix.
+//
+// All matrix elements are initialized to the default value (i.e. 0 for integral data types).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>::StaticMatrix()
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<M*NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a homogenous initialization of all elements.
+//
+// \param init Initial value for all matrix elements.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>::StaticMatrix( const Type& init )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*NN+j] = init;
+
+ for( size_t j=N; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of static matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the matrix by
+// means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::StaticMatrix<int,3,3,rowMajor> A{ { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix elements are initialized by the values of the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size of
+// the top-level initializer list exceeds the number of rows or the size of any nested list exceeds
+// the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>::StaticMatrix( initializer_list< initializer_list<Type> > list )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( list.size() != M || determineColumns( list ) > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static matrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*NN ), v_+(i+1UL)*NN, Type() );
+ ++i;
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param array Dynamic array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a dynamic array:
+
+ \code
+ using blaze::rowMajor;
+
+ int* array = new int[6];
+ // ... Initialization of the dynamic array
+ blaze::StaticMatrix<int,3,4,rowMajor> v( array, 2UL, 3UL );
+ delete[] array;
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the specified number of rows and/or columns exceeds the maximum
+// number of rows/column of the static matrix (i.e. \a m is larger than M or \a n is larger than
+// N), a \a std::invalid_argument exception is thrown.\n
+// Note that it is expected that the given \a array has at least \a m by \a n elements. Providing
+// an array with less elements results in undefined behavior!
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the initialization array
+inline StaticMatrix<Type,M,N,SO>::StaticMatrix( size_t m, size_t n, const Other* array )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( m > M || n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static matrix" );
+ }
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<n; ++j )
+ v_[i*NN+j] = array[i*n+j];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m; i<M; ++i ) {
+ for( size_t j=0UL; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a static array:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::StaticMatrix<int,3,3,rowMajor> A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the initialization array
+inline StaticMatrix<Type,M,N,SO>::StaticMatrix( const Other (&array)[M][N] )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*NN+j] = array[i][j];
+
+ for( size_t j=N; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for StaticMatrix.
+//
+// \param m Matrix to be copied.
+//
+// The copy constructor is explicitly defined in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>::StaticMatrix( const StaticMatrix& m )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<M*NN; ++i )
+ v_[i] = m.v_[i];
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different StaticMatrix instances.
+//
+// \param m Matrix to be copied.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other // Data type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline StaticMatrix<Type,M,N,SO>::StaticMatrix( const StaticMatrix<Other,M,N,SO2>& m )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*NN+j] = m(i,j);
+
+ for( size_t j=N; j<NN; ++j )
+ v_[i*NN+j] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of static matrix.
+//
+// This constructor initializes the static matrix from the given matrix. In case the size of
+// the given matrix does not match the size of the static matrix (i.e. the number of rows is
+// not M or the number of columns is not N), a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline StaticMatrix<Type,M,N,SO>::StaticMatrix( const Matrix<MT,SO2>& m )
+ : v_() // The statically allocated matrix elements
+{
+ using blaze::assign;
+
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( (~m).rows() != M || (~m).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static matrix" );
+ }
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=( IsSparseMatrix<MT>::value ? 0UL : N ); j<NN; ++j ) {
+ v_[i*NN+j] = Type();
+ }
+ }
+
+ assign( *this, ~m );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::Reference
+ StaticMatrix<Type,M,N,SO>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
+ return v_[i*NN+j];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return Reference-to-const to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::ConstReference
+ StaticMatrix<Type,M,N,SO>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
+ return v_[i*NN+j];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::Reference
+ StaticMatrix<Type,M,N,SO>::at( size_t i, size_t j )
+{
+ if( i >= M ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= N ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::ConstReference
+ StaticMatrix<Type,M,N,SO>::at( size_t i, size_t j ) const
+{
+ if( i >= M ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= N ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the static matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The static matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::Pointer
+ StaticMatrix<Type,M,N,SO>::data() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the static matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The static matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a row/column are given by the \c rows() and \c columns() member functions,
+// respectively, the total number of elements including padding is given by the \c spacing()
+// member function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::ConstPointer
+ StaticMatrix<Type,M,N,SO>::data() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::Pointer
+ StaticMatrix<Type,M,N,SO>::data( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return v_ + i*NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the matrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::ConstPointer
+ StaticMatrix<Type,M,N,SO>::data( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return v_ + i*NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::Iterator
+ StaticMatrix<Type,M,N,SO>::begin( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return Iterator( v_ + i*NN );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::ConstIterator
+ StaticMatrix<Type,M,N,SO>::begin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*NN );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::ConstIterator
+ StaticMatrix<Type,M,N,SO>::cbegin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*NN );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::Iterator
+ StaticMatrix<Type,M,N,SO>::end( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return Iterator( v_ + i*NN + N );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::ConstIterator
+ StaticMatrix<Type,M,N,SO>::end( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*NN + N );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline typename StaticMatrix<Type,M,N,SO>::ConstIterator
+ StaticMatrix<Type,M,N,SO>::cend( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
+ return ConstIterator( v_ + i*NN + N );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Homogenous assignment to all matrix elements.
+//
+// \param set Scalar value to be assigned to all matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::operator=( const Type& set )
+{
+ for( size_t i=0UL; i<M; ++i )
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*NN+j] = set;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to static matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the matrix
+// by means of an initializer list:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::StaticMatrix<int,3,3,rowMajor> A;
+ A = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>&
+ StaticMatrix<Type,M,N,SO>::operator=( initializer_list< initializer_list<Type> > list )
+{
+ if( list.size() != M || determineColumns( list ) > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static matrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*NN ), v_+(i+1UL)*NN, Type() );
+ ++i;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array assignment to all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+//
+// This assignment operator offers the option to directly set all elements of the matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::StaticMatrix<int,3UL,3UL,rowMajor> A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the initialization array
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::operator=( const Other (&array)[M][N] )
+{
+ for( size_t i=0UL; i<M; ++i )
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*NN+j] = array[i][j];
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for StaticMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// Explicit definition of a copy assignment operator for performance reasons.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::operator=( const StaticMatrix& rhs )
+{
+ using blaze::assign;
+
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different StaticMatrix instances.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other // Data type of the foreign matrix
+ , bool SO2 > // Storage order of the foreign matrix
+inline StaticMatrix<Type,M,N,SO>&
+ StaticMatrix<Type,M,N,SO>::operator=( const StaticMatrix<Other,M,N,SO2>& rhs )
+{
+ using blaze::assign;
+
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to static matrix.
+//
+// This constructor initializes the matrix as a copy of the given matrix. In case the
+// number of rows of the given matrix is not M or the number of columns is not N, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::operator=( const Matrix<MT,SO2>& rhs )
+{
+ using blaze::assign;
+
+ typedef TransExprTrait_<This> TT;
+ typedef CTransExprTrait_<This> CT;
+ typedef InvExprTrait_<This> IT;
+
+ if( (~rhs).rows() != M || (~rhs).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static matrix" );
+ }
+
+ if( IsSame<MT,TT>::value && (~rhs).isAliased( this ) ) {
+ transpose( typename IsSquare<This>::Type() );
+ }
+ else if( IsSame<MT,CT>::value && (~rhs).isAliased( this ) ) {
+ ctranspose( typename IsSquare<This>::Type() );
+ }
+ else if( !IsSame<MT,IT>::value && (~rhs).canAlias( this ) ) {
+ StaticMatrix tmp( ~rhs );
+ assign( *this, tmp );
+ }
+ else {
+ if( IsSparseMatrix<MT>::value )
+ reset();
+ assign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::operator+=( const Matrix<MT,SO2>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).rows() != M || (~rhs).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ addAssign( *this, tmp );
+ }
+ else {
+ addAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::operator-=( const Matrix<MT,SO2>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).rows() != M || (~rhs).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ subAssign( *this, tmp );
+ }
+ else {
+ subAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::operator*=( const Matrix<MT,SO2>& rhs )
+{
+ if( M != N || (~rhs).rows() != M || (~rhs).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const StaticMatrix tmp( *this * (~rhs) );
+ this->operator=( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, StaticMatrix<Type,M,N,SO> >&
+ StaticMatrix<Type,M,N,SO>::operator*=( Other rhs )
+{
+ using blaze::assign;
+
+ assign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, StaticMatrix<Type,M,N,SO> >&
+ StaticMatrix<Type,M,N,SO>::operator/=( Other rhs )
+{
+ using blaze::assign;
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ assign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline constexpr size_t StaticMatrix<Type,M,N,SO>::rows() const noexcept
+{
+ return M;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline constexpr size_t StaticMatrix<Type,M,N,SO>::columns() const noexcept
+{
+ return N;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the spacing between the beginning of two rows.
+//
+// \return The spacing between the beginning of two rows.
+//
+// This function returns the spacing between the beginning of two rows, i.e. the total number
+// of elements of a row.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline constexpr size_t StaticMatrix<Type,M,N,SO>::spacing() const noexcept
+{
+ return NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline constexpr size_t StaticMatrix<Type,M,N,SO>::capacity() const noexcept
+{
+ return M*NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline size_t StaticMatrix<Type,M,N,SO>::capacity( size_t i ) const noexcept
+{
+ UNUSED_PARAMETER( i );
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ return NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline size_t StaticMatrix<Type,M,N,SO>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<M; ++i )
+ for( size_t j=0UL; j<N; ++j )
+ if( !isDefault( v_[i*NN+j] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline size_t StaticMatrix<Type,M,N,SO>::nonZeros( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t jend( i*NN + N );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=i*NN; j<jend; ++j )
+ if( !isDefault( v_[j] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::reset()
+{
+ using blaze::clear;
+
+ for( size_t i=0UL; i<M; ++i )
+ for( size_t j=0UL; j<N; ++j )
+ clear( v_[i*NN+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::reset( size_t i )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ for( size_t j=0UL; j<N; ++j )
+ clear( v_[i*NN+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+//
+// This function transposes the static matrix in-place. Note that this function can only be used
+// for square static matrices, i.e. if \a M is equal to N.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::transpose()
+{
+ using std::swap;
+
+ BLAZE_STATIC_ASSERT( M == N );
+
+ for( size_t i=1UL; i<M; ++i )
+ for( size_t j=0UL; j<i; ++j )
+ swap( v_[i*NN+j], v_[j*NN+i] );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper function for self-transpose via the trans() function.
+//
+// \return void
+//
+// This function assists in the evaluation of self-transpose via the trans() function:
+
+ \code
+ blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> A;
+
+ A = trans( A );
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::transpose( TrueType )
+{
+ transpose();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper function for self-transpose via the trans() function.
+//
+// \return void
+//
+// This function assists in the evaluation of self-transpose via the trans() function:
+
+ \code
+ blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> A;
+
+ A = trans( A );
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::transpose( FalseType )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+//
+// This function transposes the static matrix in-place. Note that this function can only be used
+// for square static matrices, i.e. if \a M is equal to N.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::ctranspose()
+{
+ BLAZE_STATIC_ASSERT( M == N );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<i; ++j ) {
+ cswap( v_[i*NN+j], v_[j*NN+i] );
+ }
+ conjugate( v_[i*NN+i] );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper function for self-transpose via the ctrans() function.
+//
+// \return void
+//
+// This function assists in the evaluation of self-transpose via the ctrans() function:
+
+ \code
+ blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> A;
+
+ A = ctrans( A );
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::ctranspose( TrueType )
+{
+ ctranspose();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper function for self-transpose via the ctrans() function.
+//
+// \return void
+//
+// This function assists in the evaluation of self-transpose via the ctrans() function:
+
+ \code
+ blaze::StaticMatrix<int,3UL,3UL,blaze::rowMajor> A;
+
+ A = ctrans( A );
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::ctranspose( FalseType )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A*=s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the scalar value
+inline StaticMatrix<Type,M,N,SO>& StaticMatrix<Type,M,N,SO>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<M; ++i )
+ for( size_t j=0UL; j<N; ++j )
+ v_[i*NN+j] *= scalar;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two static matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::swap( StaticMatrix& m ) noexcept
+{
+ using std::swap;
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ swap( v_[i*NN+j], m(i,j) );
+ }
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MEMORY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void* StaticMatrix<Type,M,N,SO>::operator new( std::size_t size )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( StaticMatrix ), "Invalid number of bytes detected" );
+
+ return allocate<StaticMatrix>( 1UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void* StaticMatrix<Type,M,N,SO>::operator new[]( std::size_t size )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( StaticMatrix ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( StaticMatrix ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<StaticMatrix>( size/sizeof(StaticMatrix) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of the no-throw operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void* StaticMatrix<Type,M,N,SO>::operator new( std::size_t size, const std::nothrow_t& )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( StaticMatrix ), "Invalid number of bytes detected" );
+
+ return allocate<StaticMatrix>( 1UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of the no-throw operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void* StaticMatrix<Type,M,N,SO>::operator new[]( std::size_t size, const std::nothrow_t& )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( StaticMatrix ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( StaticMatrix ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<StaticMatrix>( size/sizeof(StaticMatrix) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::operator delete( void* ptr )
+{
+ deallocate( static_cast<StaticMatrix*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::operator delete[]( void* ptr )
+{
+ deallocate( static_cast<StaticMatrix*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of no-throw operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::operator delete( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<StaticMatrix*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of no-throw operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void StaticMatrix<Type,M,N,SO>::operator delete[]( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<StaticMatrix*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the static matrix are intact.
+//
+// \return \a true in case the static matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the static matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline bool StaticMatrix<Type,M,N,SO>::isIntact() const noexcept
+{
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=N; j<NN; ++j ) {
+ if( v_[i*NN+j] != Type() )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool StaticMatrix<Type,M,N,SO>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool StaticMatrix<Type,M,N,SO>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each row/column of the matrix are guaranteed to conform
+// to the alignment restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline bool StaticMatrix<Type,M,N,SO>::isAligned() const noexcept
+{
+ return ( usePadding || columns() % SIMDSIZE == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller then the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename StaticMatrix<Type,M,N,SO>::SIMDType
+ StaticMatrix<Type,M,N,SO>::load( size_t i, size_t j ) const noexcept
+{
+ if( usePadding )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename StaticMatrix<Type,M,N,SO>::SIMDType
+ StaticMatrix<Type,M,N,SO>::loada( size_t i, size_t j ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
+
+ return loada( &v_[i*NN+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE typename StaticMatrix<Type,M,N,SO>::SIMDType
+ StaticMatrix<Type,M,N,SO>::loadu( size_t i, size_t j ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+
+ return loadu( &v_[i*NN+j] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the column index (in case of a row-major matrix) or the row index
+// (in case of a column-major matrix) must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ StaticMatrix<Type,M,N,SO>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( usePadding )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ StaticMatrix<Type,M,N,SO>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
+
+ storea( &v_[i*NN+j], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ StaticMatrix<Type,M,N,SO>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+
+ storeu( &v_[i*NN+j], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the column index (in case of a
+// row-major matrix) or the row index (in case of a column-major matrix) must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE void
+ StaticMatrix<Type,M,N,SO>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
+
+ stream( &v_[i*NN+j], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename StaticMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ StaticMatrix<Type,M,N,SO>::assign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ v_[i*NN+j] = (~rhs)(i,j);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename StaticMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ StaticMatrix<Type,M,N,SO>::assign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ const size_t jpos( ( remainder )?( N & size_t(-SIMDSIZE) ):( N ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ store( i, j, (~rhs).load(i,j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ v_[i*NN+j] = (~rhs)(i,j);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,SO>::assign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*NN+element->index()] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,SO>::assign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*NN+j] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename StaticMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ StaticMatrix<Type,M,N,SO>::addAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[i*NN+i] += (~rhs)(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ v_[i*NN+j] += (~rhs)(i,j);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename StaticMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ StaticMatrix<Type,M,N,SO>::addAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ store( i, j, load(i,j) + (~rhs).load(i,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ v_[i*NN+j] += (~rhs)(i,j);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,SO>::addAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*NN+element->index()] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,SO>::addAssign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*NN+j] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename StaticMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ StaticMatrix<Type,M,N,SO>::subAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[i*NN+i] -= (~rhs)(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ v_[i*NN+j] -= (~rhs)(i,j);
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename StaticMatrix<Type,M,N,SO>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ StaticMatrix<Type,M,N,SO>::subAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ store( i, j, load(i,j) - (~rhs).load(i,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ v_[i*NN+j] -= (~rhs)(i,j);
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,SO>::subAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i*NN+element->index()] -= element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,SO>::subAssign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()*NN+j] -= element->value();
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StaticMatrix for column-major matrices.
+// \ingroup static_matrix
+//
+// This specialization of StaticMatrix adapts the class template to the requirements of
+// column-major matrices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+class StaticMatrix<Type,M,N,true> : public DenseMatrix< StaticMatrix<Type,M,N,true>, true >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef StaticMatrix<Type,M,N,true> This; //!< Type of this StaticMatrix instance.
+ typedef DenseMatrix<This,true> BaseType; //!< Base type of this StaticMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef StaticMatrix<Type,M,N,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef StaticMatrix<Type,N,M,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Type* Pointer; //!< Pointer to a non-constant matrix value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant matrix value.
+
+ typedef DenseIterator<Type,usePadding> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,usePadding> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a StaticMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef StaticMatrix<ET,M,N,true> Other; //!< The type of the other StaticMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the element type of the matrix is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StaticMatrix();
+ explicit inline StaticMatrix( const Type& init );
+ explicit inline StaticMatrix( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other > explicit inline StaticMatrix( size_t m, size_t n, const Other* array );
+ template< typename Other > explicit inline StaticMatrix( const Other (&array)[M][N] );
+
+ inline StaticMatrix( const StaticMatrix& m );
+ template< typename Other, bool SO > inline StaticMatrix( const StaticMatrix<Other,M,N,SO>& m );
+ template< typename MT , bool SO > inline StaticMatrix( const Matrix<MT,SO>& m );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t j ) noexcept;
+ inline ConstPointer data ( size_t j ) const noexcept;
+ inline Iterator begin ( size_t j ) noexcept;
+ inline ConstIterator begin ( size_t j ) const noexcept;
+ inline ConstIterator cbegin( size_t j ) const noexcept;
+ inline Iterator end ( size_t j ) noexcept;
+ inline ConstIterator end ( size_t j ) const noexcept;
+ inline ConstIterator cend ( size_t j ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline StaticMatrix& operator=( const Type& set );
+ inline StaticMatrix& operator=( initializer_list< initializer_list<Type> > list );
+
+ template< typename Other >
+ inline StaticMatrix& operator=( const Other (&array)[M][N] );
+
+ inline StaticMatrix& operator= ( const StaticMatrix& rhs );
+ template< typename Other, bool SO > inline StaticMatrix& operator= ( const StaticMatrix<Other,M,N,SO>& rhs );
+ template< typename MT , bool SO > inline StaticMatrix& operator= ( const Matrix<MT,SO>& rhs );
+ template< typename MT , bool SO > inline StaticMatrix& operator+=( const Matrix<MT,SO>& rhs );
+ template< typename MT , bool SO > inline StaticMatrix& operator-=( const Matrix<MT,SO>& rhs );
+ template< typename MT , bool SO > inline StaticMatrix& operator*=( const Matrix<MT,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, StaticMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, StaticMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline constexpr size_t rows() const noexcept;
+ inline constexpr size_t columns() const noexcept;
+ inline constexpr size_t spacing() const noexcept;
+ inline constexpr size_t capacity() const noexcept;
+ inline size_t capacity( size_t j ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t j ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline StaticMatrix& transpose();
+ inline StaticMatrix& ctranspose();
+ template< typename Other > inline StaticMatrix& scale( const Other& scalar );
+ inline void swap( StaticMatrix& m ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Memory functions****************************************************************************
+ /*!\name Memory functions */
+ //@{
+ static inline void* operator new ( std::size_t size );
+ static inline void* operator new[]( std::size_t size );
+ static inline void* operator new ( std::size_t size, const std::nothrow_t& );
+ static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
+
+ static inline void operator delete ( void* ptr );
+ static inline void operator delete[]( void* ptr );
+ static inline void operator delete ( void* ptr, const std::nothrow_t& );
+ static inline void operator delete[]( void* ptr, const std::nothrow_t& );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ IsColumnMajorMatrix<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDAdd< Type, ElementType_<MT> >::value &&
+ IsColumnMajorMatrix<MT>::value &&
+ !IsDiagonal<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<MT> >::value &&
+ HasSIMDSub< Type, ElementType_<MT> >::value &&
+ IsColumnMajorMatrix<MT>::value &&
+ !IsDiagonal<MT>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT, bool SO >
+ inline DisableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT, bool SO >
+ inline EnableIf_<VectorizedAssign<MT> > assign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void assign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void assign( const SparseMatrix<MT,false>& rhs );
+
+ template< typename MT, bool SO >
+ inline DisableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT, bool SO >
+ inline EnableIf_<VectorizedAddAssign<MT> > addAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void addAssign( const SparseMatrix<MT,false>& rhs );
+
+ template< typename MT, bool SO >
+ inline DisableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT, bool SO >
+ inline EnableIf_<VectorizedSubAssign<MT> > subAssign( const DenseMatrix<MT,SO>& rhs );
+
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void subAssign( const SparseMatrix<MT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ inline void transpose ( TrueType );
+ inline void transpose ( FalseType );
+ inline void ctranspose( TrueType );
+ inline void ctranspose( FalseType );
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Alignment adjustment.
+ enum : size_t { MM = ( usePadding )?( NextMultiple< SizeT<M>, SizeT<SIMDSIZE> >::value ):( M ) };
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ AlignedArray<Type,MM*N> v_; //!< The statically allocated matrix elements.
+ /*!< Access to the matrix elements is gained via the
+ function call operator. */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_STATIC_ASSERT( !usePadding || MM % SIMDSIZE == 0UL );
+ BLAZE_STATIC_ASSERT( MM >= M );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for StaticMatrix.
+//
+// All matrix elements are initialized to the default value (i.e. 0 for integral data types).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>::StaticMatrix()
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<MM*N; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a homogenous initialization of all elements.
+//
+// \param init Initial value for all matrix elements.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>::StaticMatrix( const Type& init )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*MM] = init;
+
+ for( size_t i=M; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List initialization of all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of static matrix.
+//
+// This constructor provides the option to explicitly initialize the elements of the matrix by
+// means of an initializer list:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::StaticMatrix<int,3,3,columnMajor> A{ { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix elements are initialized by the values of the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size of
+// the top-level initializer list exceeds the number of rows or the size of any nested list exceeds
+// the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>::StaticMatrix( initializer_list< initializer_list<Type> > list )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( list.size() != M || determineColumns( list ) > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static matrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ v_[i+j*MM] = element;
+ ++j;
+ }
+ for( ; j<N; ++j ) {
+ v_[i+j*MM] = Type();
+ }
+ ++i;
+ }
+
+ BLAZE_INTERNAL_ASSERT( i == M, "Invalid number of elements detected" );
+
+ if( IsNumeric<Type>::value ) {
+ for( ; i<MM; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all matrix elements.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param array Dynamic array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a dynamic array:
+
+ \code
+ using blaze::columnMajor;
+
+ int* array = new int[6];
+ // ... Initialization of the dynamic array
+ blaze::StaticMatrix<int,3,4,columnMajor> v( array, 2UL, 3UL );
+ delete[] array;
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the specified number of rows and/or columns exceeds the maximum
+// number of rows/column of the static matrix (i.e. \m is larger than M or \a n is larger than N),
+// a \a std::invalid_argument exception is thrown.\n
+// Note that it is expected that the given \a array has at least \a m by \a n elements. Providing
+// an array with less elements results in undefined behavior!
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the initialization array
+inline StaticMatrix<Type,M,N,true>::StaticMatrix( size_t m, size_t n, const Other* array )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( m > M || n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static matrix" );
+ }
+
+ for( size_t j=0UL; j<n; ++j ) {
+ for( size_t i=0UL; i<m; ++i )
+ v_[i+j*MM] = array[i+j*m];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=m; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+ }
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=n; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*MM] = Type();
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array initialization of all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the matrix with
+// a static array:
+
+ \code
+ using blaze::columnMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::StaticMatrix<int,3,3,columnMajor> A( init );
+ \endcode
+
+// The matrix is initialized with the values from the given array. Missing values are initialized
+// with default values (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the initialization array
+inline StaticMatrix<Type,M,N,true>::StaticMatrix( const Other (&array)[M][N] )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*MM] = array[i][j];
+
+ for( size_t i=M; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for StaticMatrix.
+//
+// \param m Matrix to be copied.
+//
+// The copy constructor is explicitly defined in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>::StaticMatrix( const StaticMatrix& m )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ for( size_t i=0UL; i<MM*N; ++i )
+ v_[i] = m.v_[i];
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different StaticMatrix instances.
+//
+// \param m Matrix to be copied.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other // Data type of the foreign matrix
+ , bool SO > // Storage order of the foreign matrix
+inline StaticMatrix<Type,M,N,true>::StaticMatrix( const StaticMatrix<Other,M,N,SO>& m )
+ : v_() // The statically allocated matrix elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*MM] = m(i,j);
+
+ for( size_t i=M; i<MM; ++i )
+ v_[i+j*MM] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different matrices.
+//
+// \param m Matrix to be copied.
+// \exception std::invalid_argument Invalid setup of static matrix.
+//
+// This constructor initializes the static matrix from the given matrix. In case the size of
+// the given matrix does not match the size of the static matrix (i.e. the number of rows is
+// not M or the number of columns is not N), a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the foreign matrix
+ , bool SO > // Storage order of the foreign matrix
+inline StaticMatrix<Type,M,N,true>::StaticMatrix( const Matrix<MT,SO>& m )
+ : v_() // The statically allocated matrix elements
+{
+ using blaze::assign;
+
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || MM == M );
+
+ if( (~m).rows() != M || (~m).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static matrix" );
+ }
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=( IsSparseMatrix<MT>::value ? 0UL : M ); i<MM; ++i ) {
+ v_[i+j*MM] = Type();
+ }
+ }
+
+ assign( *this, ~m );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::Reference
+ StaticMatrix<Type,M,N,true>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
+ return v_[i+j*MM];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return Reference-to-const to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::ConstReference
+ StaticMatrix<Type,M,N,true>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
+ return v_[i+j*MM];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::Reference
+ StaticMatrix<Type,M,N,true>::at( size_t i, size_t j )
+{
+ if( i >= M ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= N ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::ConstReference
+ StaticMatrix<Type,M,N,true>::at( size_t i, size_t j ) const
+{
+ if( i >= M ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= N ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the static matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The static matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a column are given by the \c columns() member functions, the total number
+// of elements including padding is given by the \c spacing() member function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::Pointer
+ StaticMatrix<Type,M,N,true>::data() noexcept
+{
+ return v_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the static matrix. Note that you
+// can NOT assume that all matrix elements lie adjacent to each other! The static matrix may
+// use techniques such as padding to improve the alignment of the data. Whereas the number of
+// elements within a column are given by the \c columns() member functions, the total number
+// of elements including padding is given by the \c spacing() member function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::ConstPointer
+ StaticMatrix<Type,M,N,true>::data() const noexcept
+{
+ return v_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::Pointer
+ StaticMatrix<Type,M,N,true>::data( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return v_ + j*MM;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the matrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::ConstPointer
+ StaticMatrix<Type,M,N,true>::data( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return v_ + j*MM;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::Iterator
+ StaticMatrix<Type,M,N,true>::begin( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return Iterator( v_ + j*MM );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::ConstIterator
+ StaticMatrix<Type,M,N,true>::begin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*MM );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::ConstIterator
+ StaticMatrix<Type,M,N,true>::cbegin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*MM );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::Iterator
+ StaticMatrix<Type,M,N,true>::end( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return Iterator( v_ + j*MM + M );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::ConstIterator
+ StaticMatrix<Type,M,N,true>::end( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*MM + M );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last element of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline typename StaticMatrix<Type,M,N,true>::ConstIterator
+ StaticMatrix<Type,M,N,true>::cend( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
+ return ConstIterator( v_ + j*MM + M );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all matrix elements.
+//
+// \param set Scalar value to be assigned to all matrix elements.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>&
+ StaticMatrix<Type,M,N,true>::operator=( const Type& set )
+{
+ for( size_t j=0UL; j<N; ++j )
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*MM] = set;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all matrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to static matrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the matrix
+// by means of an initializer list:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::StaticMatrix<int,3,3,columnMajor> A;
+ A = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ \endcode
+
+// The matrix elements are assigned the values from the given initializer list. Missing values
+// are initialized as default (as e.g. the value 6 in the example). Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>&
+ StaticMatrix<Type,M,N,true>::operator=( initializer_list< initializer_list<Type> > list )
+{
+ if( list.size() != M || determineColumns( list ) > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static matrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ v_[i+j*MM] = element;
+ ++j;
+ }
+ for( ; j<N; ++j ) {
+ v_[i+j*MM] = Type();
+ }
+ ++i;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Array assignment to all matrix elements.
+//
+// \param array \f$ M \times N \f$ dimensional array for the assignment.
+// \return Reference to the assigned matrix.
+//
+// This assignment operator offers the option to directly set all elements of the matrix:
+
+ \code
+ using blaze::columnMajor;
+
+ const int init[3][3] = { { 1, 2, 3 },
+ { 4, 5 },
+ { 7, 8, 9 } };
+ blaze::StaticMatrix<int,3UL,3UL,columnMajor> A;
+ A = init;
+ \endcode
+
+// The matrix is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the value 6 in the example).
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the initialization array
+inline StaticMatrix<Type,M,N,true>&
+ StaticMatrix<Type,M,N,true>::operator=( const Other (&array)[M][N] )
+{
+ for( size_t j=0UL; j<N; ++j )
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*MM] = array[i][j];
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for StaticMatrix.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// Explicit definition of a copy assignment operator for performance reasons.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>&
+ StaticMatrix<Type,M,N,true>::operator=( const StaticMatrix& rhs )
+{
+ using blaze::assign;
+
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different StaticMatrix instances.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other // Data type of the foreign matrix
+ , bool SO > // Storage order of the foreign matrix
+inline StaticMatrix<Type,M,N,true>&
+ StaticMatrix<Type,M,N,true>::operator=( const StaticMatrix<Other,M,N,SO>& rhs )
+{
+ using blaze::assign;
+
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be copied.
+// \return Reference to the assigned matrix.
+// \exception std::invalid_argument Invalid assignment to static matrix.
+//
+// This constructor initializes the matrix as a copy of the given matrix. In case the
+// number of rows of the given matrix is not M or the number of columns is not N, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline StaticMatrix<Type,M,N,true>& StaticMatrix<Type,M,N,true>::operator=( const Matrix<MT,SO>& rhs )
+{
+ using blaze::assign;
+
+ typedef TransExprTrait_<This> TT;
+ typedef CTransExprTrait_<This> CT;
+ typedef InvExprTrait_<This> IT;
+
+ if( (~rhs).rows() != M || (~rhs).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static matrix" );
+ }
+
+ if( IsSame<MT,TT>::value && (~rhs).isAliased( this ) ) {
+ transpose( typename IsSquare<This>::Type() );
+ }
+ else if( IsSame<MT,CT>::value && (~rhs).isAliased( this ) ) {
+ ctranspose( typename IsSquare<This>::Type() );
+ }
+ else if( !IsSame<MT,IT>::value && (~rhs).canAlias( this ) ) {
+ StaticMatrix tmp( ~rhs );
+ assign( *this, tmp );
+ }
+ else {
+ if( IsSparseMatrix<MT>::value )
+ reset();
+ assign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline StaticMatrix<Type,M,N,true>& StaticMatrix<Type,M,N,true>::operator+=( const Matrix<MT,SO>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).rows() != M || (~rhs).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ addAssign( *this, tmp );
+ }
+ else {
+ addAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline StaticMatrix<Type,M,N,true>& StaticMatrix<Type,M,N,true>::operator-=( const Matrix<MT,SO>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).rows() != M || (~rhs).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const ResultType_<MT> tmp( ~rhs );
+ subAssign( *this, tmp );
+ }
+ else {
+ subAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline StaticMatrix<Type,M,N,true>& StaticMatrix<Type,M,N,true>::operator*=( const Matrix<MT,SO>& rhs )
+{
+ if( M != N || (~rhs).rows() != M || (~rhs).columns() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const StaticMatrix tmp( *this * (~rhs) );
+ this->operator=( tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, StaticMatrix<Type,M,N,true> >&
+ StaticMatrix<Type,M,N,true>::operator*=( Other rhs )
+{
+ using blaze::assign;
+
+ assign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, StaticMatrix<Type,M,N,true> >&
+ StaticMatrix<Type,M,N,true>::operator/=( Other rhs )
+{
+ using blaze::assign;
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ assign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline constexpr size_t StaticMatrix<Type,M,N,true>::rows() const noexcept
+{
+ return M;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline constexpr size_t StaticMatrix<Type,M,N,true>::columns() const noexcept
+{
+ return N;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two columns.
+//
+// \return The spacing between the beginning of two columns.
+//
+// This function returns the spacing between the beginning of two column, i.e. the total number
+// of elements of a column.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline constexpr size_t StaticMatrix<Type,M,N,true>::spacing() const noexcept
+{
+ return MM;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline constexpr size_t StaticMatrix<Type,M,N,true>::capacity() const noexcept
+{
+ return MM*N;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified column.
+//
+// \param j The index of the column.
+// \return The current capacity of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline size_t StaticMatrix<Type,M,N,true>::capacity( size_t j ) const noexcept
+{
+ UNUSED_PARAMETER( j );
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return MM;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of non-zero elements in the matrix
+//
+// \return The number of non-zero elements in the dense matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline size_t StaticMatrix<Type,M,N,true>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t j=0UL; j<N; ++j )
+ for( size_t i=0UL; i<M; ++i )
+ if( !isDefault( v_[i+j*MM] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified column.
+//
+// \param j The index of the column.
+// \return The number of non-zero elements of column \a j.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline size_t StaticMatrix<Type,M,N,true>::nonZeros( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t iend( j*MM + M );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=j*MM; i<iend; ++i )
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::reset()
+{
+ using blaze::clear;
+
+ for( size_t j=0UL; j<N; ++j )
+ for( size_t i=0UL; i<M; ++i )
+ clear( v_[i+j*MM] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified column to the default initial values.
+//
+// \param j The index of the column.
+// \return void
+//
+// This function reset the values in the specified column to their default value. Note that
+// the capacity of the column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::reset( size_t j )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ for( size_t i=0UL; i<M; ++i )
+ clear( v_[i+j*MM] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+//
+// This function transposes the static matrix in-place. Note that this function can only be used
+// for square static matrices, i.e. if \a M is equal to N.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>& StaticMatrix<Type,M,N,true>::transpose()
+{
+ using std::swap;
+
+ BLAZE_STATIC_ASSERT( M == N );
+
+ for( size_t j=1UL; j<N; ++j )
+ for( size_t i=0UL; i<j; ++i )
+ swap( v_[i+j*MM], v_[j+i*MM] );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper function for self-transpose via the trans() function.
+//
+// \return void
+//
+// This function assists in the evaluation of self-transpose via the trans() function:
+
+ \code
+ blaze::StaticMatrix<int,3UL,3UL,blaze::columnMajor> A;
+
+ A = trans( A );
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::transpose( TrueType )
+{
+ transpose();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper function for self-transpose via the trans() function.
+//
+// \return void
+//
+// This function assists in the evaluation of self-transpose via the trans() function:
+
+ \code
+ blaze::StaticMatrix<int,3UL,3UL,blaze::columnMajor> A;
+
+ A = trans( A );
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::transpose( FalseType )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+//
+// This function transposes the static matrix in-place. Note that this function can only be used
+// for square static matrices, i.e. if \a M is equal to N.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline StaticMatrix<Type,M,N,true>& StaticMatrix<Type,M,N,true>::ctranspose()
+{
+ BLAZE_STATIC_ASSERT( M == N );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<j; ++i ) {
+ cswap( v_[i+j*MM], v_[j+i*MM] );
+ }
+ conjugate( v_[j+j*MM] );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper function for self-transpose via the ctrans() function.
+//
+// \return void
+//
+// This function assists in the evaluation of self-transpose via the ctrans() function:
+
+ \code
+ blaze::StaticMatrix<int,3UL,3UL,blaze::columnMajor> A;
+
+ A = ctrans( A );
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::ctranspose( TrueType )
+{
+ ctranspose();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper function for self-transpose via the ctrans() function.
+//
+// \return void
+//
+// This function assists in the evaluation of self-transpose via the ctrans() function:
+
+ \code
+ blaze::StaticMatrix<int,3UL,3UL,blaze::columnMajor> A;
+
+ A = ctrans( A );
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::ctranspose( FalseType )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A*=s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the scalar value
+inline StaticMatrix<Type,M,N,true>&
+ StaticMatrix<Type,M,N,true>::scale( const Other& scalar )
+{
+ for( size_t j=0UL; j<N; ++j )
+ for( size_t i=0UL; i<M; ++i )
+ v_[i+j*MM] *= scalar;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two static matrices.
+//
+// \param m The matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::swap( StaticMatrix& m ) noexcept
+{
+ using std::swap;
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ swap( v_[i+j*MM], m(i,j) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MEMORY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void* StaticMatrix<Type,M,N,true>::operator new( std::size_t size )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( StaticMatrix ), "Invalid number of bytes detected" );
+
+ return allocate<StaticMatrix>( 1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void* StaticMatrix<Type,M,N,true>::operator new[]( std::size_t size )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( StaticMatrix ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( StaticMatrix ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<StaticMatrix>( size/sizeof(StaticMatrix) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of the no-throw operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void* StaticMatrix<Type,M,N,true>::operator new( std::size_t size, const std::nothrow_t& )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( StaticMatrix ), "Invalid number of bytes detected" );
+
+ return allocate<StaticMatrix>( 1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of the no-throw operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticMatrix class template.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void* StaticMatrix<Type,M,N,true>::operator new[]( std::size_t size, const std::nothrow_t& )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( StaticMatrix ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( StaticMatrix ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<StaticMatrix>( size/sizeof(StaticMatrix) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::operator delete( void* ptr )
+{
+ deallocate( static_cast<StaticMatrix*>( ptr ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::operator delete[]( void* ptr )
+{
+ deallocate( static_cast<StaticMatrix*>( ptr ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of no-throw operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::operator delete( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<StaticMatrix*>( ptr ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class specific implementation of no-throw operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline void StaticMatrix<Type,M,N,true>::operator delete[]( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<StaticMatrix*>( ptr ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the static matrix are intact.
+//
+// \return \a true in case the static matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the static matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline bool StaticMatrix<Type,M,N,true>::isIntact() const noexcept
+{
+ if( IsNumeric<Type>::value ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=M; i<MM; ++i ) {
+ if( v_[i+j*MM] != Type() )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the foreign expression
+inline bool StaticMatrix<Type,M,N,true>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename Other > // Data type of the foreign expression
+inline bool StaticMatrix<Type,M,N,true>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is properly aligned in memory.
+//
+// \return \a true in case the matrix is aligned, \a false if not.
+//
+// This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of each column of the matrix are guaranteed to conform to
+// the alignment restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+inline bool StaticMatrix<Type,M,N,true>::isAligned() const noexcept
+{
+ return ( usePadding || rows() % SIMDSIZE == 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller than the number
+// of columns. Additionally, the row index must be a multiple of the number of values inside
+// the SIMD element. This function must \b NOT be called explicitly! It is used internally
+// for the performance optimized evaluation of expression templates. Calling this function
+// explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE typename StaticMatrix<Type,M,N,true>::SIMDType
+ StaticMatrix<Type,M,N,true>::load( size_t i, size_t j ) const noexcept
+{
+ if( usePadding )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE typename StaticMatrix<Type,M,N,true>::SIMDType
+ StaticMatrix<Type,M,N,true>::loada( size_t i, size_t j ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
+
+ return loada( &v_[i+j*MM] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE typename StaticMatrix<Type,M,N,true>::SIMDType
+ StaticMatrix<Type,M,N,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+
+ return loadu( &v_[i+j*MM] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense matrix. The row index
+// must be smaller than the number of rows and the column index must be smaller then the number
+// of columns. Additionally, the row index must be a multiple of the number of values inside the
+// SIMD element. This function must \b NOT be called explicitly! It is used internally for the
+// performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE void
+ StaticMatrix<Type,M,N,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( usePadding )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE void
+ StaticMatrix<Type,M,N,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
+
+ storea( &v_[i+j*MM], value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense matrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE void
+ StaticMatrix<Type,M,N,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+
+ storeu( &v_[i+j*MM], value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense matrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the row index must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+BLAZE_ALWAYS_INLINE void
+ StaticMatrix<Type,M,N,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( i < M, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < N, "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
+
+ stream( &v_[i+j*MM], value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename StaticMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ StaticMatrix<Type,M,N,true>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ v_[i+j*MM] = (~rhs)(i,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename StaticMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedAssign<MT> >
+ StaticMatrix<Type,M,N,true>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ const size_t ipos( ( remainder )?( M & size_t(-SIMDSIZE) ):( M ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, j, (~rhs).load(i,j) );
+ }
+ for( ; remainder && i<M; ++i ) {
+ v_[i+j*MM] = (~rhs)(i,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,true>::assign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*MM] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,true>::assign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*MM] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename StaticMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ StaticMatrix<Type,M,N,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[j+j*MM] += (~rhs)(j,j);
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ v_[i+j*MM] += (~rhs)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename StaticMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT> >
+ StaticMatrix<Type,M,N,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, j, load(i,j) + (~rhs).load(i,j) );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ v_[i+j*MM] += (~rhs)(i,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,true>::addAssign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*MM] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,true>::addAssign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*MM] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline DisableIf_<typename StaticMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ StaticMatrix<Type,M,N,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ if( IsDiagonal<MT>::value )
+ {
+ v_[j+j*MM] -= (~rhs)(j,j);
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ v_[i+j*MM] -= (~rhs)(i,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline EnableIf_<typename StaticMatrix<Type,M,N,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT> >
+ StaticMatrix<Type,M,N,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ const bool remainder( !usePadding || !IsPadded<MT>::value );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, j, load(i,j) - (~rhs).load(i,j) );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ v_[i+j*MM] -= (~rhs)(i,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,true>::subAssign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t j=0UL; j<N; ++j )
+ for( ConstIterator_<MT> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ v_[element->index()+j*MM] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N > // Number of columns
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void StaticMatrix<Type,M,N,true>::subAssign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" );
+
+ for( size_t i=0UL; i<M; ++i )
+ for( ConstIterator_<MT> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ v_[i+element->index()*MM] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// UNDEFINED CLASS TEMPLATE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StaticMatrix for zero columns.
+// \ingroup static_matrix
+//
+// This specialization of the StaticMatrix class template is left undefined and therefore
+// prevents the instantiation for zero columns.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , bool SO > // Storage order
+class StaticMatrix<Type,M,0UL,SO>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StaticMatrix for zero rows.
+// \ingroup static_matrix
+//
+// This specialization of the StaticMatrix class template is left undefined and therefore
+// prevents the instantiation for zero rows.
+*/
+template< typename Type // Data type of the matrix
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+class StaticMatrix<Type,0UL,N,SO>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StaticMatrix for 0 rows and 0 columns.
+// \ingroup static_matrix
+//
+// This specialization of the StaticMatrix class template is left undefined and therefore
+// prevents the instantiation for 0 rows and 0 columns.
+*/
+template< typename Type // Data type of the matrix
+ , bool SO > // Storage order
+class StaticMatrix<Type,0UL,0UL,SO>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// STATICMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name StaticMatrix operators */
+//@{
+template< typename Type, size_t M, size_t N, bool SO >
+inline void reset( StaticMatrix<Type,M,N,SO>& m );
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline void reset( StaticMatrix<Type,M,N,SO>& m, size_t i );
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline void clear( StaticMatrix<Type,M,N,SO>& m );
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline bool isDefault( const StaticMatrix<Type,M,N,SO>& m );
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline bool isIntact( const StaticMatrix<Type,M,N,SO>& m ) noexcept;
+
+template< typename Type, size_t M, size_t N, bool SO >
+inline void swap( StaticMatrix<Type,M,N,SO>& a, StaticMatrix<Type,M,N,SO>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given static matrix.
+// \ingroup static_matrix
+//
+// \param m The matrix to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void reset( StaticMatrix<Type,M,N,SO>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column of the given static matrix.
+// \ingroup static_matrix
+//
+// \param m The matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given static matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void reset( StaticMatrix<Type,M,N,SO>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given static matrix.
+// \ingroup static_matrix
+//
+// \param m The matrix to be cleared.
+// \return void
+//
+// Clearing a static matrix is equivalent to resetting it via the reset() function.
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void clear( StaticMatrix<Type,M,N,SO>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given dynamic matrix is in default state.
+// \ingroup dynamic_matrix
+//
+// \param m The matrix to be tested for its default state.
+// \return \a true in case the given matrix's rows and columns are zero, \a false otherwise.
+//
+// This function checks whether the static matrix is in default (constructed) state. In case it
+// is in default state, the function returns \a true, else it will return \a false. The following
+// example demonstrates the use of the \a isDefault() function:
+
+ \code
+ blaze::StaticMatrix<double,3,5> A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline bool isDefault( const StaticMatrix<Type,M,N,SO>& m )
+{
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<M; ++i )
+ for( size_t j=0UL; j<N; ++j )
+ if( !isDefault( m(i,j) ) ) return false;
+ }
+ else {
+ for( size_t j=0UL; j<N; ++j )
+ for( size_t i=0UL; i<M; ++i )
+ if( !isDefault( m(i,j) ) ) return false;
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given static matrix are intact.
+// \ingroup static_matrix
+//
+// \param m The static matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the static matrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::StaticMatrix<double,3,5> A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline bool isIntact( const StaticMatrix<Type,M,N,SO>& m ) noexcept
+{
+ return m.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two static matrices.
+// \ingroup static_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the matrix
+ , size_t M // Number of rows
+ , size_t N // Number of columns
+ , bool SO > // Storage order
+inline void swap( StaticMatrix<Type,M,N,SO>& a, StaticMatrix<Type,M,N,SO>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct Rows< StaticMatrix<T,M,N,SO> > : public SizeT<M>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct Columns< StaticMatrix<T,M,N,SO> > : public SizeT<N>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSQUARE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool SO >
+struct IsSquare< StaticMatrix<T,N,N,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct HasConstDataAccess< StaticMatrix<T,M,N,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct HasMutableDataAccess< StaticMatrix<T,M,N,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct IsAligned< StaticMatrix<T,M,N,SO> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t M, size_t N, bool SO >
+struct IsPadded< StaticMatrix<T,M,N,SO> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct AddTrait< StaticMatrix<T1,M,N,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct AddTrait< StaticMatrix<T1,M,N,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct SubTrait< StaticMatrix<T1,M,N,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct SubTrait< StaticMatrix<T1,M,N,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MultTrait< StaticMatrix<T1,M,N,SO>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = StaticMatrix< MultTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< T1, StaticMatrix<T2,M,N,SO>, EnableIf_<IsNumeric<T1> > >
+{
+ using Type = StaticMatrix< MultTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MultTrait< StaticMatrix<T1,M,N,SO>, StaticVector<T2,N,false> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, size_t M, typename T2, size_t N, bool SO >
+struct MultTrait< StaticVector<T1,M,true>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, size_t L >
+struct MultTrait< StaticMatrix<T1,M,N,SO>, HybridVector<T2,L,false> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, size_t L, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< HybridVector<T1,L,true>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MultTrait< StaticMatrix<T1,M,N,SO>, DynamicVector<T2,false> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< DynamicVector<T1,true>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF >
+struct MultTrait< StaticMatrix<T1,M,N,SO>, CustomVector<T2,AF,PF,false> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< CustomVector<T1,AF,PF,true>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MultTrait< StaticMatrix<T1,M,N,SO>, CompressedVector<T2,false> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, M, false >;
+};
+
+template< typename T1, typename T2, size_t M, size_t N, bool SO >
+struct MultTrait< CompressedVector<T1,true>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, true >;
+};
+
+template< typename T1, size_t M, size_t K, bool SO1, typename T2, size_t N, bool SO2 >
+struct MultTrait< StaticMatrix<T1,M,K,SO1>, StaticMatrix<T2,K,N,SO2> >
+{
+ using Type = StaticMatrix< MultTrait_<T1,T2>, M, N, SO1 >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct DivTrait< StaticMatrix<T1,M,N,SO>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = StaticMatrix< DivTrait_<T1,T2>, M, N, SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct MathTrait< StaticMatrix<T1,M,N,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using HighType = StaticMatrix< typename MathTrait<T1,T2>::HighType, M, N, SO >;
+ using LowType = StaticMatrix< typename MathTrait<T1,T2>::LowType , M, N, SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO >
+struct SubmatrixTrait< StaticMatrix<T1,M,N,SO> >
+{
+ using Type = HybridMatrix<T1,M,N,SO>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO >
+struct RowTrait< StaticMatrix<T1,M,N,SO> >
+{
+ using Type = StaticVector<T1,N,true>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t M, size_t N, bool SO >
+struct ColumnTrait< StaticMatrix<T1,M,N,SO> >
+{
+ using Type = StaticVector<T1,M,false>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/dense/StaticVector.h b/src/cpu/blaze/math/dense/StaticVector.h
new file mode 100644
index 00000000..eb7a4c7e
--- /dev/null
+++ b/src/cpu/blaze/math/dense/StaticVector.h
@@ -0,0 +1,2842 @@
+//=================================================================================================
+/*!
+// \file blaze/math/dense/StaticVector.h
+// \brief Header file for the implementation of a fixed-size vector
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_DENSE_STATICVECTOR_H_
+#define _BLAZE_MATH_DENSE_STATICVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/dense/DenseIterator.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/TransposeFlag.h>
+#include <blaze/util/AlignedArray.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/mpl/NextMultiple.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup static_vector StaticVector
+// \ingroup dense_vector
+*/
+/*!\brief Efficient implementation of a fixed-sized vector.
+// \ingroup static_vector
+//
+// The StaticVector class template is the representation of a fixed-size vector with statically
+// allocated elements of arbitrary type. The type of the elements, the number of elements and
+// the transpose flag of the vector can be specified via the three template parameters:
+
+ \code
+ template< typename Type, size_t N, bool TF >
+ class StaticVector;
+ \endcode
+
+// - Type: specifies the type of the vector elements. StaticVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - N : specifies the total number of vector elements. It is expected that StaticVector is
+// only used for tiny and small vectors.
+// - TF : specifies whether the vector is a row vector (\a blaze::rowVector) or a column
+// vector (\a blaze::columnVector). The default value is \a blaze::columnVector.
+//
+// These contiguously stored elements can be directly accessed with the subscript operator. The
+// numbering of the vector elements is
+
+ \f[\left(\begin{array}{*{4}{c}}
+ 0 & 1 & \cdots & N-1 \\
+ \end{array}\right)\f]
+
+// The use of StaticVector is very natural and intuitive. All operations (addition, subtraction,
+// multiplication, scaling, ...) can be performed on all possible combinations of dense and sparse
+// vectors with fitting element types. The following example gives an impression of the use of a
+// 2-dimensional StaticVector:
+
+ \code
+ using blaze::StaticVector;
+ using blaze::CompressedVector;
+ using blaze::StaticMatrix;
+
+ StaticVector<double,2UL> a; // Default initialized 2D vector
+ a[0] = 1.0; // Initialization of the first element
+ a[1] = 2.0; // Initialization of the second element
+
+ StaticVector<double,2UL> b( 3.0, 2.0 ); // Directly initialized 2D vector
+ CompressedVector<float> c( 2 ); // Empty sparse single precision vector
+ StaticVector<double,2UL> d; // Default constructed static vector
+ StaticMatrix<double,2UL,2UL> A; // Default constructed static row-major matrix
+
+ d = a + b; // Vector addition between vectors of equal element type
+ d = a - c; // Vector subtraction between a dense and sparse vector with different element types
+ d = a * b; // Component-wise vector multiplication
+
+ a *= 2.0; // In-place scaling of vector
+ d = a * 2.0; // Scaling of vector a
+ d = 2.0 * a; // Scaling of vector a
+
+ d += a - b; // Addition assignment
+ d -= a + c; // Subtraction assignment
+ d *= a * b; // Multiplication assignment
+
+ double scalar = trans( a ) * b; // Scalar/dot/inner product between two vectors
+
+ A = a * trans( b ); // Outer product between two vectors
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF = defaultTransposeFlag > // Transpose flag
+class StaticVector : public DenseVector< StaticVector<Type,N,TF>, TF >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef StaticVector<Type,N,TF> This; //!< Type of this StaticVector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this StaticVector instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef StaticVector<Type,N,!TF> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the vector elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the vector elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const StaticVector& CompositeType; //!< Data type for composite expression templates.
+
+ typedef Type& Reference; //!< Reference to a non-constant vector value.
+ typedef const Type& ConstReference; //!< Reference to a constant vector value.
+ typedef Type* Pointer; //!< Pointer to a non-constant vector value.
+ typedef const Type* ConstPointer; //!< Pointer to a constant vector value.
+
+ typedef DenseIterator<Type,aligned> Iterator; //!< Iterator over non-constant elements.
+ typedef DenseIterator<const Type,aligned> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a StaticVector with different data/element type.
+ */
+ template< typename ET > // Data type of the other vector
+ struct Rebind {
+ typedef StaticVector<ET,N,TF> Other; //!< The type of the other StaticVector.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
+ in can be optimized via SIMD operations. In case the element type of the vector is a
+ vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
+ it is set to \a false. */
+ enum : bool { simdEnabled = IsVectorizable<Type>::value };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline StaticVector();
+ explicit inline StaticVector( const Type& init );
+ explicit inline StaticVector( initializer_list<Type> list );
+
+ template< typename Other >
+ explicit inline StaticVector( size_t n, const Other* array );
+
+ template< typename Other >
+ explicit inline StaticVector( const Other (&array)[N] );
+
+ inline StaticVector( const StaticVector& v );
+ template< typename Other > inline StaticVector( const StaticVector<Other,N,TF>& v );
+ template< typename VT > inline StaticVector( const Vector<VT,TF>& v );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) noexcept;
+ inline ConstReference operator[]( size_t index ) const noexcept;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin () noexcept;
+ inline ConstIterator begin () const noexcept;
+ inline ConstIterator cbegin() const noexcept;
+ inline Iterator end () noexcept;
+ inline ConstIterator end () const noexcept;
+ inline ConstIterator cend () const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline StaticVector& operator=( const Type& rhs );
+ inline StaticVector& operator=( initializer_list<Type> list );
+
+ template< typename Other >
+ inline StaticVector& operator=( const Other (&array)[N] );
+
+ inline StaticVector& operator=( const StaticVector& rhs );
+ template< typename Other > inline StaticVector& operator=( const StaticVector<Other,N,TF>& rhs );
+
+ template< typename VT > inline StaticVector& operator= ( const Vector<VT,TF>& rhs );
+ template< typename VT > inline StaticVector& operator+=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline StaticVector& operator-=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline StaticVector& operator*=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline StaticVector& operator/=( const DenseVector<VT,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, StaticVector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, StaticVector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline constexpr size_t size() const noexcept;
+ inline constexpr size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline StaticVector& scale( const Other& scalar );
+ inline void swap( StaticVector& v ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Memory functions****************************************************************************
+ /*!\name Memory functions */
+ //@{
+ static inline void* operator new ( std::size_t size );
+ static inline void* operator new[]( std::size_t size );
+ static inline void* operator new ( std::size_t size, const std::nothrow_t& );
+ static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
+
+ static inline void operator delete ( void* ptr );
+ static inline void operator delete[]( void* ptr );
+ static inline void operator delete ( void* ptr, const std::nothrow_t& );
+ static inline void operator delete[]( void* ptr, const std::nothrow_t& );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDAdd< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDSub< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDMult< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< Type, ElementType_<VT> >::value &&
+ HasSIMDDiv< Type, ElementType_<VT> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! The number of elements packed within a single SIMD vector.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Debugging functions*************************************************************************
+ /*!\name Debugging functions */
+ //@{
+ inline bool isIntact() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool isAligned() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAssign<VT> > assign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline DisableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+
+ template< typename VT >
+ inline EnableIf_<VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Alignment adjustment.
+ enum : size_t { NN = ( usePadding )?( NextMultiple< SizeT<N>, SizeT<SIMDSIZE> >::value ):( N ) };
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ AlignedArray<Type,NN> v_; //!< The statically allocated vector elements.
+ /*!< Access to the vector values is gained via the subscript operator.
+ The order of the elements is
+ \f[\left(\begin{array}{*{4}{c}}
+ 0 & 1 & \cdots & N-1 \\
+ \end{array}\right)\f] */
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_STATIC_ASSERT( !usePadding || ( NN % SIMDSIZE == 0UL ) );
+ BLAZE_STATIC_ASSERT( NN >= N );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for StaticVector.
+//
+// All vector elements are initialized to the default value (i.e. 0 for integral data types).
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline StaticVector<Type,N,TF>::StaticVector()
+ : v_() // The statically allocated vector elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=0UL; i<NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a homogenous initialization of all elements.
+//
+// \param init Initial value for all vector elements.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline StaticVector<Type,N,TF>::StaticVector( const Type& init )
+ : v_() // The statically allocated vector elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = init;
+
+ for( size_t i=N; i<NN; ++i )
+ v_[i] = Type();
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List initialization of all vector elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid setup of static vector.
+//
+// This constructor provides the option to explicitly initialize the elements of the vector by
+// means of an initializer list:
+
+ \code
+ blaze::StaticVector<double,3UL> v1{ 4.2, 6.3, -1.2 };
+ \endcode
+
+// The vector elements are initialized by the values of the given initializer list. Missing values
+// are initialized as default. Note that in case the size of the initializer list exceeds the size
+// of the vector, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline StaticVector<Type,N,TF>::StaticVector( initializer_list<Type> list )
+ : v_() // The statically allocated vector elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( list.size() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static vector" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), v_.data() ), v_.data()+NN, Type() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all vector elements.
+//
+// \param n The size of the vector.
+// \param array Dynamic array for the initialization.
+//
+// This constructor offers the option to directly initialize the elements of the vector with a
+// dynamic array:
+
+ \code
+ const double array* = new double[2];
+ // ... Initialization of the array
+ blaze::StaticVector<double,2> v( array, 2UL );
+ delete[] array;
+ \endcode
+
+// The vector is initialized with the values from the given array. Missing values are initialized
+// with default values. In case the size of the given vector exceeds the maximum size of the
+// static vector (i.e. is larger than N), a \a std::invalid_argument exception is thrown.\n
+// Note that it is expected that the given \a array has at least \a n elements. Providing an
+// array with less elements results in undefined behavior!
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the initialization array
+inline StaticVector<Type,N,TF>::StaticVector( size_t n, const Other* array )
+ : v_() // The statically allocated vector elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( n > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static vector" );
+ }
+
+ for( size_t i=0UL; i<n; ++i )
+ v_[i] = array[i];
+
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=n; i<NN; ++i )
+ v_[i] = Type();
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array initialization of all vector elements.
+//
+// \param array M-dimensional array for the initialization.
+//
+// This assignment operator offers the option to directly initialize the elements of the vector
+// with a static array:
+
+ \code
+ const double init[3] = { 1.0, 2.0 };
+ blaze::StaticVector<double,3> v( init );
+ \endcode
+
+// The vector is initialized with the values from the given array. Missing values are initialized
+// with default values (as e.g. the third value in the example).
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the initialization array
+inline StaticVector<Type,N,TF>::StaticVector( const Other (&array)[N] )
+ : v_() // The statically allocated vector elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = array[i];
+
+ for( size_t i=N; i<NN; ++i )
+ v_[i] = Type();
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for StaticVector.
+//
+// \param v Vector to be copied.
+//
+// The copy constructor is explicitly defined in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline StaticVector<Type,N,TF>::StaticVector( const StaticVector& v )
+ : v_() // The statically allocated vector elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<NN; ++i )
+ v_[i] = v.v_[i];
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different StaticVector instances.
+//
+// \param v Vector to be copied.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign vector
+inline StaticVector<Type,N,TF>::StaticVector( const StaticVector<Other,N,TF>& v )
+ : v_() // The statically allocated vector elements
+{
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = v[i];
+
+ for( size_t i=N; i<NN; ++i )
+ v_[i] = Type();
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different vectors.
+//
+// \param v Vector to be copied.
+// \exception std::invalid_argument Invalid setup of static vector.
+//
+// This constructor initializes the static vector from the given vector. In case the size
+// of the given vector does not match the size of the static vector (i.e. is not N), a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the foreign vector
+inline StaticVector<Type,N,TF>::StaticVector( const Vector<VT,TF>& v )
+ : v_() // The statically allocated vector elements
+{
+ using blaze::assign;
+
+ BLAZE_STATIC_ASSERT( IsVectorizable<Type>::value || NN == N );
+
+ if( (~v).size() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static vector" );
+ }
+
+ for( size_t i=( IsSparseVector<VT>::value ? 0UL : N ); i<NN; ++i ) {
+ v_[i] = Type();
+ }
+
+ assign( *this, ~v );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::Reference
+ StaticVector<Type,N,TF>::operator[]( size_t index ) noexcept
+{
+ BLAZE_USER_ASSERT( index < N, "Invalid vector access index" );
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference-to-const to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::ConstReference
+ StaticVector<Type,N,TF>::operator[]( size_t index ) const noexcept
+{
+ BLAZE_USER_ASSERT( index < N, "Invalid vector access index" );
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::Reference
+ StaticVector<Type,N,TF>::at( size_t index )
+{
+ if( index >= N ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::ConstReference
+ StaticVector<Type,N,TF>::at( size_t index ) const
+{
+ if( index >= N ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the static vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::Pointer StaticVector<Type,N,TF>::data() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the vector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the static vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::ConstPointer StaticVector<Type,N,TF>::data() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the static vector.
+//
+// \return Iterator to the first element of the static vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::Iterator StaticVector<Type,N,TF>::begin() noexcept
+{
+ return Iterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the static vector.
+//
+// \return Iterator to the first element of the static vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::ConstIterator StaticVector<Type,N,TF>::begin() const noexcept
+{
+ return ConstIterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the static vector.
+//
+// \return Iterator to the first element of the static vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::ConstIterator StaticVector<Type,N,TF>::cbegin() const noexcept
+{
+ return ConstIterator( v_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the static vector.
+//
+// \return Iterator just past the last element of the static vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::Iterator StaticVector<Type,N,TF>::end() noexcept
+{
+ return Iterator( v_ + N );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the static vector.
+//
+// \return Iterator just past the last element of the static vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::ConstIterator StaticVector<Type,N,TF>::end() const noexcept
+{
+ return ConstIterator( v_ + N );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the static vector.
+//
+// \return Iterator just past the last element of the static vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline typename StaticVector<Type,N,TF>::ConstIterator StaticVector<Type,N,TF>::cend() const noexcept
+{
+ return ConstIterator( v_ + N );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Homogenous assignment to all vector elements.
+//
+// \param rhs Scalar value to be assigned to all vector elements.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator=( const Type& rhs )
+{
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief List assignment to all vector elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to static vector.
+//
+// This assignment operator offers the option to directly assign to all elements of the vector
+// by means of an initializer list:
+
+ \code
+ blaze::StaticVector<double,3UL> v;
+ v = { 4.2, 6.3, -1.2 };
+ \endcode
+
+// The vector elements are assigned the values from the given initializer list. Missing values
+// are reset to their default state. Note that in case the size of the initializer list exceeds
+// the size of the vector, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator=( initializer_list<Type> list )
+{
+ if( list.size() > N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static vector" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), v_.data() ), v_.data()+N, Type() );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Array assignment to all vector elements.
+//
+// \param array M-dimensional array for the assignment.
+// \return Reference to the assigned vector.
+//
+// This assignment operator offers the option to directly set all elements of the vector:
+
+ \code
+ const double init[3] = { 1.0, 2.0 };
+ blaze::StaticVector<double,3> v;
+ v = init;
+ \endcode
+
+// The vector is assigned the values from the given array. Missing values are initialized with
+// default values (as e.g. the third value in the example).
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the initialization array
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator=( const Other (&array)[N] )
+{
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = array[i];
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for StaticVector.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+//
+// Explicit definition of a copy assignment operator for performance reasons.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator=( const StaticVector& rhs )
+{
+ using blaze::assign;
+
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different StaticVector instances.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign vector
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator=( const StaticVector<Other,N,TF>& rhs )
+{
+ using blaze::assign;
+
+ assign( *this, ~rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be copied.
+// \return Reference to the assigned vector.
+// \exception std::invalid_argument Invalid assignment to static vector.
+//
+// This constructor initializes the vector as a copy of the given vector. In case the
+// size of the given vector is not N, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator=( const Vector<VT,TF>& rhs )
+{
+ using blaze::assign;
+
+ if( (~rhs).size() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static vector" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ StaticVector tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ assign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator+=( const Vector<VT,TF>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).size() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ StaticVector tmp( ~rhs );
+ addAssign( *this, tmp );
+ }
+ else {
+ addAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator-=( const Vector<VT,TF>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).size() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ StaticVector tmp( ~rhs );
+ subAssign( *this, tmp );
+ }
+ else {
+ subAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the vector.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator*=( const Vector<VT,TF>& rhs )
+{
+ using blaze::multAssign;
+
+ if( (~rhs).size() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( IsSparseVector<VT>::value || (~rhs).canAlias( this ) ) {
+ const StaticVector tmp( *this * (~rhs) );
+ this->operator=( tmp );
+ }
+ else {
+ multAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::operator/=( const DenseVector<VT,TF>& rhs )
+{
+ using blaze::divAssign;
+
+ if( (~rhs).size() != N ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ const StaticVector tmp( *this / (~rhs) );
+ this->operator=( tmp );
+ }
+ else {
+ divAssign( *this, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a vector and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, StaticVector<Type,N,TF> >&
+ StaticVector<Type,N,TF>::operator*=( Other rhs )
+{
+ using blaze::assign;
+
+ assign( *this, (*this) * rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a vector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, StaticVector<Type,N,TF> >&
+ StaticVector<Type,N,TF>::operator/=( Other rhs )
+{
+ using blaze::assign;
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ assign( *this, (*this) / rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the vector.
+//
+// \return The size of the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline constexpr size_t StaticVector<Type,N,TF>::size() const noexcept
+{
+ return N;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the vector.
+//
+// \return The capacity of the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline constexpr size_t StaticVector<Type,N,TF>::capacity() const noexcept
+{
+ return NN;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the vector.
+//
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline size_t StaticVector<Type,N,TF>::nonZeros() const
+{
+ size_t nonzeros( 0 );
+
+ for( size_t i=0UL; i<N; ++i ) {
+ if( !isDefault( v_[i] ) )
+ ++nonzeros;
+ }
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void StaticVector<Type,N,TF>::reset()
+{
+ using blaze::clear;
+ for( size_t i=0UL; i<N; ++i )
+ clear( v_[i] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}*=s \f$).
+//
+// \param scalar The scalar value for the vector scaling.
+// \return Reference to the vector.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline StaticVector<Type,N,TF>& StaticVector<Type,N,TF>::scale( const Other& scalar )
+{
+ for( size_t i=0; i<N; ++i )
+ v_[i] *= scalar;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two static vectors.
+//
+// \param v The vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void StaticVector<Type,N,TF>::swap( StaticVector& v ) noexcept
+{
+ using std::swap;
+
+ for( size_t i=0UL; i<N; ++i )
+ swap( v_[i], v.v_[i] );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MEMORY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticVector class template.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void* StaticVector<Type,N,TF>::operator new( std::size_t size )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( StaticVector ), "Invalid number of bytes detected" );
+
+ return allocate<StaticVector>( 1UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticVector class template.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void* StaticVector<Type,N,TF>::operator new[]( std::size_t size )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( StaticVector ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( StaticVector ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<StaticVector>( size/sizeof(StaticVector) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of the no-throw operator new.
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticVector class template.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void* StaticVector<Type,N,TF>::operator new( std::size_t size, const std::nothrow_t& )
+{
+ UNUSED_PARAMETER( size );
+
+ BLAZE_INTERNAL_ASSERT( size == sizeof( StaticVector ), "Invalid number of bytes detected" );
+
+ return allocate<StaticVector>( 1UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of the no-throw operator new[].
+//
+// \param size The total number of bytes to be allocated.
+// \return Pointer to the newly allocated memory.
+// \exception std::bad_alloc Allocation failed.
+//
+// This class-specific implementation of operator new provides the functionality to allocate
+// dynamic memory based on the alignment restrictions of the StaticVector class template.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void* StaticVector<Type,N,TF>::operator new[]( std::size_t size, const std::nothrow_t& )
+{
+ BLAZE_INTERNAL_ASSERT( size >= sizeof( StaticVector ) , "Invalid number of bytes detected" );
+ BLAZE_INTERNAL_ASSERT( size % sizeof( StaticVector ) == 0UL, "Invalid number of bytes detected" );
+
+ return allocate<StaticVector>( size/sizeof(StaticVector) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void StaticVector<Type,N,TF>::operator delete( void* ptr )
+{
+ deallocate( static_cast<StaticVector*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void StaticVector<Type,N,TF>::operator delete[]( void* ptr )
+{
+ deallocate( static_cast<StaticVector*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of no-throw operator delete.
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void StaticVector<Type,N,TF>::operator delete( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<StaticVector*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Class specific implementation of no-throw operator delete[].
+//
+// \param ptr The memory to be deallocated.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void StaticVector<Type,N,TF>::operator delete[]( void* ptr, const std::nothrow_t& )
+{
+ deallocate( static_cast<StaticVector*>( ptr ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEBUGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the static vector are intact.
+//
+// \return \a true in case the static vector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the static vector are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline bool StaticVector<Type,N,TF>::isIntact() const noexcept
+{
+ if( IsNumeric<Type>::value ) {
+ for( size_t i=N; i<NN; ++i ) {
+ if( v_[i] != Type() )
+ return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address can alias with the vector. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool StaticVector<Type,N,TF>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address is aliased with the vector. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool StaticVector<Type,N,TF>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is properly aligned in memory.
+//
+// \return \a true in case the vector is aligned, \a false if not.
+//
+// This function returns whether the vector is guaranteed to be properly aligned in memory, i.e.
+// whether the beginning and the end of the vector are guaranteed to conform to the alignment
+// restrictions of the element type \a Type.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline bool StaticVector<Type,N,TF>::isAligned() const noexcept
+{
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename StaticVector<Type,N,TF>::SIMDType
+ StaticVector<Type,N,TF>::load( size_t index ) const noexcept
+{
+ return loada( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename StaticVector<Type,N,TF>::SIMDType
+ StaticVector<Type,N,TF>::loada( size_t index ) const noexcept
+{
+ using blaze::loada;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
+
+ return loada( &v_[index] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned load of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename StaticVector<Type,N,TF>::SIMDType
+ StaticVector<Type,N,TF>::loadu( size_t index ) const noexcept
+{
+ using blaze::loadu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+
+ return loadu( &v_[index] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense vector. The index
+// must be smaller than the number of vector elements and it must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ StaticVector<Type,N,TF>::store( size_t index, const SIMDType& value ) noexcept
+{
+ storea( index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense vector. The
+// index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ StaticVector<Type,N,TF>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storea;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
+
+ storea( &v_[index], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense vector.
+// The index must be smaller than the number of vector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ StaticVector<Type,N,TF>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::storeu;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+
+ storeu( &v_[index], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a SIMD element of the vector.
+//
+// \param index Access index. The index must be smaller than the number of vector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense vector. The index must be smaller than the number of vector elements and it must be
+// a multiple of the number of values inside the SIMD element. This function must \b NOT be
+// called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ StaticVector<Type,N,TF>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ using blaze::stream;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
+
+ stream( &v_[index], value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ StaticVector<Type,N,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] = (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ StaticVector<Type,N,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( N & size_t(-SIMDSIZE) ):( N ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, (~rhs).load(i) );
+ }
+ for( ; remainder && i<N; ++i ) {
+ v_[i] = (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void StaticVector<Type,N,TF>::assign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ StaticVector<Type,N,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] += (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ StaticVector<Type,N,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( N & size_t(-SIMDSIZE) ):( N ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, load(i) + (~rhs).load(i) );
+ }
+ for( ; remainder && i<N; ++i ) {
+ v_[i] += (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void StaticVector<Type,N,TF>::addAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] += element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ StaticVector<Type,N,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] -= (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ StaticVector<Type,N,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( N & size_t(-SIMDSIZE) ):( N ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, load(i) - (~rhs).load(i) );
+ }
+ for( ; remainder && i<N; ++i ) {
+ v_[i] -= (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void StaticVector<Type,N,TF>::subAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] -= element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ StaticVector<Type,N,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] *= (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ StaticVector<Type,N,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ const bool remainder( !usePadding || !IsPadded<VT>::value );
+
+ const size_t ipos( ( remainder )?( N & size_t(-SIMDSIZE) ):( N ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, load(i) * (~rhs).load(i) );
+ }
+ for( ; remainder && i<N; ++i ) {
+ v_[i] *= (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void StaticVector<Type,N,TF>::multAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ const StaticVector tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ v_[element->index()] = tmp[element->index()] * element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ StaticVector<Type,N,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<N; ++i )
+ v_[i] /= (~rhs)[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_<typename StaticVector<Type,N,TF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ StaticVector<Type,N,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
+
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" );
+
+ const size_t ipos( N & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( N - ( N % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ store( i, load(i) / (~rhs).load(i) );
+ }
+ for( ; i<N; ++i ) {
+ v_[i] /= (~rhs)[i];
+ }
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// UNDEFINED CLASS TEMPLATE SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of StaticVector for 0 elements.
+// \ingroup static_vector
+//
+// This specialization of the StaticVector class template is left undefined and therefore
+// prevents the instantiation for 0 elements.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+class StaticVector<Type,0UL,TF>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// STATICVECTOR OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name StaticVector operators */
+//@{
+template< typename Type, size_t N, bool TF >
+inline void reset( StaticVector<Type,N,TF>& v );
+
+template< typename Type, size_t N, bool TF >
+inline void clear( StaticVector<Type,N,TF>& v );
+
+template< typename Type, size_t N, bool TF >
+inline bool isDefault( const StaticVector<Type,N,TF>& v );
+
+template< typename Type, size_t N, bool TF >
+inline bool isIntact( const StaticVector<Type,N,TF>& v ) noexcept;
+
+template< typename Type, bool TF >
+inline const StaticVector<Type,2UL,TF> perp( const StaticVector<Type,2UL,TF>& v );
+
+template< typename Type, bool TF >
+inline const StaticVector<Type,3UL,TF> perp( const StaticVector<Type,3UL,TF>& v );
+
+template< typename Type, size_t N, bool TF >
+inline void swap( StaticVector<Type,N,TF>& a, StaticVector<Type,N,TF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given static vector.
+// \ingroup static_vector
+//
+// \param v The vector to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void reset( StaticVector<Type,N,TF>& v )
+{
+ v.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given static vector.
+// \ingroup static_vector
+//
+// \param v The vector to be cleared.
+// \return void
+//
+// Clearing a static vector is equivalent to resetting it via the reset() function.
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void clear( StaticVector<Type,N,TF>& v )
+{
+ v.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given static vector is in default state.
+// \ingroup static_vector
+//
+// \param v The vector to be tested for its default state.
+// \return \a true in case the given vector is component-wise zero, \a false otherwise.
+//
+// This function checks whether the static vector is in default state. For instance, in case
+// the static vector is instantiated for a built-in integral or floating point data type, the
+// function returns \a true in case all vector elements are 0 and \a false in case any vector
+// element is not 0. Following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::StaticVector<double,3> a;
+ // ... Initialization
+ if( isDefault( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline bool isDefault( const StaticVector<Type,N,TF>& v )
+{
+ for( size_t i=0UL; i<N; ++i )
+ if( !isDefault( v[i] ) ) return false;
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given static vector are intact.
+// \ingroup static_vector
+//
+// \param v The static vector to be tested.
+// \return \a true in case the given vector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the static vector are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::StaticVector<double,3> a;
+ // ... Resizing and initialization
+ if( isIntact( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline bool isIntact( const StaticVector<Type,N,TF>& v ) noexcept
+{
+ return v.isIntact();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unary perp dot product operator for the calculation of a perpendicular vector
+// (\f$ \vec{a}=\vec{b}^\perp \f$).
+//
+// \param v The vector to be rotated.
+// \return The perpendicular vector.
+//
+// The "perp dot product" \f$ \vec{a}^\perp \cdot b \f$ for the vectors \f$ \vec{a} \f$ and
+// \f$ \vec{b} \f$ is a modification of the two-dimensional dot product in which \f$ \vec{a} \f$
+// is replaced by the perpendicular vector rotated 90 degrees to the left defined by Hill (1994).
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline const StaticVector<Type,2UL,TF> perp( const StaticVector<Type,2UL,TF>& v )
+{
+ return StaticVector<Type,2UL,TF>( -v[1UL], v[0UL] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creates a perpendicular vector b which satisfies \f$ \vec{a} \cdot \vec{b} = 0 \f$.
+//
+// \param v The vector to be rotated.
+// \return The perpendicular vector.
+//
+// \note The perpendicular vector may have any length!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline const StaticVector<Type,3UL,TF> perp( const StaticVector<Type,3UL,TF>& v )
+{
+ if( v[0] != Type() || v[1] != Type() )
+ return StaticVector<Type,3UL,TF>( v[1UL], -v[0UL], Type() );
+ else
+ return StaticVector<Type,3UL,TF>( Type(), v[2UL], -v[1UL] );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two static vectors.
+// \ingroup static_vector
+//
+// \param a The first vector to be swapped.
+// \param b The second vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , size_t N // Number of elements
+ , bool TF > // Transpose flag
+inline void swap( StaticVector<Type,N,TF>& a, StaticVector<Type,N,TF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct Size< StaticVector<T,N,TF> >
+{
+ static const size_t value = N;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct HasConstDataAccess< StaticVector<T,N,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct HasMutableDataAccess< StaticVector<T,N,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct IsAligned< StaticVector<T,N,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, size_t N, bool TF >
+struct IsPadded< StaticVector<T,N,TF> > : public BoolConstant<usePadding>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct AddTrait< StaticVector<T1,N,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, N, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct SubTrait< StaticVector<T1,N,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, N, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MultTrait< StaticVector<T1,N,TF>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, typename T2, size_t N, bool TF >
+struct MultTrait< T1, StaticVector<T2,N,TF>, EnableIf_<IsNumeric<T1> > >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MultTrait< StaticVector<T1,N,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< MultTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t M, typename T2, size_t N >
+struct MultTrait< StaticVector<T1,M,false>, StaticVector<T2,N,true> >
+{
+ using Type = StaticMatrix< MultTrait_<T1,T2>, M, N, false >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< StaticVector<T1,N,true>, StaticVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CROSSTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, typename T2, bool TF >
+struct CrossTrait< StaticVector<T1,3UL,TF>, StaticVector<T2,3UL,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct DivTrait< StaticVector<T1,N,TF>, T2, EnableIf_<IsNumeric<T2> > >
+{
+ using Type = StaticVector< DivTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct DivTrait< StaticVector<T1,N,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< DivTrait_<T1,T2>, N, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MathTrait< StaticVector<T1,N,TF>, StaticVector<T2,N,TF> >
+{
+ using HighType = StaticVector< typename MathTrait<T1,T2>::HighType, N, TF >;
+ using LowType = StaticVector< typename MathTrait<T1,T2>::LowType , N, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, size_t N, bool TF >
+struct SubvectorTrait< StaticVector<T1,N,TF> >
+{
+ using Type = HybridVector<T1,N,TF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/AddExpr.h b/src/cpu/blaze/math/expressions/AddExpr.h
new file mode 100644
index 00000000..43b4de58
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/AddExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/AddExpr.h
+// \brief Header file for the AddExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_ADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_ADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all addition expression templates.
+// \ingroup math
+//
+// The AddExpr class serves as a tag for all expression templates that implement mathematical
+// additions. All classes, that represent a mathematical addition (vector additions and matrix
+// additions) and that are used within the expression template environment of the Blaze library
+// have to derive from this class in order to qualify as addition expression template. Only in
+// case a class is derived from the AddExpr base class, the IsAddExpr type trait recognizes the
+// class as valid addition expression template.
+*/
+struct AddExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/Computation.h b/src/cpu/blaze/math/expressions/Computation.h
new file mode 100644
index 00000000..f04f68fb
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/Computation.h
@@ -0,0 +1,65 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/Computation.h
+// \brief Header file for the Computation base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_COMPUTATION_H_
+#define _BLAZE_MATH_EXPRESSIONS_COMPUTATION_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all compute expression templates.
+// \ingroup math
+//
+// The Computation class serves as a tag for all computational expression templates. All
+// classes, that represent a mathematical computation (addition, subtraction, multiplication,
+// division, absolute value calculation, ...) and that are used within the expression template
+// environment of the Blaze library have to derive from this class in order to qualify as
+// computational expression template. Only in case a class is derived from the Computation base
+// class, the IsComputation type trait recognizes the class as valid computational expression
+// template.
+*/
+struct Computation
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/CrossExpr.h b/src/cpu/blaze/math/expressions/CrossExpr.h
new file mode 100644
index 00000000..84e886c3
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/CrossExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/CrossExpr.h
+// \brief Header file for the CrossExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_CROSSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_CROSSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all cross product expression templates.
+// \ingroup math
+//
+// The CrossExpr class serves as a tag for all expression templates that implement mathematical
+// cross products. All classes, that represent a mathematical cross product and that are used
+// within the expression template environment of the Blaze library have to derive from this class
+// in order to qualify as cross product expression template. Only in case a class is derived from
+// the CrossExpr base class, the IsCrossExpr type trait recognizes the class as valid cross
+// product expression template.
+*/
+struct CrossExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatDMatAddExpr.h b/src/cpu/blaze/math/expressions/DMatDMatAddExpr.h
new file mode 100644
index 00000000..35d0354a
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatDMatAddExpr.h
@@ -0,0 +1,1276 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatDMatAddExpr.h
+// \brief Header file for the dense matrix/dense matrix addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATDMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATDMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATDMATADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-dense matrix additions.
+// \ingroup dense_matrix_expression
+//
+// The DMatDMatAddExpr class represents the compile time expression for additions between
+// dense matrices with identical storage order.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+class DMatDMatAddExpr : public DenseMatrix< DMatDMatAddExpr<MT1,MT2,SO>, SO >
+ , private MatMatAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ typedef ElementType_<MT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<MT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the addition expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the addition expression. In case either of the two
+ dense matrix operands requires an intermediate evaluation or the subscript operator
+ can only return by value, \a useAssign will be set to 1 and the addition expression
+ will be evaluated via the \a assign function family. Otherwise \a useAssign will be
+ set to 0 and the expression will be evaluated via the function call operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT1>::value || RequiresEvaluation<MT2>::value || !returnExpr };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable and at
+ least one of the two operands requires an intermediate evaluation, \a value is set to 1
+ and the expression specific evaluation strategy is selected. Otherwise \a value is set
+ to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatDMatAddExpr<MT1,MT2,SO> This; //!< Type of this DMatDMatAdd instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DMatDMatAddExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense matrix.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the left-hand side dense matrix expression.
+ typedef ConstIterator_<MT1> LeftIteratorType;
+
+ //! ConstIterator type of the right-hand side dense matrix expression.
+ typedef ConstIterator_<MT2> RightIteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param left Iterator to the initial left-hand side element.
+ // \param right Iterator to the initial right-hand side element.
+ */
+ explicit inline ConstIterator( LeftIteratorType left, RightIteratorType right )
+ : left_ ( left ) // Iterator to the current left-hand side element
+ , right_( right ) // Iterator to the current right-hand side element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ left_ += inc;
+ right_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ left_ -= dec;
+ right_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++left_;
+ ++right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( left_++, right_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --left_;
+ --right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( left_--, right_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return (*left_) + (*right_);
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return left_.load() + right_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return left_ == rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return left_ != rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return left_ < rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return left_ > rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return left_ <= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return left_ >= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return left_ - rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.left_ - dec, it.right_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftIteratorType left_; //!< Iterator to the current left-hand side element.
+ RightIteratorType right_; //!< Iterator to the current right-hand side element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT1::simdEnabled && MT2::simdEnabled &&
+ HasSIMDAdd<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT1::smpAssignable && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatDMatAddExpr class.
+ //
+ // \param lhs The left-hand side operand of the addition expression.
+ // \param rhs The right-hand side operand of the addition expression.
+ */
+ explicit inline DMatDMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the addition expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) + rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t i, size_t j ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !SO || ( i % SIMDSIZE == 0UL ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( SO || ( j % SIMDSIZE == 0UL ), "Invalid column access index" );
+ return lhs_.load(i,j) + rhs_.load(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( lhs_.begin(i), rhs_.begin(i) );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( lhs_.end(i), rhs_.end(i) );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && ( RequiresEvaluation<MT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
+ ( IsExpression<MT2>::value && ( RequiresEvaluation<MT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
+ ( ( ( SO == rowMajor ) ? rows() : columns() ) > SMP_DMATDMATADD_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the addition expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-dense
+ // matrix addition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,SO2>& lhs, const DMatDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( !IsExpression<MT2>::value && isSame( ~lhs, rhs.rhs_ ) ) {
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-dense matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-dense
+ // matrix addition expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( SparseMatrix<MT,SO2>& lhs, const DMatDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // dense matrix addition expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // dense matrix addition expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-dense
+ // matrix addition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( !IsExpression<MT2>::value && isSame( ~lhs, rhs.rhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-dense matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-dense
+ // matrix addition expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-dense matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance SMP optimized subtraction assignment of a dense
+ // matrix-dense matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT1, MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of two dense matrices with identical storage order
+// (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the addition of two dense matrices with identical storage order:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+inline const DMatDMatAddExpr<T1,T2,SO>
+ operator+( const DenseMatrix<T1,SO>& lhs, const DenseMatrix<T2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatDMatAddExpr<T1,T2,SO>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Rows< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Columns< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsAligned< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsAligned<MT1>, IsAligned<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsPadded< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsPadded<MT1>, IsPadded<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsSymmetric< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsHermitian< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsLower< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniLower< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< Or< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >
+ , And< IsUniLower<MT2>, IsStrictlyLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyLower< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUpper< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniUpper< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< Or< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >
+ , And< IsUniUpper<MT2>, IsStrictlyUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyUpper< DMatDMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatDMatAddExpr<MT1,MT2,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct RowExprTrait< DMatDMatAddExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct ColumnExprTrait< DMatDMatAddExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatDMatMultExpr.h b/src/cpu/blaze/math/expressions/DMatDMatMultExpr.h
new file mode 100644
index 00000000..5b31cc61
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatDMatMultExpr.h
@@ -0,0 +1,8100 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatDMatMultExpr.h
+// \brief Header file for the dense matrix/dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/gemm.h>
+#include <blaze/math/blas/trmm.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/expressions/MatScalarMultExpr.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDMatMultExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The DMatDMatMultExpr class represents the compile time expression for multiplications between
+// row-major dense matrices.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class DMatDMatMultExpr : public DenseMatrix< DMatDMatMultExpr<MT1,MT2>, false >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the target matrix is column-major and either of the
+ two matrix operands is symmetric, \a value is set to 1 and an optimized evaluation
+ strategy is selected. Otherwise \a value is set to 0 and the default strategy is
+ chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsColumnMajorMatrix<T1>::value &&
+ ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the types of all three involved matrices are suited for a BLAS kernel, the nested
+ \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatDMatMultExpr<MT1,MT2> This; //!< Type of this DMatDMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT2>::value &&
+ MT1::simdEnabled && MT2::simdEnabled &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatDMatMultExpr class.
+ //
+ // \param lhs The left-hand side operand of the multiplication expression.
+ // \param rhs The right-hand side operand of the multiplication expression.
+ */
+ explicit inline DMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( rows() * columns() < DMATDMATMULT_THRESHOLD ) ) &&
+ ( rows() > SMP_DMATDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-dense matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-dense
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( rhs.lhs_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a dense matrix-dense matrix
+ // multiplication to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( C, A, B );
+ else
+ selectBlasAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (general/general)**************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general dense matrix-general dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general dense matrix-general dense
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ if( IsStrictlyTriangular<MT4>::value && kbegin == kend ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ continue;
+ }
+
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? kbegin+1UL : kbegin )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? kbegin : kbegin+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT4>::value && IsUpper<MT5>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ else if( IsStrictlyUpper<MT5>::value ) {
+ reset( C(i,0UL) );
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) = A(i,kbegin) * B(kbegin,j);
+ }
+ if( IsLower<MT4>::value && IsLower<MT5>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ else if( IsStrictlyLower<MT5>::value ) {
+ reset( C(i,N-1UL) );
+ }
+ }
+
+ for( size_t k=kbegin+1UL; k<kend; ++k )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? k-1UL : k )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) += A(i,k) * B(k,j);
+ }
+ if( IsLower<MT5>::value ) {
+ C(i,jend) = A(i,k) * B(k,jend);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (general/diagonal)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general dense matrix-diagonal dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general dense matrix-diagonal dense
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT4>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) = A(i,j) * B(j,j);
+ }
+ if( IsLower<MT4>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/general)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal dense matrix-general dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal dense matrix-general dense
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT5>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) = A(i,i) * B(i,j);
+ }
+ if( IsLower<MT5>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/diagonal)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal dense matrix-diagonal dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal dense matrix-diagonal dense
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) = A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small dense matrix-dense matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (small matrices)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small dense matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a dense matrix-dense matrix
+ // multiplication expression to a row-major dense matrix. This kernel is optimized for small
+ // matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i, j+SIMDSIZE*4UL, xmm5 );
+ (~C).store( i, j+SIMDSIZE*5UL, xmm6 );
+ (~C).store( i, j+SIMDSIZE*6UL, xmm7 );
+ (~C).store( i, j+SIMDSIZE*7UL, xmm8 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE , xmm2 );
+ (~C).store( i , j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i , j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j+SIMDSIZE , xmm6 );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, xmm7 );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, xmm8 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j+SIMDSIZE, xmm4 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+1UL, j, xmm2 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) = value1;
+ (~C)(i+1UL,j) = value2;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (small matrices)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small dense matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a dense matrix-dense matrix
+ // multiplication expression to a column-major dense matrix. This kernel is optimized for small
+ // matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( ~C, tmp * B );
+ }
+ else if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( ~C, A * tmp );
+ }
+ else if( A.rows() * A.columns() <= B.rows() * B.columns() ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( ~C, tmp * B );
+ }
+ else {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( ~C, A * tmp );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large dense matrix-dense matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (large matrices)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large dense matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a dense matrix-dense matrix
+ // multiplication expression to a row-major dense matrix. This kernel is optimized for large
+ // matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_IBLOCK_SIZE, M ) );
+
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i ,j2) );
+ SIMDType xmm4( (~C).load(i ,j3) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j1) );
+ SIMDType xmm7( (~C).load(i+1UL,j2) );
+ SIMDType xmm8( (~C).load(i+1UL,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i , j2, xmm3 );
+ (~C).store( i , j3, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j1, xmm6 );
+ (~C).store( i+1UL, j2, xmm7 );
+ (~C).store( i+1UL, j3, xmm8 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+ SIMDType xmm3( (~C).load(i,j2) );
+ SIMDType xmm4( (~C).load(i,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ (~C).store( i, j2, xmm3 );
+ (~C).store( i, j3, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+ SIMDType xmm5( (~C).load(i+2UL,j ) );
+ SIMDType xmm6( (~C).load(i+2UL,j1) );
+ SIMDType xmm7( (~C).load(i+3UL,j ) );
+ SIMDType xmm8( (~C).load(i+3UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ (~C).store( i+2UL, j , xmm5 );
+ (~C).store( i+2UL, j1, xmm6 );
+ (~C).store( i+3UL, j , xmm7 );
+ (~C).store( i+3UL, j1, xmm8 );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (large matrices)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large dense matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a small dense
+ // matrix-dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ selectSmallAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices (default)*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense matrix-dense matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices*****************************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based assignment of a dense matrix-dense matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the dense matrix-dense matrix multiplication based on the according
+ // BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ assign( C, B );
+ trmm( C, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ assign( C, A );
+ trmm( C, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ }
+ else {
+ gemm( C, A, B, ET(1), ET(0) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-dense matrix multiplication to a sparse matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-dense
+ // matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to column-major matrices*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a dense matrix-dense matrix multiplication to a
+ // column-major matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a dense matrix-
+ // dense matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,true>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-dense matrix multiplication to a dense matrix
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a dense matrix-dense matrix
+ // multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( C, A, B );
+ else
+ selectBlasAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/general)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general dense matrix-general dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general dense matrix-general
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ for( size_t k=kbegin; k<kend; ++k )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? k : k+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) += A(i,k) * B(k,j );
+ C(i,j+1UL) += A(i,k) * B(k,j+1UL);
+ }
+ if( jpos < jend ) {
+ C(i,jpos) += A(i,k) * B(k,jpos);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/diagonal)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general dense matrix-diagonal dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general dense matrix-diagonal
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) += A(i,j ) * B(j ,j );
+ C(i,j+1UL) += A(i,j+1UL) * B(j+1UL,j+1UL);
+ }
+ if( jpos < jend ) {
+ C(i,jpos) += A(i,jpos) * B(jpos,jpos);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/general)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal dense matrix-general dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal dense matrix-general
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) += A(i,i) * B(i,j );
+ C(i,j+1UL) += A(i,i) * B(i,j+1UL);
+ }
+ if( jpos < jend ) {
+ C(i,jpos) += A(i,i) * B(i,jpos);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/diagonal)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal dense matrix-diagonal dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal dense matrix-diagonal
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) += A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small dense matrix-dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (small matrices)*********
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a dense matrix-dense
+ // matrix multiplication expression to a row-major dense matrix. This kernel is optimized for
+ // small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i,j+SIMDSIZE*3UL) );
+ SIMDType xmm5( (~C).load(i,j+SIMDSIZE*4UL) );
+ SIMDType xmm6( (~C).load(i,j+SIMDSIZE*5UL) );
+ SIMDType xmm7( (~C).load(i,j+SIMDSIZE*6UL) );
+ SIMDType xmm8( (~C).load(i,j+SIMDSIZE*7UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i, j+SIMDSIZE*4UL, xmm5 );
+ (~C).store( i, j+SIMDSIZE*5UL, xmm6 );
+ (~C).store( i, j+SIMDSIZE*6UL, xmm7 );
+ (~C).store( i, j+SIMDSIZE*7UL, xmm8 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i ,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i ,j+SIMDSIZE*3UL) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j+SIMDSIZE ) );
+ SIMDType xmm7( (~C).load(i+1UL,j+SIMDSIZE*2UL) );
+ SIMDType xmm8( (~C).load(i+1UL,j+SIMDSIZE*3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE , xmm2 );
+ (~C).store( i , j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i , j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j+SIMDSIZE , xmm6 );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, xmm7 );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, xmm8 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i,j+SIMDSIZE*3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j+SIMDSIZE) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j+SIMDSIZE) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j+SIMDSIZE, xmm4 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+1UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+1UL, j, xmm2 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1( (~C)(i ,j) );
+ ElementType value2( (~C)(i+1UL,j) );;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) = value1;
+ (~C)(i+1UL,j) = value2;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (small matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a small dense
+ // matrix-dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( ~C, tmp * B );
+ }
+ else if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( ~C, A * tmp );
+ }
+ else if( A.rows() * A.columns() <= B.rows() * B.columns() ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( ~C, tmp * B );
+ }
+ else {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( ~C, A * tmp );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large dense matrix-dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (large matrices)*********
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a dense matrix-dense
+ // matrix multiplication expression to a row-major dense matrix. This kernel is optimized for
+ // large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_IBLOCK_SIZE, M ) );
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i ,j2) );
+ SIMDType xmm4( (~C).load(i ,j3) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j1) );
+ SIMDType xmm7( (~C).load(i+1UL,j2) );
+ SIMDType xmm8( (~C).load(i+1UL,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i , j2, xmm3 );
+ (~C).store( i , j3, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j1, xmm6 );
+ (~C).store( i+1UL, j2, xmm7 );
+ (~C).store( i+1UL, j3, xmm8 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+ SIMDType xmm3( (~C).load(i,j2) );
+ SIMDType xmm4( (~C).load(i,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ (~C).store( i, j2, xmm3 );
+ (~C).store( i, j3, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+ SIMDType xmm5( (~C).load(i+2UL,j ) );
+ SIMDType xmm6( (~C).load(i+2UL,j1) );
+ SIMDType xmm7( (~C).load(i+3UL,j ) );
+ SIMDType xmm8( (~C).load(i+3UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ (~C).store( i+2UL, j , xmm5 );
+ (~C).store( i+2UL, j1, xmm6 );
+ (~C).store( i+3UL, j , xmm7 );
+ (~C).store( i+3UL, j1, xmm8 );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (large matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a small
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ selectSmallAddAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices (default)**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a dense matrix-dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices********************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based addition assignment of a dense matrix-dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the dense matrix-dense matrix multiplication based on the according
+ // BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ addAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ addAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to column-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a dense matrix-dense matrix multiplication to a
+ // column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a dense
+ // matrix-dense matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,true>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a dense matrix-dense matrix
+ // multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( C, A, B );
+ else
+ selectBlasSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/general)**************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general dense matrix-general dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general dense matrix-
+ // general dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ for( size_t k=kbegin; k<kend; ++k )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? k : k+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) -= A(i,k) * B(k,j );
+ C(i,j+1UL) -= A(i,k) * B(k,j+1UL);
+ }
+ if( jpos < jend ) {
+ C(i,jpos) -= A(i,k) * B(k,jpos);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/diagonal)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general dense matrix-diagonal dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general dense matrix-
+ // diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) -= A(i,j ) * B(j ,j );
+ C(i,j+1UL) -= A(i,j+1UL) * B(j+1UL,j+1UL);
+ }
+ if( jpos < jend ) {
+ C(i,jpos) -= A(i,jpos) * B(jpos,jpos);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/general)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal dense matrix-general dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal dense matrix-
+ // general dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) -= A(i,i) * B(i,j );
+ C(i,j+1UL) -= A(i,i) * B(i,j+1UL);
+ }
+ if( jpos < jend ) {
+ C(i,jpos) -= A(i,i) * B(i,jpos);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/diagonal)************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal dense matrix-diagonal dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal dense matrix-
+ // diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) -= A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small dense matrix-dense matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (small matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small dense matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a dense matrix-
+ // dense matrix multiplication expression to a row-major dense matrix. This kernel is optimized
+ // for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i,j+SIMDSIZE*3UL) );
+ SIMDType xmm5( (~C).load(i,j+SIMDSIZE*4UL) );
+ SIMDType xmm6( (~C).load(i,j+SIMDSIZE*5UL) );
+ SIMDType xmm7( (~C).load(i,j+SIMDSIZE*6UL) );
+ SIMDType xmm8( (~C).load(i,j+SIMDSIZE*7UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 - a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 - a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 - a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 - a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 - a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 - a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i, j+SIMDSIZE*4UL, xmm5 );
+ (~C).store( i, j+SIMDSIZE*5UL, xmm6 );
+ (~C).store( i, j+SIMDSIZE*6UL, xmm7 );
+ (~C).store( i, j+SIMDSIZE*7UL, xmm8 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i ,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i ,j+SIMDSIZE*3UL) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j+SIMDSIZE ) );
+ SIMDType xmm7( (~C).load(i+1UL,j+SIMDSIZE*2UL) );
+ SIMDType xmm8( (~C).load(i+1UL,j+SIMDSIZE*3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a1 * b3;
+ xmm4 = xmm4 - a1 * b4;
+ xmm5 = xmm5 - a2 * b1;
+ xmm6 = xmm6 - a2 * b2;
+ xmm7 = xmm7 - a2 * b3;
+ xmm8 = xmm8 - a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE , xmm2 );
+ (~C).store( i , j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i , j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j+SIMDSIZE , xmm6 );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, xmm7 );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, xmm8 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i,j+SIMDSIZE*3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 - a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 - a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j+SIMDSIZE) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j+SIMDSIZE) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a2 * b1;
+ xmm4 = xmm4 - a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j+SIMDSIZE, xmm4 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+1UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 - set( A(i ,k) ) * b1;
+ xmm2 = xmm2 - set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+1UL, j, xmm2 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 - set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1( (~C)(i ,j) );
+ ElementType value2( (~C)(i+1UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 -= A(i ,k) * B(k,j);
+ value2 -= A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) = value1;
+ (~C)(i+1UL,j) = value2;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value -= A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (small matrices)***
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small dense matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a dense matrix-
+ // dense matrix multiplication expression to a column-major dense matrix. This kernel is
+ // optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( ~C, tmp * B );
+ }
+ else if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( ~C, A * tmp );
+ }
+ else if( A.rows() * A.columns() <= B.rows() * B.columns() ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( ~C, tmp * B );
+ }
+ else {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( ~C, A * tmp );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large dense matrix-dense matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (large matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large dense matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a dense matrix-
+ // dense matrix multiplication expression to a row-major dense matrix. This kernel is optimized
+ // for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_IBLOCK_SIZE, M ) );
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i ,j2) );
+ SIMDType xmm4( (~C).load(i ,j3) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j1) );
+ SIMDType xmm7( (~C).load(i+1UL,j2) );
+ SIMDType xmm8( (~C).load(i+1UL,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a1 * b3;
+ xmm4 = xmm4 - a1 * b4;
+ xmm5 = xmm5 - a2 * b1;
+ xmm6 = xmm6 - a2 * b2;
+ xmm7 = xmm7 - a2 * b3;
+ xmm8 = xmm8 - a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i , j2, xmm3 );
+ (~C).store( i , j3, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j1, xmm6 );
+ (~C).store( i+1UL, j2, xmm7 );
+ (~C).store( i+1UL, j3, xmm8 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+ SIMDType xmm3( (~C).load(i,j2) );
+ SIMDType xmm4( (~C).load(i,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j1);
+ xmm3 = xmm3 - a1 * B.load(k,j2);
+ xmm4 = xmm4 - a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ (~C).store( i, j2, xmm3 );
+ (~C).store( i, j3, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+ SIMDType xmm5( (~C).load(i+2UL,j ) );
+ SIMDType xmm6( (~C).load(i+2UL,j1) );
+ SIMDType xmm7( (~C).load(i+3UL,j ) );
+ SIMDType xmm8( (~C).load(i+3UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a2 * b1;
+ xmm4 = xmm4 - a2 * b2;
+ xmm5 = xmm5 - a3 * b1;
+ xmm6 = xmm6 - a3 * b2;
+ xmm7 = xmm7 - a4 * b1;
+ xmm8 = xmm8 - a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ (~C).store( i+2UL, j , xmm5 );
+ (~C).store( i+2UL, j1, xmm6 );
+ (~C).store( i+3UL, j , xmm7 );
+ (~C).store( i+3UL, j1, xmm8 );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a2 * b1;
+ xmm4 = xmm4 - a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value -= A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (large matrices)***
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large dense matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a small
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ selectSmallSubAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense matrices (default)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a dense matrix-dense matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subraction assignment to dense matrices******************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based subraction assignment of a dense matrix-dense matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the dense matrix-dense matrix multiplication based on the according
+ // BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ subAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ subAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(-1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to column-major matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a dense matrix-dense matrix multiplication
+ // to a column-major matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a dense
+ // matrix-dense matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,true>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-dense matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-dense
+ // matrix multiplication expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( rhs.lhs_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-dense matrix multiplication to a sparse matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-dense
+ // matrix multiplication expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to column-major matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a dense matrix-dense matrix multiplication to a
+ // column-major matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a dense matrix-
+ // dense matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,true>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-dense matrix multiplication to a dense
+ // matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to column-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a dense matrix-dense matrix multiplication
+ // to a column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a dense
+ // matrix-dense matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,true>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to column-major matrices***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a dense matrix-dense matrix multiplication
+ // to a column-major matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // dense matrix-dense matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,true>& lhs, const DMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSCALARMULTEXPR SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Expression object for scaled dense matrix-dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// This specialization of the DMatScalarMultExpr class represents the compile time expression
+// for scaled multiplications between row-major dense matrices.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar value
+class DMatScalarMultExpr< DMatDMatMultExpr<MT1,MT2>, ST, false >
+ : public DenseMatrix< DMatScalarMultExpr< DMatDMatMultExpr<MT1,MT2>, ST, false >, false >
+ , private MatScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef DMatDMatMultExpr<MT1,MT2> MMM; //!< Type of the dense matrix multiplication expression.
+ typedef ResultType_<MMM> RES; //!< Result type of the dense matrix multiplication expression.
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the target matrix is column-major and either of the
+ two matrix operands is symmetric, \a value is set to 1 and an optimized evaluation
+ strategy is selected. Otherwise \a value is set to 0 and the default strategy is
+ chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsColumnMajorMatrix<T1>::value &&
+ ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the types of all three involved matrices and the scalar type are suited for a BLAS
+ kernel, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ !( IsBuiltin< ElementType_<T1> >::value && IsComplex<T4>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all four involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3>
+ , T4 >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatScalarMultExpr<MMM,ST,false> This; //!< Type of this DMatScalarMultExpr instance.
+ typedef MultTrait_<RES,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef const DMatDMatMultExpr<MT1,MT2> LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT2>::value &&
+ MT1::simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable<ET1,ET2,ST>::value &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatScalarMultExpr class.
+ //
+ // \param matrix The left-hand side dense matrix of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DMatScalarMultExpr( const MMM& matrix, ST scalar )
+ : matrix_( matrix ) // Left-hand side dense matrix of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ return matrix_(i,j) * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= matrix_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= matrix_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const {
+ return matrix_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const {
+ return matrix_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return matrix_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const {
+ return matrix_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return matrix_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const {
+ return matrix_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const {
+ LeftOperand_<MMM> A( matrix_.leftOperand() );
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( rows() * columns() < DMATDMATMULT_THRESHOLD ) ) &&
+ ( A.rows() > SMP_DMATDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand matrix_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*!\brief Assignment of a scaled dense matrix-dense matrix multiplication to a dense matrix
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*!\brief Selection of the kernel for an assignment of a scaled dense matrix-dense matrix
+ // multiplication to a dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( C, A, B, scalar );
+ else
+ selectBlasAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (general/general)**************************************
+ /*!\brief Default assignment of a scaled general dense matrix-general dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general dense matrix-general
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ if( IsStrictlyTriangular<MT4>::value && kbegin == kend ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ continue;
+ }
+
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? kbegin+1UL : kbegin )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? kbegin : kbegin+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT4>::value && IsUpper<MT5>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ else if( IsStrictlyUpper<MT5>::value ) {
+ reset( C(i,0UL) );
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) = A(i,kbegin) * B(kbegin,j);
+ }
+ if( IsLower<MT4>::value && IsLower<MT5>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ else if( IsStrictlyLower<MT5>::value ) {
+ reset( C(i,N-1UL) );
+ }
+ }
+
+ for( size_t k=kbegin+1UL; k<kend; ++k )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? k-1UL : k )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) += A(i,k) * B(k,j);
+ }
+ if( IsLower<MT5>::value ) {
+ C(i,jend) = A(i,k) * B(k,jend);
+ }
+ }
+
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT4>::value || IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT4>::value || IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) *= scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (general/diagonal)*************************************
+ /*!\brief Default assignment of a scaled general dense matrix-diagonal dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general dense matrix-diagonal
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT4>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) = A(i,j) * B(j,j) * scalar;
+ }
+ if( IsLower<MT4>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/general)*************************************
+ /*!\brief Default assignment of a scaled diagonal dense matrix-general dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal dense matrix-general
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT5>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i,j) = A(i,i) * B(i,j) * scalar;
+ }
+ if( IsLower<MT5>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/diagonal)************************************
+ /*!\brief Default assignment of a scaled diagonal dense matrix-diagonal dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal dense matrix-diagional
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) = A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*!\brief Default assignment of a small scaled dense matrix-dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (small matrices)******************
+ /*!\brief Vectorized default assignment of a small scaled dense matrix-dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled dense matrix-dense
+ // matrix multiplication expression to a row-major dense matrix. This kernel is optimized for
+ // small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 * factor );
+ (~C).store( i, j+SIMDSIZE*4UL, xmm5 * factor );
+ (~C).store( i, j+SIMDSIZE*5UL, xmm6 * factor );
+ (~C).store( i, j+SIMDSIZE*6UL, xmm7 * factor );
+ (~C).store( i, j+SIMDSIZE*7UL, xmm8 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE , xmm2 * factor );
+ (~C).store( i , j+SIMDSIZE*2UL, xmm3 * factor );
+ (~C).store( i , j+SIMDSIZE*3UL, xmm4 * factor );
+ (~C).store( i+1UL, j , xmm5 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE , xmm6 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, xmm7 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, xmm8 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE, xmm2 * factor );
+ (~C).store( i+1UL, j , xmm3 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE, xmm4 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE, xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, xmm1 * factor );
+ (~C).store( i+1UL, j, xmm2 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) = value1 * scalar;
+ (~C)(i+1UL,j) = value2 * scalar;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (small matrices)***************
+ /*!\brief Vectorized default assignment of a small scaled dense matrix-dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a small scaled dense matrix-
+ // dense matrix multiplication expression to a column-major dense matrix. This kernel is
+ // optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( ~C, tmp * B * scalar );
+ }
+ else if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( ~C, A * tmp * scalar );
+ }
+ else if( A.rows() * A.columns() <= B.rows() * B.columns() ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( ~C, tmp * B * scalar );
+ }
+ else {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( ~C, A * tmp * scalar );
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*!\brief Default assignment of a large scaled dense matrix-dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (large matrices)******************
+ /*!\brief Vectorized default assignment of a large scaled dense matrix-dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled dense matrix-dense
+ // matrix multiplication expression to a row-major dense matrix. This kernel is optimized for
+ // large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_IBLOCK_SIZE, M ) );
+
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i , j2, (~C).load(i ,j2) + xmm3 * factor );
+ (~C).store( i , j3, (~C).load(i ,j3) + xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm5 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm6 * factor );
+ (~C).store( i+1UL, j2, (~C).load(i+1UL,j2) + xmm7 * factor );
+ (~C).store( i+1UL, j3, (~C).load(i+1UL,j3) + xmm8 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) + xmm2 * factor );
+ (~C).store( i, j2, (~C).load(i,j2) + xmm3 * factor );
+ (~C).store( i, j3, (~C).load(i,j3) + xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm4 * factor );
+ (~C).store( i+2UL, j , (~C).load(i+2UL,j ) + xmm5 * factor );
+ (~C).store( i+2UL, j1, (~C).load(i+2UL,j1) + xmm6 * factor );
+ (~C).store( i+3UL, j , (~C).load(i+3UL,j ) + xmm7 * factor );
+ (~C).store( i+3UL, j1, (~C).load(i+3UL,j1) + xmm8 * factor );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm4 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) + xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (large matrices)***************
+ /*!\brief Vectorized default assignment of a large scaled dense matrix-dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a small scaled
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectSmallAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices (default)*******************************************
+ /*!\brief Default assignment of a scaled dense matrix-dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large scaled
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices*****************************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based assignment of a scaled dense matrix-dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ assign( C, B );
+ trmm( C, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ assign( C, A );
+ trmm( C, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ }
+ else {
+ gemm( C, A, B, ET(scalar), ET(0) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*!\brief Assignment of a scaled dense matrix-dense matrix multiplication to a sparse matrix
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled dense matrix-
+ // dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Restructuring assignment to column-major matrices*******************************************
+ /*!\brief Restructuring assignment of a scaled dense matrix-dense matrix multiplication to a
+ // column-major matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,true>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ assign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ assign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ assign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*!\brief Addition assignment of a scaled dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectAddAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*!\brief Selection of the kernel for an addition assignment of a scaled dense matrix-dense
+ // matrix multiplication to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( C, A, B, scalar );
+ else
+ selectBlasAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/general)*****************************
+ /*!\brief Default addition assignment of a scaled general dense matrix-general dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled dense matrix-dense
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const ResultType tmp( serial( A * B * scalar ) );
+ addAssign( C, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/diagonal)****************************
+ /*!\brief Default addition assignment of a scaled general dense matrix-diagonal dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general dense matrix-
+ // diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) += A(i,j ) * B(j ,j ) * scalar;
+ C(i,j+1UL) += A(i,j+1UL) * B(j+1UL,j+1UL) * scalar;
+ }
+ if( jpos < jend ) {
+ C(i,jpos) += A(i,jpos) * B(jpos,jpos) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/general)****************************
+ /*!\brief Default addition assignment of a scaled diagonal dense matrix-general dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal dense matrix-
+ // general dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) += A(i,i) * B(i,j ) * scalar;
+ C(i,j+1UL) += A(i,i) * B(i,j+1UL) * scalar;
+ }
+ if( jpos < jend ) {
+ C(i,jpos) += A(i,i) * B(i,jpos) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/diagonal)***************************
+ /*!\brief Default addition assignment of a scaled diagonal dense matrix-diagonal dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal dense matrix-
+ // diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) += A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*!\brief Default addition assignment of a small scaled dense matrix-dense matrix multiplication
+ // (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (small matrices)*********
+ /*!\brief Vectorized default addition assignment of a small scaled dense matrix-dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , (~C).load(i,j+SIMDSIZE ) + xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, (~C).load(i,j+SIMDSIZE*2UL) + xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, (~C).load(i,j+SIMDSIZE*3UL) + xmm4 * factor );
+ (~C).store( i, j+SIMDSIZE*4UL, (~C).load(i,j+SIMDSIZE*4UL) + xmm5 * factor );
+ (~C).store( i, j+SIMDSIZE*5UL, (~C).load(i,j+SIMDSIZE*5UL) + xmm6 * factor );
+ (~C).store( i, j+SIMDSIZE*6UL, (~C).load(i,j+SIMDSIZE*6UL) + xmm7 * factor );
+ (~C).store( i, j+SIMDSIZE*7UL, (~C).load(i,j+SIMDSIZE*7UL) + xmm8 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE , (~C).load(i ,j+SIMDSIZE ) + xmm2 * factor );
+ (~C).store( i , j+SIMDSIZE*2UL, (~C).load(i ,j+SIMDSIZE*2UL) + xmm3 * factor );
+ (~C).store( i , j+SIMDSIZE*3UL, (~C).load(i ,j+SIMDSIZE*3UL) + xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm5 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE , (~C).load(i+1UL,j+SIMDSIZE ) + xmm6 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, (~C).load(i+1UL,j+SIMDSIZE*2UL) + xmm7 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, (~C).load(i+1UL,j+SIMDSIZE*3UL) + xmm8 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , (~C).load(i,j+SIMDSIZE ) + xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, (~C).load(i,j+SIMDSIZE*2UL) + xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, (~C).load(i,j+SIMDSIZE*3UL) + xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE, (~C).load(i ,j+SIMDSIZE) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE, (~C).load(i+1UL,j+SIMDSIZE) + xmm4 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE, (~C).load(i,j+SIMDSIZE) + xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i+1UL, j, (~C).load(i+1UL,j) + xmm2 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) += value1 * scalar;
+ (~C)(i+1UL,j) += value2 * scalar;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (small matrices)******
+ /*!\brief Vectorized default addition assignment of a small scaled dense matrix-dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( ~C, tmp * B * scalar );
+ }
+ else if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( ~C, A * tmp * scalar );
+ }
+ else if( A.rows() * A.columns() <= B.rows() * B.columns() ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( ~C, tmp * B * scalar );
+ }
+ else {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( ~C, A * tmp * scalar );
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*!\brief Default addition assignment of a large scaled dense matrix-dense matrix multiplication
+ // (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (large matrices)*********
+ /*!\brief Vectorized default addition assignment of a large scaled dense matrix-dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_IBLOCK_SIZE, M ) );
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i , j2, (~C).load(i ,j2) + xmm3 * factor );
+ (~C).store( i , j3, (~C).load(i ,j3) + xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm5 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm6 * factor );
+ (~C).store( i+1UL, j2, (~C).load(i+1UL,j2) + xmm7 * factor );
+ (~C).store( i+1UL, j3, (~C).load(i+1UL,j3) + xmm8 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) + xmm2 * factor );
+ (~C).store( i, j2, (~C).load(i,j2) + xmm3 * factor );
+ (~C).store( i, j3, (~C).load(i,j3) + xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm4 * factor );
+ (~C).store( i+2UL, j , (~C).load(i+2UL,j ) + xmm5 * factor );
+ (~C).store( i+2UL, j1, (~C).load(i+2UL,j1) + xmm6 * factor );
+ (~C).store( i+3UL, j , (~C).load(i+3UL,j ) + xmm7 * factor );
+ (~C).store( i+3UL, j1, (~C).load(i+3UL,j1) + xmm8 * factor );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm4 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) + xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (large matrices)******
+ /*!\brief Vectorized default addition assignment of a large scaled dense matrix-dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a small
+ // scaled dense matrix-dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectSmallAddAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices (default)**********************************
+ /*!\brief Default addition assignment of a scaled dense matrix-dense matrix multiplication
+ // (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // scaled dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices********************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based addition assignment of a scaled dense matrix-dense matrix multiplication
+ // (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ addAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ addAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to column-major matrices**********************************
+ /*!\brief Restructuring addition assignment of a scaled dense matrix-dense matrix multiplication
+ // to a column-major matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a scaled
+ // dense matrix-dense matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,true>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ addAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ addAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ addAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*!\brief Subtraction assignment of a scaled dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectSubAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*!\brief Selection of the kernel for a subtraction assignment of a scaled dense matrix-dense
+ // matrix multiplication to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( C, A, B, scalar );
+ else
+ selectBlasSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/general)**************************
+ /*!\brief Default subtraction assignment of a scaled general dense matrix-general dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general dense
+ // matrix-general dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const ResultType tmp( serial( A * B * scalar ) );
+ subAssign( C, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/diagonal)*************************
+ /*!\brief Default subtraction assignment of a scaled general dense matrix-diagonal dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general dense
+ // matrix-diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) -= A(i,j ) * B(j ,j ) * scalar;
+ C(i,j+1UL) -= A(i,j+1UL) * B(j+1UL,j+1UL) * scalar;
+ }
+ if( jpos < jend ) {
+ C(i,jpos) -= A(i,jpos) * B(jpos,jpos) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/general)*************************
+ /*!\brief Default subtraction assignment of a scaled diagonal dense matrix-general dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal dense
+ // matrix-general dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ C(i,j ) -= A(i,i) * B(i,j ) * scalar;
+ C(i,j+1UL) -= A(i,i) * B(i,j+1UL) * scalar;
+ }
+ if( jpos < jend ) {
+ C(i,jpos) -= A(i,i) * B(i,jpos) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/diagonal)************************
+ /*!\brief Default subtraction assignment of a scaled diagonal dense matrix-diagonal dense
+ // matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal dense
+ // matrix-diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) -= A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*!\brief Default subtraction assignment of a small scaled dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (small matrices)******
+ /*!\brief Vectorized default subtraction assignment of a small scaled dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel is
+ // optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , (~C).load(i,j+SIMDSIZE ) - xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, (~C).load(i,j+SIMDSIZE*2UL) - xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, (~C).load(i,j+SIMDSIZE*3UL) - xmm4 * factor );
+ (~C).store( i, j+SIMDSIZE*4UL, (~C).load(i,j+SIMDSIZE*4UL) - xmm5 * factor );
+ (~C).store( i, j+SIMDSIZE*5UL, (~C).load(i,j+SIMDSIZE*5UL) - xmm6 * factor );
+ (~C).store( i, j+SIMDSIZE*6UL, (~C).load(i,j+SIMDSIZE*6UL) - xmm7 * factor );
+ (~C).store( i, j+SIMDSIZE*7UL, (~C).load(i,j+SIMDSIZE*7UL) - xmm8 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE , (~C).load(i ,j+SIMDSIZE ) - xmm2 * factor );
+ (~C).store( i , j+SIMDSIZE*2UL, (~C).load(i ,j+SIMDSIZE*2UL) - xmm3 * factor );
+ (~C).store( i , j+SIMDSIZE*3UL, (~C).load(i ,j+SIMDSIZE*3UL) - xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm5 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE , (~C).load(i+1UL,j+SIMDSIZE ) - xmm6 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, (~C).load(i+1UL,j+SIMDSIZE*2UL) - xmm7 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, (~C).load(i+1UL,j+SIMDSIZE*3UL) - xmm8 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , (~C).load(i,j+SIMDSIZE ) - xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, (~C).load(i,j+SIMDSIZE*2UL) - xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, (~C).load(i,j+SIMDSIZE*3UL) - xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE, (~C).load(i ,j+SIMDSIZE) - xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm3 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE, (~C).load(i+1UL,j+SIMDSIZE) - xmm4 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE, (~C).load(i,j+SIMDSIZE) - xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i+1UL, j, (~C).load(i+1UL,j) - xmm2 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) - xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) -= value1 * scalar;
+ (~C)(i+1UL,j) -= value2 * scalar;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) -= value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (small matrices)***
+ /*!\brief Vectorized default subtraction assignment of a small scaled dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a small scaled
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( ~C, tmp * B * scalar );
+ }
+ else if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( ~C, A * tmp * scalar );
+ }
+ else if( A.rows() * A.columns() <= B.rows() * B.columns() ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( ~C, tmp * B * scalar );
+ }
+ else {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( ~C, A * tmp * scalar );
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*!\brief Default subtraction assignment of a large scaled dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (large matrices)******
+ /*!\brief Vectorized default subtraction assignment of a large scaled dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel is
+ // optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_IBLOCK_SIZE, M ) );
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) - xmm2 * factor );
+ (~C).store( i , j2, (~C).load(i ,j2) - xmm3 * factor );
+ (~C).store( i , j3, (~C).load(i ,j3) - xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm5 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) - xmm6 * factor );
+ (~C).store( i+1UL, j2, (~C).load(i+1UL,j2) - xmm7 * factor );
+ (~C).store( i+1UL, j3, (~C).load(i+1UL,j3) - xmm8 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) - xmm2 * factor );
+ (~C).store( i, j2, (~C).load(i,j2) - xmm3 * factor );
+ (~C).store( i, j3, (~C).load(i,j3) - xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) - xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) - xmm4 * factor );
+ (~C).store( i+2UL, j , (~C).load(i+2UL,j ) - xmm5 * factor );
+ (~C).store( i+2UL, j1, (~C).load(i+2UL,j1) - xmm6 * factor );
+ (~C).store( i+3UL, j , (~C).load(i+3UL,j ) - xmm7 * factor );
+ (~C).store( i+3UL, j1, (~C).load(i+3UL,j1) - xmm8 * factor );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) - xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) - xmm4 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) - xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) - xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) -= value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (large matrices)***
+ /*!\brief Vectorized default subtraction assignment of a large scaled dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a small
+ // scaled dense matrix-dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectSmallSubAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense matrices (default)*******************************
+ /*!\brief Default subtraction assignment of a scaled dense matrix-dense matrix multiplication
+ // (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // scaled dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subraction assignment to dense matrices******************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based subraction assignment of a scaled dense matrix-dense matrix multiplication
+ // (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ subAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ subAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(-scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to column-major matrices*******************************
+ /*!\brief Restructuring subtraction assignment of a scaled dense matrix-dense matrix
+ // multiplication to a column-major matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a scaled
+ // dense matrix-dense matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,true>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ subAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ subAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ subAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*!\brief SMP assignment of a scaled dense matrix-dense matrix multiplication to a dense matrix
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled dense matrix-
+ // dense matrix multiplication expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case either
+ // of the two matrix operands requires an intermediate evaluation and no symmetry can be
+ // exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*!\brief SMP assignment of a scaled dense matrix-dense matrix multiplication to a sparse matrix
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled dense matrix-
+ // dense matrix multiplication expression to a sparse matrix. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case either
+ // of the two matrix operands requires an intermediate evaluation and no symmetry can be
+ // exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to column-major matrices***************************************
+ /*!\brief Restructuring SMP assignment of a scaled dense matrix-dense matrix multiplication to
+ // a column-major matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,true>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ smpAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ smpAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*!\brief SMP addition assignment of a scaled dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled dense
+ // matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to column-major matrices******************************
+ /*!\brief Restructuring SMP addition assignment of a scaled dense matrix-dense matrix
+ // multiplication to a column-major matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a scaled
+ // dense matrix-dense matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,true>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAddAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ smpAddAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ smpAddAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*!\brief SMP subtraction assignment of a scaled dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a scaled
+ // dense matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to column-major matrices***************************
+ /*!\brief Restructuring SMP subtraction assignment of a scaled dense matrix-dense matrix
+ // multiplication to a column-major matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // scaled dense matrix-dense matrix multiplication expression to a column-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,true>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpSubAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ smpSubAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ smpSubAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MMM );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MMM );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of two row-major dense matrices
+// (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side matrix for the multiplication.
+// \param rhs The right-hand side matrix for the multiplication.
+// \return The resulting matrix.
+//
+// This operator represents the multiplication of two row-major dense matrices:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current number of columns of \a lhs and the current number of rows of \a rhs
+// don't match, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const DMatDMatMultExpr<T1,T2>
+ operator*( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< DMatDMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< DMatDMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< DMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsAligned<MT1>, IsAligned<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< DMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< DMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< DMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< DMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< DMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< DMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatDVecMultExprTrait< DMatDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , DMatDVecMultExprTrait_< MT1, DMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatSVecMultExprTrait< DMatDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , DMatDVecMultExprTrait_< MT1, DMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecDMatMultExprTrait< VT, DMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecDMatMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecDMatMultExprTrait< VT, DMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecDMatMultExprTrait_< TSVecDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< DMatDMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< DMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< DMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatDMatSubExpr.h b/src/cpu/blaze/math/expressions/DMatDMatSubExpr.h
new file mode 100644
index 00000000..ab64f2c2
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatDMatSubExpr.h
@@ -0,0 +1,1264 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatDMatSubExpr.h
+// \brief Header file for the dense matrix/dense matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATDMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATDMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATDMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-dense matrix subtractions.
+// \ingroup dense_matrix_expression
+//
+// The DMatDMatSubExpr class represents the compile time expression for subtractions between
+// dense matrices with identical storage order.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+class DMatDMatSubExpr : public DenseMatrix< DMatDMatSubExpr<MT1,MT2,SO>, SO >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ typedef ElementType_<MT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<MT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the subtraction expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for the
+ serial evaluation strategy of the subtraction expression. In case either of the two dense
+ matrix operands requires an intermediate evaluation or the subscript operator can only
+ return by value, \a useAssign will be set to 1 and the subtraction expression will be
+ evaluated via the \a assign function family. Otherwise \a useAssign will be set to 0 and
+ the expression will be evaluated via the function call operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT1>::value || RequiresEvaluation<MT2>::value || !returnExpr };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable and at
+ least one of the two operands requires an intermediate evaluation, \a value is set to 1
+ and the expression specific evaluation strategy is selected. Otherwise \a value is set
+ to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatDMatSubExpr<MT1,MT2,SO> This; //!< Type of this DMatDMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DMatDMatSubExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense matrix.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the left-hand side dense matrix expression.
+ typedef ConstIterator_<MT1> LeftIteratorType;
+
+ //! ConstIterator type of the right-hand side dense matrix expression.
+ typedef ConstIterator_<MT2> RightIteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param left Iterator to the initial left-hand side element.
+ // \param right Iterator to the initial right-hand side element.
+ */
+ explicit inline ConstIterator( LeftIteratorType left, RightIteratorType right )
+ : left_ ( left ) // Iterator to the current left-hand side element
+ , right_( right ) // Iterator to the current right-hand side element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ left_ += inc;
+ right_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ left_ -= dec;
+ right_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++left_;
+ ++right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( left_++, right_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --left_;
+ --right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( left_--, right_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return (*left_) - (*right_);
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return left_.load() - right_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return left_ == rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return left_ != rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return left_ < rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return left_ > rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return left_ <= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return left_ >= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return left_ - rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.left_ - dec, it.right_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftIteratorType left_; //!< Iterator to the current left-hand side element.
+ RightIteratorType right_; //!< Iterator to the current right-hand side element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT1::simdEnabled && MT2::simdEnabled &&
+ HasSIMDSub<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT1::smpAssignable && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatDMatSubExpr class.
+ //
+ // \param lhs The left-hand side operand of the subtraction expression.
+ // \param rhs The right-hand side operand of the subtraction expression.
+ */
+ explicit inline DMatDMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t i, size_t j ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !SO || ( i % SIMDSIZE == 0UL ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( SO || ( j % SIMDSIZE == 0UL ), "Invalid column access index" );
+ return lhs_.load(i,j) - rhs_.load(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( lhs_.begin(i), rhs_.begin(i) );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( lhs_.end(i), rhs_.end(i) );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && ( RequiresEvaluation<MT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
+ ( IsExpression<MT2>::value && ( RequiresEvaluation<MT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
+ ( ( ( SO == rowMajor ) ? rows() : columns() ) > SMP_DMATDMATSUB_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-dense
+ // matrix subtraction expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,SO2>& lhs, const DMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-dense
+ // matrix subtraction expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( SparseMatrix<MT,SO2>& lhs, const DMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // dense matrix subtraction expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // dense matrix subtraction expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-dense
+ // matrix subtraction expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-dense
+ // matrix subtraction expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-dense matrix subtraction expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of two dense matrices with identical storage
+// order (\f$ A=B-C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the left-hand side matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the subtraction of two dense matrices with identical storage order:
+
+ \code
+ blaze::DynamicMatrix<double> A, B, C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+inline const DMatDMatSubExpr<T1,T2,SO>
+ operator-( const DenseMatrix<T1,SO>& lhs, const DenseMatrix<T2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatDMatSubExpr<T1,T2,SO>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Rows< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Columns< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsAligned< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsAligned<MT1>, IsAligned<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsPadded< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsPadded<MT1>, IsPadded<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsSymmetric< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsHermitian< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsLower< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniLower< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyLower< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUpper< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniUpper< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyUpper< DMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatDMatSubExpr<MT1,MT2,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct RowExprTrait< DMatDMatSubExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct ColumnExprTrait< DMatDMatSubExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatDVecMultExpr.h b/src/cpu/blaze/math/expressions/DMatDVecMultExpr.h
new file mode 100644
index 00000000..40b111db
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatDVecMultExpr.h
@@ -0,0 +1,5453 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatDVecMultExpr.h
+// \brief Header file for the dense matrix/dense vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/gemv.h>
+#include <blaze/math/blas/trmv.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/math/expressions/VecScalarMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-dense vector multiplications.
+// \ingroup dense_vector_expression
+//
+// The DMatDVecMultExpr class represents the compile time expression for multiplications
+// between row-major dense matrices and dense vectors.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename VT > // Type of the right-hand side dense vector
+class DMatDVecMultExpr : public DenseVector< DMatDVecMultExpr<MT,VT>, false >
+ , private MatVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side dense vector expression.
+ typedef ElementType_<MRT> MET; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the right-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
+ IsBLASCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateMatrix || evaluateVector ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the matrix type and the two involved vector types are suited for a BLAS kernel,
+ the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the matrix type and the two involved vector types are suited for a vectorized
+ computation of the matrix/vector multiplication, the nested \a value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatDVecMultExpr<MT,VT> This; //!< Type of this DMatDVecMultExpr instance.
+ typedef MultTrait_<MRT,VRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ MT::simdEnabled && VT::simdEnabled &&
+ HasSIMDAdd<MET,VET>::value &&
+ HasSIMDMult<MET,VET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatDVecMultExpr class.
+ //
+ // \param mat The left-hand side matrix operand of the multiplication expression.
+ // \param vec The right-hand side vector operand of the multiplication expression.
+ */
+ explicit inline DMatDVecMultExpr( const MT& mat, const VT& vec ) noexcept
+ : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
+ , vec_( vec ) // Right-hand side dense vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return mat_(index,index) * vec_[index];
+ }
+ else if( IsLower<MT>::value && ( index + 8UL < mat_.rows() ) )
+ {
+ const size_t n( IsStrictlyLower<MT>::value ? index : index+1UL );
+ return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n );
+ }
+ else if( IsUpper<MT>::value && ( index > 8UL ) )
+ {
+ const size_t begin( IsStrictlyUpper<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.columns() - begin );
+ return subvector( row( mat_, index ), begin, n ) * subvector( vec_, begin, n );
+ }
+ else
+ {
+ return row( mat_, index ) * vec_;
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept{
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an aliasing effect is possible, \a false if not.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the given alias is contained in this expression, \a false if not.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return mat_.isAligned() && vec_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( mat_.rows() * mat_.columns() < DMATDVECMULT_THRESHOLD ) ) &&
+ ( size() > SMP_DMATDVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand mat_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand vec_; //!< Right-hand side dense vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-dense
+ // vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+ else if( rhs.mat_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DMatDVecMultExpr::selectAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors (kernel selection)**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a dense matrix-dense vector multiplication
+ // to a dense vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
+ selectSmallAssignKernel( y, A, x );
+ else
+ selectBlasAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the dense matrix-dense vector
+ // multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ y.assign( A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (small matrices)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the dense matrix-
+ // dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+7UL,j) * x1;
+ }
+
+ y[i ] = sum( xmm1 );
+ y[i+1UL] = sum( xmm2 );
+ y[i+2UL] = sum( xmm3 );
+ y[i+3UL] = sum( xmm4 );
+ y[i+4UL] = sum( xmm5 );
+ y[i+5UL] = sum( xmm6 );
+ y[i+6UL] = sum( xmm7 );
+ y[i+7UL] = sum( xmm8 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ y[i+4UL] += A(i+4UL,j) * x[j];
+ y[i+5UL] += A(i+5UL,j) * x[j];
+ y[i+6UL] += A(i+6UL,j) * x[j];
+ y[i+7UL] += A(i+7UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ }
+
+ y[i ] = sum( xmm1 );
+ y[i+1UL] = sum( xmm2 );
+ y[i+2UL] = sum( xmm3 );
+ y[i+3UL] = sum( xmm4 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+3UL) <= M; i+=3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+2UL : i+3UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ }
+
+ y[i ] = sum( xmm1 );
+ y[i+1UL] = sum( xmm2 );
+ y[i+2UL] = sum( xmm3 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ }
+
+ y[i ] = sum( xmm1 );
+ y[i+1UL] = sum( xmm2 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(j);
+ }
+
+ y[i] = sum( xmm1 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] += A(i,j) * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (large matrices)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the dense matrix-
+ // dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ reset( y );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 + A.load(i+4UL,j2) * x3 + A.load(i+4UL,j3) * x4 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 + A.load(i+5UL,j2) * x3 + A.load(i+5UL,j3) * x4 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 + A.load(i+6UL,j2) * x3 + A.load(i+6UL,j3) * x4 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 + A.load(i+7UL,j2) * x3 + A.load(i+7UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ y[i+4UL] += A(i+4UL,j) * x[j];
+ y[i+5UL] += A(i+5UL,j) * x[j];
+ y[i+6UL] += A(i+6UL,j) * x[j];
+ y[i+7UL] += A(i+7UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i] += sum( A.load(i,j) * x1 + A.load(i,j1) * x2 + A.load(i,j2) * x3 + A.load(i,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i] += sum( A.load(i,j) * x1 + A.load(i,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i] += sum( A.load(i,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] += A(i,j) * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors (default)********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectLargeAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors******************************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based assignment of a dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function performs the dense matrix-dense vector multiplication based on the according
+ // BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ assign( y, x );
+ trmv( y, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ }
+ else {
+ gemv( y, A, x, ET(1), ET(0) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-dense vector multiplication to a sparse vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-dense
+ // vector multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DMatDVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors (kernel selection)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a dense matrix-dense vector
+ // multiplication to a dense vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( y, A, x );
+ else
+ selectBlasAddAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the dense matrix-dense
+ // vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ y.addAssign( A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (small matrices)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultAddAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (small matrices)********************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the dense
+ // matrix-dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+7UL,j) * x1;
+ }
+
+ y[i ] += sum( xmm1 );
+ y[i+1UL] += sum( xmm2 );
+ y[i+2UL] += sum( xmm3 );
+ y[i+3UL] += sum( xmm4 );
+ y[i+4UL] += sum( xmm5 );
+ y[i+5UL] += sum( xmm6 );
+ y[i+6UL] += sum( xmm7 );
+ y[i+7UL] += sum( xmm8 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ y[i+4UL] += A(i+4UL,j) * x[j];
+ y[i+5UL] += A(i+5UL,j) * x[j];
+ y[i+6UL] += A(i+6UL,j) * x[j];
+ y[i+7UL] += A(i+7UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ }
+
+ y[i ] += sum( xmm1 );
+ y[i+1UL] += sum( xmm2 );
+ y[i+2UL] += sum( xmm3 );
+ y[i+3UL] += sum( xmm4 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+3UL) <= M; i+=3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+2UL : i+3UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ }
+
+ y[i ] += sum( xmm1 );
+ y[i+1UL] += sum( xmm2 );
+ y[i+2UL] += sum( xmm3 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ }
+
+ y[i ] += sum( xmm1 );
+ y[i+1UL] += sum( xmm2 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(j);
+ }
+
+ y[i] += sum( xmm1 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] += A(i,j) * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (large matrices)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultAddAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (large matrices)********************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the dense
+ // matrix-dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 + A.load(i+4UL,j2) * x3 + A.load(i+4UL,j3) * x4 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 + A.load(i+5UL,j2) * x3 + A.load(i+5UL,j3) * x4 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 + A.load(i+6UL,j2) * x3 + A.load(i+6UL,j3) * x4 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 + A.load(i+7UL,j2) * x3 + A.load(i+7UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ y[i+4UL] += A(i+4UL,j) * x[j];
+ y[i+5UL] += A(i+5UL,j) * x[j];
+ y[i+6UL] += A(i+6UL,j) * x[j];
+ y[i+7UL] += A(i+7UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i] += sum( A.load(i,j) * x1 + A.load(i,j1) * x2 + A.load(i,j2) * x3 + A.load(i,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i] += sum( A.load(i,j) * x1 + A.load(i,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i] += sum( A.load(i,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] += A(i,j) * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors (default)***********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectLargeAddAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors*********************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based addition assignment of a matrix-vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function performs the dense matrix-dense vector multiplication based on the according
+ // BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ addAssign( y, tmp );
+ }
+ else {
+ gemv( y, A, x, ET(1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DMatDVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors (kernel selection)**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a dense matrix-dense vector
+ // multiplication to a dense vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( y, A, x );
+ else
+ selectBlasSubAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a dense matrix-dense vector multiplication
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the dense matrix-
+ // dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ y.subAssign( A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (small matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small dense matrix-dense vector multiplication
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultSubAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (small matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the dense
+ // matrix-dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+7UL,j) * x1;
+ }
+
+ y[i ] -= sum( xmm1 );
+ y[i+1UL] -= sum( xmm2 );
+ y[i+2UL] -= sum( xmm3 );
+ y[i+3UL] -= sum( xmm4 );
+ y[i+4UL] -= sum( xmm5 );
+ y[i+5UL] -= sum( xmm6 );
+ y[i+6UL] -= sum( xmm7 );
+ y[i+7UL] -= sum( xmm8 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j];
+ y[i+1UL] -= A(i+1UL,j) * x[j];
+ y[i+2UL] -= A(i+2UL,j) * x[j];
+ y[i+3UL] -= A(i+3UL,j) * x[j];
+ y[i+4UL] -= A(i+4UL,j) * x[j];
+ y[i+5UL] -= A(i+5UL,j) * x[j];
+ y[i+6UL] -= A(i+6UL,j) * x[j];
+ y[i+7UL] -= A(i+7UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ }
+
+ y[i ] -= sum( xmm1 );
+ y[i+1UL] -= sum( xmm2 );
+ y[i+2UL] -= sum( xmm3 );
+ y[i+3UL] -= sum( xmm4 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j];
+ y[i+1UL] -= A(i+1UL,j) * x[j];
+ y[i+2UL] -= A(i+2UL,j) * x[j];
+ y[i+3UL] -= A(i+3UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+3UL) <= M; i+=3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+2UL : i+3UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ }
+
+ y[i ] -= sum( xmm1 );
+ y[i+1UL] -= sum( xmm2 );
+ y[i+2UL] -= sum( xmm3 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j];
+ y[i+1UL] -= A(i+1UL,j) * x[j];
+ y[i+2UL] -= A(i+2UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ }
+
+ y[i ] -= sum( xmm1 );
+ y[i+1UL] -= sum( xmm2 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j];
+ y[i+1UL] -= A(i+1UL,j) * x[j];
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(j);
+ }
+
+ y[i] -= sum( xmm1 );
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] -= A(i,j) * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (large matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large dense matrix-dense vector multiplication
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultSubAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (large matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the dense
+ // matrix-dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 );
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 );
+ y[i+4UL] -= sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 + A.load(i+4UL,j2) * x3 + A.load(i+4UL,j3) * x4 );
+ y[i+5UL] -= sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 + A.load(i+5UL,j2) * x3 + A.load(i+5UL,j3) * x4 );
+ y[i+6UL] -= sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 + A.load(i+6UL,j2) * x3 + A.load(i+6UL,j3) * x4 );
+ y[i+7UL] -= sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 + A.load(i+7UL,j2) * x3 + A.load(i+7UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 );
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 );
+ y[i+4UL] -= sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 );
+ y[i+5UL] -= sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 );
+ y[i+6UL] -= sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 );
+ y[i+7UL] -= sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] -= sum( A.load(i ,j) * x1 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 );
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 );
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 );
+ y[i+4UL] -= sum( A.load(i+4UL,j) * x1 );
+ y[i+5UL] -= sum( A.load(i+5UL,j) * x1 );
+ y[i+6UL] -= sum( A.load(i+6UL,j) * x1 );
+ y[i+7UL] -= sum( A.load(i+7UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j];
+ y[i+1UL] -= A(i+1UL,j) * x[j];
+ y[i+2UL] -= A(i+2UL,j) * x[j];
+ y[i+3UL] -= A(i+3UL,j) * x[j];
+ y[i+4UL] -= A(i+4UL,j) * x[j];
+ y[i+5UL] -= A(i+5UL,j) * x[j];
+ y[i+6UL] -= A(i+6UL,j) * x[j];
+ y[i+7UL] -= A(i+7UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 );
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 );
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] -= sum( A.load(i ,j) * x1 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 );
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 );
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j];
+ y[i+1UL] -= A(i+1UL,j) * x[j];
+ y[i+2UL] -= A(i+2UL,j) * x[j];
+ y[i+3UL] -= A(i+3UL,j) * x[j];
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] -= sum( A.load(i ,j) * x1 );
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j];
+ y[i+1UL] -= A(i+1UL,j) * x[j];
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i] -= sum( A.load(i,j) * x1 + A.load(i,j1) * x2 + A.load(i,j2) * x3 + A.load(i,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i] -= sum( A.load(i,j) * x1 + A.load(i,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i] -= sum( A.load(i,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] -= A(i,j) * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors (default)********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a dense matrix-dense vector multiplication
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectLargeSubAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors******************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based subtraction assignment of a matrix-vector multiplication
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function performs the dense matrix-dense vector multiplication based on the according
+ // BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ subAssign( y, tmp );
+ }
+ else {
+ gemv( y, A, x, ET(-1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-dense
+ // vector multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+ else if( rhs.mat_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-dense vector multiplication to a sparse vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-dense
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR( MT, VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSCALARMULTEXPR SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Expression object for scaled dense matrix-dense vector multiplications.
+// \ingroup dense_vector_expression
+//
+// This specialization of the DVecScalarMultExpr class represents the compile time expression
+// for scaled multiplications between a row-major dense matrix and a non-transpose dense vector.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename VT // Type of the right-hand side dense vector
+ , typename ST > // Type of the scalar value
+class DVecScalarMultExpr< DMatDVecMultExpr<MT,VT>, ST, false >
+ : public DenseVector< DVecScalarMultExpr< DMatDVecMultExpr<MT,VT>, ST, false >, false >
+ , private VecScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef DMatDVecMultExpr<MT,VT> MVM; //!< Type of the dense matrix-dense vector multiplication expression.
+ typedef ResultType_<MVM> RES; //!< Result type of the dense matrix-dense vector multiplication expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side dense vector expression.
+ typedef ElementType_<MRT> MET; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the right-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
+ IsBLASCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateMatrix || evaluateVector ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the matrix type, the two involved vector types, and the scalar type are suited
+ for a BLAS kernel, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ !( IsBuiltin< ElementType_<T1> >::value && IsComplex<T4>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types, the matrix type, and the scalar type are suited
+ for a vectorized computation of the scaled vector/matrix multiplication, the nested
+ \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3>
+ , T4 >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecScalarMultExpr<MVM,ST,false> This; //!< Type of this DVecScalarMultExpr instance.
+ typedef MultTrait_<RES,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef const DMatDVecMultExpr<MT,VT> LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+
+ //! Type for the assignment of the dense matrix operand of the left-hand side expression.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the dense vector operand of the left-hand side expression.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ MT::simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable<MET,VET,ST>::value &&
+ HasSIMDAdd<MET,VET>::value &&
+ HasSIMDMult<MET,VET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecScalarMultExpr class.
+ //
+ // \param vector The left-hand side dense vector of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DVecScalarMultExpr( const MVM& vector, ST scalar )
+ : vector_( vector ) // Left-hand side dense vector of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
+ return vector_[index] * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= vector_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const {
+ return vector_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return vector_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const {
+ return vector_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const {
+ LeftOperand_<MVM> A( vector_.leftOperand() );
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) ) &&
+ ( size() > SMP_DMATDVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vector_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*!\brief Assignment of a scaled dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled dense matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectAssignKernel( ~lhs, A, x, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors (kernel selection)**********************************************
+ /*!\brief Selection of the kernel for an assignment of a scaled dense matrix-dense vector
+ // multiplication to a dense vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
+ selectSmallAssignKernel( y, A, x, scalar );
+ else
+ selectBlasAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*!\brief Default assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the scaled dense matrix-dense
+ // vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ y.assign( A * x * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*!\brief Default assignment of a small scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (small matrices)*****************************
+ /*!\brief Vectorized default assignment of a small scaled dense matrix-dense vector
+ // multiplication (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the scaled dense
+ // matrix-dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+7UL,j) * x1;
+ }
+
+ y[i ] = sum( xmm1 ) * scalar;
+ y[i+1UL] = sum( xmm2 ) * scalar;
+ y[i+2UL] = sum( xmm3 ) * scalar;
+ y[i+3UL] = sum( xmm4 ) * scalar;
+ y[i+4UL] = sum( xmm5 ) * scalar;
+ y[i+5UL] = sum( xmm6 ) * scalar;
+ y[i+6UL] = sum( xmm7 ) * scalar;
+ y[i+7UL] = sum( xmm8 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] += A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] += A(i+3UL,j) * x[j] * scalar;
+ y[i+4UL] += A(i+4UL,j) * x[j] * scalar;
+ y[i+5UL] += A(i+5UL,j) * x[j] * scalar;
+ y[i+6UL] += A(i+6UL,j) * x[j] * scalar;
+ y[i+7UL] += A(i+7UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ }
+
+ y[i ] = sum( xmm1 ) * scalar;
+ y[i+1UL] = sum( xmm2 ) * scalar;
+ y[i+2UL] = sum( xmm3 ) * scalar;
+ y[i+3UL] = sum( xmm4 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] += A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] += A(i+3UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+3UL) <= M; i+=3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+2UL : i+3UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ }
+
+ y[i ] = sum( xmm1 ) * scalar;
+ y[i+1UL] = sum( xmm2 ) * scalar;
+ y[i+2UL] = sum( xmm3 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] += A(i+2UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ }
+
+ y[i ] = sum( xmm1 ) * scalar;
+ y[i+1UL] = sum( xmm2 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(j);
+ }
+
+ y[i] = sum( xmm1 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] += A(i,j) * x[j] * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*!\brief Default assignment of a large scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (large matrices)*****************************
+ /*!\brief Vectorized default assignment of a large scaled dense matrix-dense vector
+ // multiplication (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the scaled dense
+ // matrix-dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ reset( y );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 + A.load(i+4UL,j2) * x3 + A.load(i+4UL,j3) * x4 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 + A.load(i+5UL,j2) * x3 + A.load(i+5UL,j3) * x4 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 + A.load(i+6UL,j2) * x3 + A.load(i+6UL,j3) * x4 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 + A.load(i+7UL,j2) * x3 + A.load(i+7UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 );
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 );
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 );
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 );
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ y[i+4UL] += A(i+4UL,j) * x[j];
+ y[i+5UL] += A(i+5UL,j) * x[j];
+ y[i+6UL] += A(i+6UL,j) * x[j];
+ y[i+7UL] += A(i+7UL,j) * x[j];
+ }
+
+ y[i ] *= scalar;
+ y[i+1UL] *= scalar;
+ y[i+2UL] *= scalar;
+ y[i+3UL] *= scalar;
+ y[i+4UL] *= scalar;
+ y[i+5UL] *= scalar;
+ y[i+6UL] *= scalar;
+ y[i+7UL] *= scalar;
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 );
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ y[i+2UL] += A(i+2UL,j) * x[j];
+ y[i+3UL] += A(i+3UL,j) * x[j];
+ }
+
+ y[i ] *= scalar;
+ y[i+1UL] *= scalar;
+ y[i+2UL] *= scalar;
+ y[i+3UL] *= scalar;
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 );
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ }
+
+ y[i ] *= scalar;
+ y[i+1UL] *= scalar;
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i] += sum( A.load(i,j) * x1 + A.load(i,j1) * x2 + A.load(i,j2) * x3 + A.load(i,j3) * x4 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i] += sum( A.load(i,j) * x1 + A.load(i,j1) * x2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i] += sum( A.load(i,j) * x1 );
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] += A(i,j) * x[j];
+ }
+
+ y[i] *= scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors (default)********************************************
+ /*!\brief Default assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large scaled
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectLargeAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors******************************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-dense vector multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ assign( y, scalar * x );
+ trmv( y, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ }
+ else {
+ gemv( y, A, x, ET(scalar), ET(0) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*!\brief Assignment of a scaled dense matrix-dense vector multiplication to a sparse vector
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled dense matrix-
+ // dense vector multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*!\brief Addition assignment of a scaled dense matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectAddAssignKernel( ~lhs, A, x, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors (kernel selection)*************************************
+ /*!\brief Selection of the kernel for an addition assignment of a scaled dense matrix-dense
+ // vector multiplication to a dense vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( y, A, x, scalar );
+ else
+ selectBlasAddAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*!\brief Default addition assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the scaled dense matrix-
+ // dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ y.addAssign( A * x * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (small matrices)*******************************
+ /*!\brief Default addition assignment of a small scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (small matrices)********************
+ /*!\brief Vectorized default addition assignment of a small scaled dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the scaled
+ // dense matrix-dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+7UL,j) * x1;
+ }
+
+ y[i ] += sum( xmm1 ) * scalar;
+ y[i+1UL] += sum( xmm2 ) * scalar;
+ y[i+2UL] += sum( xmm3 ) * scalar;
+ y[i+3UL] += sum( xmm4 ) * scalar;
+ y[i+4UL] += sum( xmm5 ) * scalar;
+ y[i+5UL] += sum( xmm6 ) * scalar;
+ y[i+6UL] += sum( xmm7 ) * scalar;
+ y[i+7UL] += sum( xmm8 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] += A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] += A(i+3UL,j) * x[j] * scalar;
+ y[i+4UL] += A(i+4UL,j) * x[j] * scalar;
+ y[i+5UL] += A(i+5UL,j) * x[j] * scalar;
+ y[i+6UL] += A(i+6UL,j) * x[j] * scalar;
+ y[i+7UL] += A(i+7UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ }
+
+ y[i ] += sum( xmm1 ) * scalar;
+ y[i+1UL] += sum( xmm2 ) * scalar;
+ y[i+2UL] += sum( xmm3 ) * scalar;
+ y[i+3UL] += sum( xmm4 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] += A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] += A(i+3UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+3UL) <= M; i+=3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+2UL : i+3UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ }
+
+ y[i ] += sum( xmm1 ) * scalar;
+ y[i+1UL] += sum( xmm2 ) * scalar;
+ y[i+2UL] += sum( xmm3 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] += A(i+2UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ }
+
+ y[i ] += sum( xmm1 ) * scalar;
+ y[i+1UL] += sum( xmm2 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(j);
+ }
+
+ y[i] += sum( xmm1 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] += A(i,j) * x[j] * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (large matrices)*******************************
+ /*!\brief Default addition assignment of a large scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (large matrices)********************
+ /*!\brief Vectorized default addition assignment of a large scaled dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the scaled
+ // dense matrix-dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 ) * scalar;
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 ) * scalar;
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 ) * scalar;
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 + A.load(i+4UL,j2) * x3 + A.load(i+4UL,j3) * x4 ) * scalar;
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 + A.load(i+5UL,j2) * x3 + A.load(i+5UL,j3) * x4 ) * scalar;
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 + A.load(i+6UL,j2) * x3 + A.load(i+6UL,j3) * x4 ) * scalar;
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 + A.load(i+7UL,j2) * x3 + A.load(i+7UL,j3) * x4 ) * scalar;
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 ) * scalar;
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 ) * scalar;
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 ) * scalar;
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 ) * scalar;
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 ) * scalar;
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 ) * scalar;
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 ) * scalar;
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 ) * scalar;
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 ) * scalar;
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 ) * scalar;
+ y[i+4UL] += sum( A.load(i+4UL,j) * x1 ) * scalar;
+ y[i+5UL] += sum( A.load(i+5UL,j) * x1 ) * scalar;
+ y[i+6UL] += sum( A.load(i+6UL,j) * x1 ) * scalar;
+ y[i+7UL] += sum( A.load(i+7UL,j) * x1 ) * scalar;
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] += A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] += A(i+3UL,j) * x[j] * scalar;
+ y[i+4UL] += A(i+4UL,j) * x[j] * scalar;
+ y[i+5UL] += A(i+5UL,j) * x[j] * scalar;
+ y[i+6UL] += A(i+6UL,j) * x[j] * scalar;
+ y[i+7UL] += A(i+7UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 ) * scalar;
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 ) * scalar;
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 ) * scalar;
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 ) * scalar;
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 ) * scalar;
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 ) * scalar;
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 ) * scalar;
+ y[i+2UL] += sum( A.load(i+2UL,j) * x1 ) * scalar;
+ y[i+3UL] += sum( A.load(i+3UL,j) * x1 ) * scalar;
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] += A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] += A(i+3UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 ) * scalar;
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] += sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 ) * scalar;
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] += sum( A.load(i ,j) * x1 ) * scalar;
+ y[i+1UL] += sum( A.load(i+1UL,j) * x1 ) * scalar;
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] += A(i ,j) * x[j] * scalar;
+ y[i+1UL] += A(i+1UL,j) * x[j] * scalar;
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i] += sum( A.load(i,j) * x1 + A.load(i,j1) * x2 + A.load(i,j2) * x3 + A.load(i,j3) * x4 ) * scalar;
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i] += sum( A.load(i,j) * x1 + A.load(i,j1) * x2 ) * scalar;
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i] += sum( A.load(i,j) * x1 ) * scalar;
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] += A(i,j) * x[j] * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors (default)***********************************
+ /*!\brief Default addition assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // scaled dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectLargeAddAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors*********************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based addition assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-dense vector multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( scalar * x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ addAssign( y, tmp );
+ }
+ else {
+ gemv( y, A, x, ET(scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*!\brief Subtraction assignment of a scaled dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a scaled
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectSubAssignKernel( ~lhs, A, x, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors (kernel selection)**********************************
+ /*!\brief Selection of the kernel for a subtraction assignment of a scaled dense matrix-dense
+ // vector multiplication to a dense vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( y, A, x, scalar );
+ else
+ selectBlasSubAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*!\brief Default subtraction assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the scaled dense
+ // matrix-dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ y.subAssign( A * x * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (small matrices)****************************
+ /*!\brief Default subtraction assignment of a small scaled dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // scaled dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (small matrices)*****************
+ /*!\brief Vectorized default subtraction assignment of a small scaled dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the scaled
+ // dense matrix-dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+7UL,j) * x1;
+ }
+
+ y[i ] -= sum( xmm1 ) * scalar;
+ y[i+1UL] -= sum( xmm2 ) * scalar;
+ y[i+2UL] -= sum( xmm3 ) * scalar;
+ y[i+3UL] -= sum( xmm4 ) * scalar;
+ y[i+4UL] -= sum( xmm5 ) * scalar;
+ y[i+5UL] -= sum( xmm6 ) * scalar;
+ y[i+6UL] -= sum( xmm7 ) * scalar;
+ y[i+7UL] -= sum( xmm8 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j] * scalar;
+ y[i+1UL] -= A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] -= A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] -= A(i+3UL,j) * x[j] * scalar;
+ y[i+4UL] -= A(i+4UL,j) * x[j] * scalar;
+ y[i+5UL] -= A(i+5UL,j) * x[j] * scalar;
+ y[i+6UL] -= A(i+6UL,j) * x[j] * scalar;
+ y[i+7UL] -= A(i+7UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+3UL,j) * x1;
+ }
+
+ y[i ] -= sum( xmm1 ) * scalar;
+ y[i+1UL] -= sum( xmm2 ) * scalar;
+ y[i+2UL] -= sum( xmm3 ) * scalar;
+ y[i+3UL] -= sum( xmm4 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j] * scalar;
+ y[i+1UL] -= A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] -= A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] -= A(i+3UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+3UL) <= M; i+=3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+2UL : i+3UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ xmm3 = xmm3 + A.load(i+2UL,j) * x1;
+ }
+
+ y[i ] -= sum( xmm1 ) * scalar;
+ y[i+1UL] -= sum( xmm2 ) * scalar;
+ y[i+2UL] -= sum( xmm3 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j] * scalar;
+ y[i+1UL] -= A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] -= A(i+2UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+1UL,j) * x1;
+ }
+
+ y[i ] -= sum( xmm1 ) * scalar;
+ y[i+1UL] -= sum( xmm2 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j] * scalar;
+ y[i+1UL] -= A(i+1UL,j) * x[j] * scalar;
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(j);
+ }
+
+ y[i] -= sum( xmm1 ) * scalar;
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] -= A(i,j) * x[j] * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (large matrices)****************************
+ /*!\brief Default subtraction assignment of a large scaled dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // scaled dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (large matrices)*****************
+ /*!\brief Vectorized default subtraction assignment of a large scaled dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the scaled
+ // dense matrix-dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT2>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+8UL) <= M; i+=8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+7UL : i+8UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 ) * scalar;
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 ) * scalar;
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 ) * scalar;
+ y[i+4UL] -= sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 + A.load(i+4UL,j2) * x3 + A.load(i+4UL,j3) * x4 ) * scalar;
+ y[i+5UL] -= sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 + A.load(i+5UL,j2) * x3 + A.load(i+5UL,j3) * x4 ) * scalar;
+ y[i+6UL] -= sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 + A.load(i+6UL,j2) * x3 + A.load(i+6UL,j3) * x4 ) * scalar;
+ y[i+7UL] -= sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 + A.load(i+7UL,j2) * x3 + A.load(i+7UL,j3) * x4 ) * scalar;
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 ) * scalar;
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 ) * scalar;
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 ) * scalar;
+ y[i+4UL] -= sum( A.load(i+4UL,j) * x1 + A.load(i+4UL,j1) * x2 ) * scalar;
+ y[i+5UL] -= sum( A.load(i+5UL,j) * x1 + A.load(i+5UL,j1) * x2 ) * scalar;
+ y[i+6UL] -= sum( A.load(i+6UL,j) * x1 + A.load(i+6UL,j1) * x2 ) * scalar;
+ y[i+7UL] -= sum( A.load(i+7UL,j) * x1 + A.load(i+7UL,j1) * x2 ) * scalar;
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] -= sum( A.load(i ,j) * x1 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 ) * scalar;
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 ) * scalar;
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 ) * scalar;
+ y[i+4UL] -= sum( A.load(i+4UL,j) * x1 ) * scalar;
+ y[i+5UL] -= sum( A.load(i+5UL,j) * x1 ) * scalar;
+ y[i+6UL] -= sum( A.load(i+6UL,j) * x1 ) * scalar;
+ y[i+7UL] -= sum( A.load(i+7UL,j) * x1 ) * scalar;
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j] * scalar;
+ y[i+1UL] -= A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] -= A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] -= A(i+3UL,j) * x[j] * scalar;
+ y[i+4UL] -= A(i+4UL,j) * x[j] * scalar;
+ y[i+5UL] -= A(i+5UL,j) * x[j] * scalar;
+ y[i+6UL] -= A(i+6UL,j) * x[j] * scalar;
+ y[i+7UL] -= A(i+7UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+3UL : i+4UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 ) * scalar;
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 + A.load(i+2UL,j2) * x3 + A.load(i+2UL,j3) * x4 ) * scalar;
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 + A.load(i+3UL,j2) * x3 + A.load(i+3UL,j3) * x4 ) * scalar;
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 ) * scalar;
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 + A.load(i+2UL,j1) * x2 ) * scalar;
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 + A.load(i+3UL,j1) * x2 ) * scalar;
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] -= sum( A.load(i ,j) * x1 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 ) * scalar;
+ y[i+2UL] -= sum( A.load(i+2UL,j) * x1 ) * scalar;
+ y[i+3UL] -= sum( A.load(i+3UL,j) * x1 ) * scalar;
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j] * scalar;
+ y[i+1UL] -= A(i+1UL,j) * x[j] * scalar;
+ y[i+2UL] -= A(i+2UL,j) * x[j] * scalar;
+ y[i+3UL] -= A(i+3UL,j) * x[j] * scalar;
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i+1UL : i+2UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 + A.load(i ,j2) * x3 + A.load(i ,j3) * x4 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 + A.load(i+1UL,j2) * x3 + A.load(i+1UL,j3) * x4 ) * scalar;
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i ] -= sum( A.load(i ,j) * x1 + A.load(i ,j1) * x2 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 + A.load(i+1UL,j1) * x2 ) * scalar;
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i ] -= sum( A.load(i ,j) * x1 ) * scalar;
+ y[i+1UL] -= sum( A.load(i+1UL,j) * x1 ) * scalar;
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i ] -= A(i ,j) * x[j] * scalar;
+ y[i+1UL] -= A(i+1UL,j) * x[j] * scalar;
+ }
+ }
+
+ if( i < M )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ const SIMDType x3( x.load(j2) );
+ const SIMDType x4( x.load(j3) );
+ y[i] -= sum( A.load(i,j) * x1 + A.load(i,j1) * x2 + A.load(i,j2) * x3 + A.load(i,j3) * x4 ) * scalar;
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL ) {
+ const size_t j1( j+SIMDSIZE );
+ const SIMDType x1( x.load(j ) );
+ const SIMDType x2( x.load(j1) );
+ y[i] -= sum( A.load(i,j) * x1 + A.load(i,j1) * x2 ) * scalar;
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ const SIMDType x1( x.load(j) );
+ y[i] -= sum( A.load(i,j) * x1 ) * scalar;
+ }
+
+ for( ; remainder && j<jend; ++j ) {
+ y[i] -= A(i,j) * x[j] * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors (default)********************************
+ /*!\brief Default subtraction assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // scaled dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectLargeSubAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors******************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based subtraction assignment of a scaled dense matrix-dense vector multiplication
+ // (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-dense vector multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( scalar * x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ subAssign( y, tmp );
+ }
+ else {
+ gemv( y, A, x, ET(-scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*!\brief Multiplication assignment of a scaled dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}*=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a scaled
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*!\brief Division assignment of a scaled dense matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}/=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a scaled dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*!\brief SMP assignment of a scaled dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled dense matrix-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT x( right ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, A * x * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*!\brief SMP assignment of a scaled dense matrix-dense vector multiplication to a sparse vector
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled dense matrix-
+ // dense vector multiplication expression to a sparse vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*!\brief SMP addition assignment of a scaled dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a scaled
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT x( right ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, A * x * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*!\brief SMP subtraction assignment of a scaled dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a scaled
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT x( right ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, A * x * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*!\brief SMP multiplication assignment of a scaled dense matrix-dense vector multiplication
+ // to a dense vector (\f$ \vec{y}*=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a scaled
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*!\brief SMP division assignment of a scaled dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}/=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression division.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a scaled
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( MVM );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( MVM );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major dense matrix and a dense
+// vector (\f$ \vec{y}=A*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side row-major dense matrix for the multiplication.
+// \param vec The right-hand side dense vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator represents the multiplication between a row-major dense matrix and a dense vector:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ blaze::DynamicMatrix<double,rowMajor> A;
+ blaze::DynamicVector<double,columnVector> x, y;
+ // ... Resizing and initialization
+ y = A * x;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both the
+// dense matrix type \a T1 and the dense vector type \a T2 as well as the two element types
+// \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of columns
+// of the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense vector
+inline const DisableIf_< IsMatMatMultExpr<T1>, DMatDVecMultExpr<T1,T2> >
+ operator*( const DenseMatrix<T1,false>& mat, const DenseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return DMatDVecMultExpr<T1,T2>( ~mat, ~vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a dense matrix-matrix
+// multiplication expression and a dense vector (\f$ \vec{y}=(A*B)*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side dense matrix-matrix multiplication.
+// \param vec The right-hand side dense vector for the multiplication.
+// \return The resulting vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a dense
+// matrix-matrix multiplication expression and a dense vector. It restructures the expression
+// \f$ \vec{x}=(A*B)*\vec{x} \f$ to the expression \f$ \vec{y}=A*(B*\vec{x}) \f$.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense vector
+inline const EnableIf_< IsMatMatMultExpr<T1>, MultExprTrait_<T1,T2> >
+ operator*( const DenseMatrix<T1,SO>& mat, const DenseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( T1 );
+
+ return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct Size< DMatDVecMultExpr<MT,VT> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct IsAligned< DMatDVecMultExpr<MT,VT> >
+ : public BoolConstant< And< IsAligned<MT>, IsAligned<VT> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, bool AF >
+struct SubvectorExprTrait< DMatDVecMultExpr<MT,VT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>
+ , SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatDetExpr.h b/src/cpu/blaze/math/expressions/DMatDetExpr.h
new file mode 100644
index 00000000..7e467240
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatDetExpr.h
@@ -0,0 +1,428 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatDetExpr.h
+// \brief Header file for the dense matrix determinant expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATDETEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATDETEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/getrf.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DETERMINANT FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Determinant functions */
+//@{
+template< typename MT, bool SO >
+inline ElementType_<MT> det( const DenseMatrix<MT,SO>& dm );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Computation of the determinant of the given dense \f$ 2 \times 2 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The determinant of the given matrix.
+//
+// This function computes the determinant of the given dense \f$ 2 \times 2 \f$ matrix via the
+// rule of Sarrus.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline ElementType_<MT> det2x2( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 2UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 2UL, "Invalid number of columns detected" );
+
+ CompositeType_<MT> A( ~dm );
+
+ return A(0,0)*A(1,1) - A(0,1)*A(1,0);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Computation of the determinant of the given dense \f$ 3 \times 3 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The determinant of the given matrix.
+//
+// This function computes the determinant of the given dense \f$ 3 \times 3 \f$ matrix via the
+// rule of Sarrus.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline ElementType_<MT> det3x3( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 3UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 3UL, "Invalid number of columns detected" );
+
+ CompositeType_<MT> A( ~dm );
+
+ return A(0,0) * ( A(1,1)*A(2,2) - A(1,2)*A(2,1) ) +
+ A(0,1) * ( A(1,2)*A(2,0) - A(1,0)*A(2,2) ) +
+ A(0,2) * ( A(1,0)*A(2,1) - A(1,1)*A(2,0) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Computation of the determinant of the given dense \f$ 4 \times 4 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The determinant of the given matrix.
+//
+// This function computes the determinant of the given dense \f$ 4 \times 4 \f$ matrix via the
+// rule of Sarrus.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline ElementType_<MT> det4x4( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 4UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 4UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ CompositeType_<MT> A( ~dm );
+
+ const ET tmp1( A(2,2)*A(3,3) - A(2,3)*A(3,2) );
+ const ET tmp2( A(2,1)*A(3,3) - A(2,3)*A(3,1) );
+ const ET tmp3( A(2,1)*A(3,2) - A(2,2)*A(3,1) );
+ const ET tmp4( A(2,0)*A(3,3) - A(2,3)*A(3,0) );
+ const ET tmp5( A(2,0)*A(3,2) - A(2,2)*A(3,0) );
+ const ET tmp6( A(2,0)*A(3,1) - A(2,1)*A(3,0) );
+
+ return A(0,0) * ( A(1,1) * tmp1 - A(1,2) * tmp2 + A(1,3) * tmp3 ) -
+ A(0,1) * ( A(1,0) * tmp1 - A(1,2) * tmp4 + A(1,3) * tmp5 ) +
+ A(0,2) * ( A(1,0) * tmp2 - A(1,1) * tmp4 + A(1,3) * tmp6 ) -
+ A(0,3) * ( A(1,0) * tmp3 - A(1,1) * tmp5 + A(1,2) * tmp6 );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Computation of the determinant of the given dense \f$ 5 \times 5 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The determinant of the given matrix.
+//
+// This function computes the determinant of the given dense \f$ 5 \times 5 \f$ matrix via the
+// rule of Sarrus.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline ElementType_<MT> det5x5( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 5UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 5UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ CompositeType_<MT> A( ~dm );
+
+ const ET tmp1 ( A(3,3)*A(4,4) - A(3,4)*A(4,3) );
+ const ET tmp2 ( A(3,2)*A(4,4) - A(3,4)*A(4,2) );
+ const ET tmp3 ( A(3,2)*A(4,3) - A(3,3)*A(4,2) );
+ const ET tmp4 ( A(3,1)*A(4,4) - A(3,4)*A(4,1) );
+ const ET tmp5 ( A(3,1)*A(4,3) - A(3,3)*A(4,1) );
+ const ET tmp6 ( A(3,1)*A(4,2) - A(3,2)*A(4,1) );
+ const ET tmp7 ( A(3,0)*A(4,4) - A(3,4)*A(4,0) );
+ const ET tmp8 ( A(3,0)*A(4,3) - A(3,3)*A(4,0) );
+ const ET tmp9 ( A(3,0)*A(4,2) - A(3,2)*A(4,0) );
+ const ET tmp10( A(3,0)*A(4,1) - A(3,1)*A(4,0) );
+
+ const ET tmp11( A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3 );
+ const ET tmp12( A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5 );
+ const ET tmp13( A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6 );
+ const ET tmp14( A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6 );
+ const ET tmp15( A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8 );
+ const ET tmp16( A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9 );
+ const ET tmp17( A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9 );
+ const ET tmp18( A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10 );
+ const ET tmp19( A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10 );
+ const ET tmp20( A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10 );
+
+ return A(0,0) * ( A(1,1)*tmp11 - A(1,2)*tmp12 + A(1,3)*tmp13 - A(1,4)*tmp14 ) -
+ A(0,1) * ( A(1,0)*tmp11 - A(1,2)*tmp15 + A(1,3)*tmp16 - A(1,4)*tmp17 ) +
+ A(0,2) * ( A(1,0)*tmp12 - A(1,1)*tmp15 + A(1,3)*tmp18 - A(1,4)*tmp19 ) -
+ A(0,3) * ( A(1,0)*tmp13 - A(1,1)*tmp16 + A(1,2)*tmp18 - A(1,4)*tmp20 ) +
+ A(0,4) * ( A(1,0)*tmp14 - A(1,1)*tmp17 + A(1,2)*tmp19 - A(1,3)*tmp20 );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Computation of the determinant of the given dense \f$ 6 \times 6 \f$ matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The determinant of the given matrix.
+//
+// This function computes the determinant of the given dense \f$ 6 \times 6 \f$ matrix via the
+// rule of Sarrus.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline ElementType_<MT> det6x6( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_INTERNAL_ASSERT( (~dm).rows() == 6UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~dm).columns() == 6UL, "Invalid number of columns detected" );
+
+ typedef ElementType_<MT> ET;
+
+ CompositeType_<MT> A( ~dm );
+
+ const ET tmp1 ( A(4,4)*A(5,5) - A(4,5)*A(5,4) );
+ const ET tmp2 ( A(4,3)*A(5,5) - A(4,5)*A(5,3) );
+ const ET tmp3 ( A(4,3)*A(5,4) - A(4,4)*A(5,3) );
+ const ET tmp4 ( A(4,2)*A(5,5) - A(4,5)*A(5,2) );
+ const ET tmp5 ( A(4,2)*A(5,4) - A(4,4)*A(5,2) );
+ const ET tmp6 ( A(4,2)*A(5,3) - A(4,3)*A(5,2) );
+ const ET tmp7 ( A(4,1)*A(5,5) - A(4,5)*A(5,1) );
+ const ET tmp8 ( A(4,1)*A(5,4) - A(4,4)*A(5,1) );
+ const ET tmp9 ( A(4,1)*A(5,3) - A(4,3)*A(5,1) );
+ const ET tmp10( A(4,1)*A(5,2) - A(4,2)*A(5,1) );
+ const ET tmp11( A(4,0)*A(5,5) - A(4,5)*A(5,0) );
+ const ET tmp12( A(4,0)*A(5,4) - A(4,4)*A(5,0) );
+ const ET tmp13( A(4,0)*A(5,3) - A(4,3)*A(5,0) );
+ const ET tmp14( A(4,0)*A(5,2) - A(4,2)*A(5,0) );
+ const ET tmp15( A(4,0)*A(5,1) - A(4,1)*A(5,0) );
+
+ const ET tmp16( A(3,3)*tmp1 - A(3,4)*tmp2 + A(3,5)*tmp3 );
+ const ET tmp17( A(3,2)*tmp1 - A(3,4)*tmp4 + A(3,5)*tmp5 );
+ const ET tmp18( A(3,2)*tmp2 - A(3,3)*tmp4 + A(3,5)*tmp6 );
+ const ET tmp19( A(3,2)*tmp3 - A(3,3)*tmp5 + A(3,4)*tmp6 );
+ const ET tmp20( A(3,1)*tmp1 - A(3,4)*tmp7 + A(3,5)*tmp8 );
+ const ET tmp21( A(3,1)*tmp2 - A(3,3)*tmp7 + A(3,5)*tmp9 );
+ const ET tmp22( A(3,1)*tmp3 - A(3,3)*tmp8 + A(3,4)*tmp9 );
+ const ET tmp23( A(3,1)*tmp4 - A(3,2)*tmp7 + A(3,5)*tmp10 );
+ const ET tmp24( A(3,1)*tmp5 - A(3,2)*tmp8 + A(3,4)*tmp10 );
+ const ET tmp25( A(3,1)*tmp6 - A(3,2)*tmp9 + A(3,3)*tmp10 );
+ const ET tmp26( A(3,0)*tmp1 - A(3,4)*tmp11 + A(3,5)*tmp12 );
+ const ET tmp27( A(3,0)*tmp2 - A(3,3)*tmp11 + A(3,5)*tmp13 );
+ const ET tmp28( A(3,0)*tmp3 - A(3,3)*tmp12 + A(3,4)*tmp13 );
+ const ET tmp29( A(3,0)*tmp4 - A(3,2)*tmp11 + A(3,5)*tmp14 );
+ const ET tmp30( A(3,0)*tmp5 - A(3,2)*tmp12 + A(3,4)*tmp14 );
+ const ET tmp31( A(3,0)*tmp6 - A(3,2)*tmp13 + A(3,3)*tmp14 );
+ const ET tmp32( A(3,0)*tmp7 - A(3,1)*tmp11 + A(3,5)*tmp15 );
+ const ET tmp33( A(3,0)*tmp8 - A(3,1)*tmp12 + A(3,4)*tmp15 );
+ const ET tmp34( A(3,0)*tmp9 - A(3,1)*tmp13 + A(3,3)*tmp15 );
+ const ET tmp35( A(3,0)*tmp10 - A(3,1)*tmp14 + A(3,2)*tmp15 );
+
+ const ET tmp36( A(2,2)*tmp16 - A(2,3)*tmp17 + A(2,4)*tmp18 - A(2,5)*tmp19 );
+ const ET tmp37( A(2,1)*tmp16 - A(2,3)*tmp20 + A(2,4)*tmp21 - A(2,5)*tmp22 );
+ const ET tmp38( A(2,1)*tmp17 - A(2,2)*tmp20 + A(2,4)*tmp23 - A(2,5)*tmp24 );
+ const ET tmp39( A(2,1)*tmp18 - A(2,2)*tmp21 + A(2,3)*tmp23 - A(2,5)*tmp25 );
+ const ET tmp40( A(2,1)*tmp19 - A(2,2)*tmp22 + A(2,3)*tmp24 - A(2,4)*tmp25 );
+ const ET tmp41( A(2,0)*tmp16 - A(2,3)*tmp26 + A(2,4)*tmp27 - A(2,5)*tmp28 );
+ const ET tmp42( A(2,0)*tmp17 - A(2,2)*tmp26 + A(2,4)*tmp29 - A(2,5)*tmp30 );
+ const ET tmp43( A(2,0)*tmp18 - A(2,2)*tmp27 + A(2,3)*tmp29 - A(2,5)*tmp31 );
+ const ET tmp44( A(2,0)*tmp19 - A(2,2)*tmp28 + A(2,3)*tmp30 - A(2,4)*tmp31 );
+ const ET tmp45( A(2,0)*tmp20 - A(2,1)*tmp26 + A(2,4)*tmp32 - A(2,5)*tmp33 );
+ const ET tmp46( A(2,0)*tmp21 - A(2,1)*tmp27 + A(2,3)*tmp32 - A(2,5)*tmp34 );
+ const ET tmp47( A(2,0)*tmp22 - A(2,1)*tmp28 + A(2,3)*tmp33 - A(2,4)*tmp34 );
+ const ET tmp48( A(2,0)*tmp23 - A(2,1)*tmp29 + A(2,2)*tmp32 - A(2,5)*tmp35 );
+ const ET tmp49( A(2,0)*tmp24 - A(2,1)*tmp30 + A(2,2)*tmp33 - A(2,4)*tmp35 );
+ const ET tmp50( A(2,0)*tmp25 - A(2,1)*tmp31 + A(2,2)*tmp34 - A(2,3)*tmp35 );
+
+ return A(0,0) * ( A(1,1)*tmp36 - A(1,2)*tmp37 + A(1,3)*tmp38 - A(1,4)*tmp39 + A(1,5)*tmp40 ) -
+ A(0,1) * ( A(1,0)*tmp36 - A(1,2)*tmp41 + A(1,3)*tmp42 - A(1,4)*tmp43 + A(1,5)*tmp44 ) +
+ A(0,2) * ( A(1,0)*tmp37 - A(1,1)*tmp41 + A(1,3)*tmp45 - A(1,4)*tmp46 + A(1,5)*tmp47 ) -
+ A(0,3) * ( A(1,0)*tmp38 - A(1,1)*tmp42 + A(1,2)*tmp45 - A(1,4)*tmp48 + A(1,5)*tmp49 ) +
+ A(0,4) * ( A(1,0)*tmp39 - A(1,1)*tmp43 + A(1,2)*tmp46 - A(1,3)*tmp48 + A(1,5)*tmp50 ) -
+ A(0,5) * ( A(1,0)*tmp40 - A(1,1)*tmp44 + A(1,2)*tmp47 - A(1,3)*tmp49 + A(1,4)*tmp50 );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Computation of the determinant of the given dense square matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The determinant of the given matrix.
+//
+// This function computes the determinant of the given dense square matrix via an LU decomposition
+// of the matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+ElementType_<MT> detNxN( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_INTERNAL_ASSERT( isSquare( ~dm ), "Non-square symmetric matrix detected" );
+
+ typedef ResultType_<MT> RT;
+ typedef ElementType_<MT> ET;
+ typedef RemoveAdaptor_<RT> URT;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( URT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( URT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( URT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ET );
+
+ URT A( ~dm );
+
+ int n ( boost::numeric_cast<int>( A.rows() ) );
+ int lda ( boost::numeric_cast<int>( A.spacing() ) );
+ int info( 0 );
+
+ const std::unique_ptr<int[]> ipiv( new int[n] );
+
+ getrf( n, n, A.data(), lda, ipiv.get(), &info );
+
+ if( info > 0 ) {
+ return ET(0);
+ }
+
+ ET determinant = ET(1);
+
+ for( int i=0; i<n; ++i ) {
+ determinant *= ( ipiv[i] == (i+1) )?( A(i,i) ):( -A(i,i) );
+ }
+
+ return determinant;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computation of the determinant of the given dense square matrix.
+// \ingroup dense_matrix
+//
+// \param dm The given dense matrix.
+// \return The determinant of the given matrix.
+// \exception std::invalid_argument Invalid non-square matrix provided.
+//
+// This function computes the determinant of the given dense square matrix. The computation fails
+// if the given matrix is not a square matrix. In this case either a compilation error is created
+// (if possible) or a \a std::invalid_argument exception is thrown.
+//
+// \note The computation of the determinant is numerically unreliable since especially for large
+// matrices the value can overflow during the computation. Please note that this function does
+// not guarantee that it is possible to compute the determinant with the given matrix!
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline ElementType_<MT> det( const DenseMatrix<MT,SO>& dm )
+{
+ typedef ElementType_<MT> ET;
+
+ if( !isSquare( ~dm ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ const size_t N( (~dm).rows() );
+
+ if( IsStrictlyTriangular<MT>::value || N == 0UL ) {
+ return ET(0);
+ }
+
+ if( IsUniTriangular<MT>::value ) {
+ return ET(1);
+ }
+
+ if( N == 1UL ) {
+ return (~dm)(0,0);
+ }
+
+ if( IsTriangular<MT>::value ) {
+ ET determinant( (~dm)(0,0) );
+
+ for( size_t i=1UL; i<N; ++i ) {
+ determinant *= (~dm)(i,i);
+ }
+
+ return determinant;
+ }
+
+ switch( N ) {
+ case 2UL: return det2x2( ~dm );
+ case 3UL: return det3x3( ~dm );
+ case 4UL: return det4x4( ~dm );
+ case 5UL: return det5x5( ~dm );
+ case 6UL: return det6x6( ~dm );
+ default : return detNxN( ~dm );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatEvalExpr.h b/src/cpu/blaze/math/expressions/DMatEvalExpr.h
new file mode 100644
index 00000000..d504b8f1
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatEvalExpr.h
@@ -0,0 +1,1022 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatEvalExpr.h
+// \brief Header file for the dense matrix evaluation expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATEVALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatEvalExpr.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatEvalExprTrait.h>
+#include <blaze/math/traits/EvalExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatEvalExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATEVALEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the forced evaluation of dense matrices.
+// \ingroup dense_matrix_expression
+//
+// The DMatEvalExpr class represents the compile time expression for the forced evaluation
+// of a dense matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+class DMatEvalExpr : public DenseMatrix< DMatEvalExpr<MT,SO>, SO >
+ , private MatEvalExpr
+ , private Computation
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatEvalExpr<MT,SO> This; //!< Type of this DMatEvalExpr instance.
+ typedef ResultType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatEvalExpr class.
+ //
+ // \param dm The dense matrix operand of the evaluation expression.
+ */
+ explicit inline DMatEvalExpr( const MT& dm ) noexcept
+ : dm_( dm ) // Dense matrix of the evaluation expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < dm_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.columns(), "Invalid column access index" );
+ return dm_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= dm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= dm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return dm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return dm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense matrix operand.
+ //
+ // \return The dense matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return dm_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return dm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return dm_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return dm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dm_; //!< Dense matrix of the evaluation expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix evaluation
+ // expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluatin expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix evaluation
+ // expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( SparseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix
+ // evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( SparseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( SparseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense matrix evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // matrix evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void multAssign( DenseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense matrix evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void multAssign( SparseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAssign( DenseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluatin expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAssign( SparseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix
+ // evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAddAssign( SparseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpSubAssign( SparseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense matrix evaluation expression to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // matrix evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpMultAssign( DenseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpMultAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense matrix evaluation expression to a sparse
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpMultAssign( SparseMatrix<MT2,SO2>& lhs, const DMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpMultAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Forces the evaluation of the given dense matrix expression \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The evaluated dense matrix.
+//
+// The \a eval function forces the evaluation of the given dense matrix expression \a dm.
+// The function returns an expression representing the operation.\n
+// The following example demonstrates the use of the \a eval function
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = eval( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatEvalExpr<MT,SO> eval( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatEvalExpr<MT,SO>( ~dm );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Evaluation of the given dense matrix evaluation expression \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input evaluation expression.
+// \return The evaluated dense matrix.
+//
+// This function implements a performance optimized treatment of the evaluation of a dense matrix
+// evaluation expression.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatEvalExpr<MT,SO> eval( const DMatEvalExpr<MT,SO>& dm )
+{
+ return dm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Rows< DMatEvalExpr<MT,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Columns< DMatEvalExpr<MT,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsAligned< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsLower< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniLower< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUpper< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniUpper< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatEvalExprTrait< DMatEvalExpr<MT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatEvalExpr<MT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatEvalExprTrait< DMatEvalExpr<MT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatEvalExpr<MT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatEvalExpr<MT,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = EvalExprTrait_< SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct RowExprTrait< DMatEvalExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = EvalExprTrait_< RowExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct ColumnExprTrait< DMatEvalExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = EvalExprTrait_< ColumnExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatForEachExpr.h b/src/cpu/blaze/math/expressions/DMatForEachExpr.h
new file mode 100644
index 00000000..e481d2ab
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatForEachExpr.h
@@ -0,0 +1,3080 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatForEachExpr.h
+// \brief Header file for the dense matrix for-each expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATFOREACHEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatForEachExpr.h>
+#include <blaze/math/Functors.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/ForEachExprTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/HasMember.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATFOREACHEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the dense matrix forEach() function.
+// \ingroup dense_matrix_expression
+//
+// The DMatForEachExpr class represents the compile time expression for the evaluation of a
+// custom operation on each element of a dense matrix via the forEach() function.
+*/
+template< typename MT // Type of the dense matrix
+ , typename OP // Type of the custom operation
+ , bool SO > // Storage order
+class DMatForEachExpr : public DenseMatrix< DMatForEachExpr<MT,OP,SO>, SO >
+ , private MatForEachExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the dense matrix expression.
+ typedef OppositeType_<MT> OT; //!< Opposite type of the dense matrix expression.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix expression.
+ typedef ReturnType_<MT> RN; //!< Return type of the dense matrix expression.
+
+ //! Definition of the HasSIMDEnabled type trait.
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasSIMDEnabled, simdEnabled );
+
+ //! Definition of the HasLoad type trait.
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasLoad, load );
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the for-each expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the for-each expression. In case the given dense
+ matrix expression of type \a MT requires an intermediate evaluation, \a useAssign will
+ be set to 1 and the for-each expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to 0 and the expression will be evaluated
+ via the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target matrix or the dense matrix operand is not SMP
+ assignable and the matrix operand requires an intermediate evaluation, \a value is set
+ to 1 and the expression specific evaluation strategy is selected. Otherwise \a value is
+ set to 0 and the default strategy is chosen. */
+ template< typename MT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SIMD support detection**********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the detection of the SIMD capabilities of the given custom operation.
+ struct UseSIMDEnabledFlag {
+ enum : bool { value = OP::BLAZE_TEMPLATE simdEnabled<ET>() };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatForEachExpr<MT,OP,SO> This; //!< Type of this DMatForEachExpr instance.
+ typedef ForEachTrait_<MT,OP> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef decltype( std::declval<OP>()( std::declval<RN>() ) ) ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DMatForEachExpr& > CompositeType;
+
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+
+ //! Data type of the custom unary operation.
+ typedef OP Operation;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense matrix.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the dense matrix expression.
+ typedef ConstIterator_<MT> IteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param it Iterator to the initial matrix element.
+ // \param op The custom unary operation.
+ */
+ explicit inline ConstIterator( IteratorType it, OP op )
+ : it_( it ) // Iterator to the current matrix element
+ , op_( op ) // The custom unary operation
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ it_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ it_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( it_++, op_ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( it_--, op_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return op_( *it_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return op_.load( it_.load() );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return it_ < rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return it_ > rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return it_ <= rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return it_ >= rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.it_ + inc, it.op_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.it_ + inc, it.op_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.it_ - dec, it.op_ );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator to the current matrix element.
+ OP op_; //!< The custom unary operation.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled &&
+ If_< HasSIMDEnabled<OP>, UseSIMDEnabledFlag, HasLoad<OP> >::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatForEachExpr class.
+ //
+ // \param dm The dense matrix operand of the for-each expression.
+ // \param op The custom unary operation.
+ */
+ explicit inline DMatForEachExpr( const MT& dm, OP op ) noexcept
+ : dm_( dm ) // Dense matrix of the for-each expression
+ , op_( op ) // The custom unary operation
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( i < dm_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.columns(), "Invalid column access index" );
+ return op_( dm_(i,j) );
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= dm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= dm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t i, size_t j ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( i < dm_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !SO || ( i % SIMDSIZE == 0UL ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( SO || ( j % SIMDSIZE == 0UL ), "Invalid column access index" );
+ return op_.load( dm_.load(i,j) );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( dm_.begin(i), op_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( dm_.end(i), op_ );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return dm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return dm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense matrix operand.
+ //
+ // \return The dense matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return dm_;
+ }
+ //**********************************************************************************************
+
+ //**Operation access****************************************************************************
+ /*!\brief Returns a copy of the custom operation.
+ //
+ // \return A copy of the custom operation.
+ */
+ inline Operation operation() const {
+ return op_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return IsComputation<MT>::value && dm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return dm_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return dm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dm_; //!< Dense matrix of the for-each expression.
+ Operation op_; //!< The custom unary operation.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix for-each expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix for-each
+ // expression to a dense matrix. Due to the explicit application of the SFINAE principle,
+ // this function can only be selected by the compiler in case the operand requires an
+ // intermediate evaluation and the underlying numeric data type of the operand and the
+ // target matrix are identical.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order or the target dense matrix
+ friend inline EnableIf_< And< UseAssign<MT2>
+ , IsSame< UnderlyingNumeric<MT>, UnderlyingNumeric<MT2> > > >
+ assign( DenseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.dm_ );
+ assign( ~lhs, rhs.op_( ~lhs ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix for-each expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix for-each
+ // expression to a dense matrix. Due to the explicit application of the SFINAE principle,
+ // this function can only be selected by the compiler in case the operand requires an
+ // intermediate evaluation and the underlying numeric data type of the operand and the
+ // target vector differ.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order or the target dense matrix
+ friend inline EnableIf_< And< UseAssign<MT2>
+ , Not< IsSame< UnderlyingNumeric<MT>, UnderlyingNumeric<MT2> > > > >
+ assign( DenseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( serial( rhs.dm_ ) );
+ assign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix for-each expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix for-each
+ // expression to a sparse matrix. Due to the explicit application of the SFINAE principle,
+ // this operator can only be selected by the compiler in case the operand requires an
+ // intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order or the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( SparseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, RT, OT > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT2, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs.dm_ ) );
+ assign( ~lhs, rhs.op_( tmp ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix for-each expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense
+ // matrix for-each expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this operator can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ addAssign( DenseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( serial( rhs.dm_ ) );
+ addAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix for-each expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // matrix for-each expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this operator can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ subAssign( DenseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( serial( rhs.dm_ ) );
+ subAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix for-each expression to a row-major dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // for-each expression to a row-major dense matrix. Due to the explicit application of
+ // the SFINAE principle, this operator can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected and the underlying
+ // numeric data type of the operand and the target matrix are identical.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order or the target dense matrix
+ friend inline EnableIf_< And< UseSMPAssign<MT2>
+ , IsSame< UnderlyingNumeric<MT>, UnderlyingNumeric<MT2> > > >
+ smpAssign( DenseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.dm_ );
+ smpAssign( ~lhs, rhs.op_( ~lhs ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix for-each expression to a row-major dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // for-each expression to a row-major dense matrix. Due to the explicit application of
+ // the SFINAE principle, this operator can only be selected by the compiler in case
+ // the expression specific parallel evaluation strategy is selected and the underlying
+ // numeric data type of the operand and the target vector differ.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order or the target dense matrix
+ friend inline EnableIf_< And< UseSMPAssign<MT2>
+ , Not< IsSame< UnderlyingNumeric<MT>, UnderlyingNumeric<MT2> > > > >
+ smpAssign( DenseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( rhs.dm_ );
+ smpAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix for-each expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // for-each expression to a sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this operator can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order or the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( SparseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, RT, OT > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT2, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs.dm_ );
+ smpAssign( ~lhs, rhs.op_( tmp ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix for-each expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix for-each expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this operator can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( rhs.dm_ );
+ smpAddAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix for-each expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a
+ // dense matrix for-each expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this operator can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const DMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( rhs.dm_ );
+ smpSubAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluates the given custom operation on each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \param op The custom operation.
+// \return The custom operation applied to each single element of \a dm.
+//
+// The \a forEach() function evaluates the given custom operation on each element of the input
+// matrix \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a forEach() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = forEach( A, []( double a ){ return std::sqrt( a ); } );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , typename OP > // Type of the custom operation
+inline const DMatForEachExpr<MT,OP,SO> forEach( const DenseMatrix<MT,SO>& dm, OP op )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,OP,SO>( ~dm, op );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a abs() function to each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The resulting dense matrix.
+//
+// This function applies the \a abs() function to each element of the input matrix \a dm. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a abs() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = abs( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Abs,SO> abs( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Abs,SO>( ~dm, Abs() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a floor() function to each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The resulting dense matrix.
+//
+// This function applies the \a floor() function to each element of the input matrix \a dm. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a floor() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = floor( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Floor,SO> floor( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Floor,SO>( ~dm, Floor() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a ceil() function to each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The resulting dense matrix.
+//
+// This function applies the \a ceil() function to each element of the input matrix \a dm. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a ceil() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = ceil( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Ceil,SO> ceil( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Ceil,SO>( ~dm, Ceil() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a matrix containing the complex conjugate of each single element of \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The conjugate complex of each single element of \a dm.
+//
+// The \a conj function calculates the complex conjugate of each element of the input matrix
+// \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a conj function:
+
+ \code
+ blaze::DynamicMatrix< complex<double> > A, B;
+ // ... Resizing and initialization
+ B = conj( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Conj,SO> conj( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Conj,SO>( ~dm, Conj() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the conjugate transpose matrix of \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The conjugate transpose of \a dm.
+//
+// The \a ctrans function returns an expression representing the conjugate transpose (also called
+// adjoint matrix, Hermitian conjugate matrix or transjugate matrix) of the given input matrix
+// \a dm.\n
+// The following example demonstrates the use of the \a ctrans function:
+
+ \code
+ blaze::DynamicMatrix< complex<double> > A, B;
+ // ... Resizing and initialization
+ B = ctrans( A );
+ \endcode
+
+// Note that the \a ctrans function has the same effect as manually applying the \a conj and
+// \a trans function in any order:
+
+ \code
+ B = trans( conj( A ) ); // Computing the conjugate transpose matrix
+ B = conj( trans( A ) ); // Computing the conjugate transpose matrix
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const CTransExprTrait_<MT> ctrans( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return trans( conj( ~dm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a matrix containing the real part of each single element of \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The real part of each single element of \a dm.
+//
+// The \a real function calculates the real part of each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a real function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = real( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Real,SO> real( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Real,SO>( ~dm, Real() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a matrix containing the imaginary part of each single element of \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The imaginary part of each single element of \a dm.
+//
+// The \a imag function calculates the imaginary part of each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a imag function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = imag( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Imag,SO> imag( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Imag,SO>( ~dm, Imag() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the square root of each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[0..\infty)\f$.
+// \return The square root of each single element of \a dm.
+//
+// The \a sqrt() function computes the square root of each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sqrt() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = sqrt( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Sqrt,SO> sqrt( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Sqrt,SO>( ~dm, Sqrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse square root of each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$(0..\infty)\f$.
+// \return The inverse square root of each single element of \a dm.
+//
+// The \a invsqrt() function computes the inverse square root of each element of the input matrix
+// \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a invsqrt() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = invsqrt( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$(0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,InvSqrt,SO> invsqrt( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,InvSqrt,SO>( ~dm, InvSqrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the cubic root of each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[0..\infty)\f$.
+// \return The cubic root of each single element of \a dm.
+//
+// The \a cbrt() function computes the cubic root of each element of the input matrix \a dm. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cbrt() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = cbrt( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Cbrt,SO> cbrt( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Cbrt,SO>( ~dm, Cbrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cubic root of each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$(0..\infty)\f$.
+// \return The inverse cubic root of each single element of \a dm.
+//
+// The \a invcbrt() function computes the inverse cubic root of each element of the input matrix
+// \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a invcbrt() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = invcbrt( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$(0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,InvCbrt,SO> invcbrt( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,InvCbrt,SO>( ~dm, InvCbrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the exponential value for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \param exp The exponent.
+// \return The exponential value of each single element of \a dm.
+//
+// The \a pow() function computes the exponential value for each element of the input matrix
+// \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a pow() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = pow( A, 4.2 );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , typename ET > // Type of the exponent
+inline const DMatForEachExpr<MT,Pow<ET>,SO> pow( const DenseMatrix<MT,SO>& dm, ET exp )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET );
+
+ return DMatForEachExpr<MT,Pow<ET>,SO>( ~dm, Pow<ET>( exp ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes \f$ e^x \f$ for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The resulting dense matrix.
+//
+// The \a exp() function computes \f$ e^x \f$ for each element of the input matrix \a dm. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a exp() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = exp( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Exp,SO> exp( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Exp,SO>( ~dm, Exp() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the natural logarithm for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[0..\infty)\f$.
+// \return The natural logarithm of each single element of \a dm.
+//
+// The \a log() function computes natural logarithm for each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a log() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = log( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Log,SO> log( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Log,SO>( ~dm, Log() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the common logarithm for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[0..\infty)\f$.
+// \return The common logarithm of each single element of \a dm.
+//
+// The \a log10() function computes common logarithm for each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a log10() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = log10( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Log10,SO> log10( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Log10,SO>( ~dm, Log10() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the sine for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The sine of each single element of \a dm.
+//
+// The \a sin() function computes the sine for each element of the input matrix \a dm. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sin() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = sin( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Sin,SO> sin( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Sin,SO>( ~dm, Sin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse sine for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[-1..1]\f$.
+// \return The inverse sine of each single element of \a dm.
+//
+// The \a asin() function computes the inverse sine for each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a asin() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = asin( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Asin,SO> asin( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Asin,SO>( ~dm, Asin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic sine for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The hyperbolic sine of each single element of \a dm.
+//
+// The \a sinh() function computes the hyperbolic sine for each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sinh() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = sinh( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Sinh,SO> sinh( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Sinh,SO>( ~dm, Sinh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic sine for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The inverse hyperbolic sine of each single element of \a dm.
+//
+// The \a asinh() function computes the inverse hyperbolic sine for each element of the input
+// matrix \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a asinh() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = asinh( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Asinh,SO> asinh( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Asinh,SO>( ~dm, Asinh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the cosine for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The cosine of each single element of \a dm.
+//
+// The \a cos() function computes the cosine for each element of the input matrix \a dm. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cos() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = cos( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Cos,SO> cos( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Cos,SO>( ~dm, Cos() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cosine for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[-1..1]\f$.
+// \return The inverse cosine of each single element of \a dm.
+//
+// The \a acos() function computes the inverse cosine for each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a acos() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = acos( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Acos,SO> acos( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Acos,SO>( ~dm, Acos() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic cosine for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The hyperbolic cosine of each single element of \a dm.
+//
+// The \a cosh() function computes the hyperbolic cosine for each element of the input matrix
+// \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cosh() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = cosh( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Cosh,SO> cosh( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Cosh,SO>( ~dm, Cosh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic cosine for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[1..\infty)\f$.
+// \return The inverse hyperbolic cosine of each single element of \a dm.
+//
+// The \a acosh() function computes the inverse hyperbolic cosine for each element of the input
+// matrix \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a acosh() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = acosh( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[1..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Acosh,SO> acosh( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Acosh,SO>( ~dm, Acosh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the tangent for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The tangent of each single element of \a dm.
+//
+// The \a tan() function computes the tangent for each element of the input matrix \a dm. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a tan() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = tan( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Tan,SO> tan( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Tan,SO>( ~dm, Tan() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse tangent for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The inverse tangent of each single element of \a dm.
+//
+// The \a atan() function computes the inverse tangent for each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a atan() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = atan( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Atan,SO> atan( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Atan,SO>( ~dm, Atan() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic tangent for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[-1..1]\f$.
+// \return The hyperbolic tangent of each single element of \a dm.
+//
+// The \a tanh() function computes the hyperbolic tangent for each element of the input matrix
+// \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a tanh() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = tanh( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Tanh,SO> tanh( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Tanh,SO>( ~dm, Tanh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic tangent for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix; all elements must be in the range \f$[-1..1]\f$.
+// \return The inverse hyperbolic tangent of each single element of \a dm.
+//
+// The \a atanh() function computes the inverse hyperbolic tangent for each element of the input
+// matrix \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a atanh() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = atanh( A );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Atanh,SO> atanh( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Atanh,SO>( ~dm, Atanh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the error function for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The error function of each single element of \a dm.
+//
+// The \a erf() function computes the error function for each element of the input matrix \a dm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a erf() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = erf( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Erf,SO> erf( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Erf,SO>( ~dm, Erf() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the complementary error function for each single element of the dense matrix \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The complementary error function of each single element of \a dm.
+//
+// The \a erfc() function computes the complementary error function for each element of the input
+// matrix \a dm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a erfc() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = erfc( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Erfc,SO> erfc( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatForEachExpr<MT,Erfc,SO>( ~dm, Erfc() );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Absolute value function for absolute value dense matrix expressions.
+// \ingroup dense_matrix
+//
+// \param dm The absolute value dense matrix expression.
+// \return The absolute value of each single element of \a dm.
+//
+// This function implements a performance optimized treatment of the absolute value operation
+// on a dense matrix absolute value expression.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Abs,SO>& abs( const DMatForEachExpr<MT,Abs,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Applies the \a floor() function to a dense matrix \a floor() expressions.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix \a floor() expression.
+// \return The resulting dense matrix.
+//
+// This function implements a performance optimized treatment of the \a floor() operation on
+// a dense matrix \a floor() expression.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Floor,SO>& floor( const DMatForEachExpr<MT,Floor,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Applies the \a ceil() function to a dense matrix \a ceil() expressions.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix \a ceil() expression.
+// \return The resulting dense matrix.
+//
+// This function implements a performance optimized treatment of the \a ceil() operation on
+// a dense matrix \a ceil() expression.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Ceil,SO>& ceil( const DMatForEachExpr<MT,Ceil,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Complex conjugate function for complex conjugate dense matrix expressions.
+// \ingroup dense_matrix
+//
+// \param dm The complex conjugate dense matrix expression.
+// \return The original dense matrix.
+//
+// This function implements a performance optimized treatment of the complex conjugate operation
+// on a dense matrix complex conjugate expression. It returns an expression representing the
+// original dense matrix:
+
+ \code
+ blaze::DynamicMatrix< complex<double> > A, B;
+ // ... Resizing and initialization
+ B = conj( conj( A ) );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline typename DMatForEachExpr<MT,Conj,SO>::Operand conj( const DMatForEachExpr<MT,Conj,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dm.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Complex conjugate function for conjugate transpose dense matrix expressions.
+// \ingroup dense_matrix
+//
+// \param dm The conjugate transpose dense matrix expression.
+// \return The transpose dense matrix.
+//
+// This function implements a performance optimized treatment of the complex conjugate operation
+// on a dense matrix conjugate transpose expression. It returns an expression representing the
+// transpose of the dense matrix:
+
+ \code
+ blaze::DynamicMatrix< complex<double> > A, B;
+ // ... Resizing and initialization
+ B = conj( ctrans( A ) );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatTransExpr<MT,!SO> conj( const DMatTransExpr<DMatForEachExpr<MT,Conj,SO>,!SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatTransExpr<MT,!SO>( dm.operand().operand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Real part function for real part dense matrix expressions.
+// \ingroup dense_matrix
+//
+// \param dm The real part dense matrix expression.
+// \return The real part of each single element of \a dm.
+//
+// This function implements a performance optimized treatment of the real part operation on
+// a dense matrix real part expression.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatForEachExpr<MT,Real,SO>& real( const DMatForEachExpr<MT,Real,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct Rows< DMatForEachExpr<MT,OP,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct Columns< DMatForEachExpr<MT,OP,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct IsAligned< DMatForEachExpr<MT,OP,SO> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct IsPadded< DMatForEachExpr<MT,OP,SO> >
+ : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Abs,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Floor,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Ceil,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Conj,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Real,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Imag,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Sqrt,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,InvSqrt,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Cbrt,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,InvCbrt,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, typename ET, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Pow<ET>,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Exp,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Log,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Log10,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Sin,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Asin,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Sinh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Asinh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Cos,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Acos,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Cosh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Acosh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Tan,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Atan,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Tanh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Atanh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Erf,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< DMatForEachExpr<MT,Erfc,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Abs,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Floor,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Ceil,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Conj,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Real,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Imag,SO> >
+ : public BoolConstant< IsBuiltin< ElementType_<MT> >::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Sqrt,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,InvSqrt,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Cbrt,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,InvCbrt,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, typename ET, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Pow<ET>,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Exp,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Log,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Log10,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Sin,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Asin,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Sinh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Asinh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Cos,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Acos,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Cosh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Acosh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Tan,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Atan,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Tanh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Atanh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Erf,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< DMatForEachExpr<MT,Erfc,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Abs,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Floor,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Ceil,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Conj,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Real,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Imag,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Sin,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Asin,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Sinh,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Asinh,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Tan,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Atan,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Tanh,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Atanh,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsLower< DMatForEachExpr<MT,Erf,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ET, bool SO >
+struct IsUniLower< DMatForEachExpr<MT,Pow<ET>,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Abs,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Floor,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Ceil,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Conj,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Real,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Imag,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Sin,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Asin,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Sinh,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Asinh,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Tan,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Atan,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Tanh,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Atanh,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatForEachExpr<MT,Erf,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Abs,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Floor,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Ceil,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Conj,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Real,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Imag,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Sin,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Asin,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Sinh,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Asinh,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Tan,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Atan,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Tanh,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Atanh,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsUpper< DMatForEachExpr<MT,Erf,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ET, bool SO >
+struct IsUniUpper< DMatForEachExpr<MT,Pow<ET>,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Abs,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Floor,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Ceil,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Conj,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Real,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Imag,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Sin,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Asin,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Sinh,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Asinh,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Tan,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Atan,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Tanh,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Atanh,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatForEachExpr<MT,Erf,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatForEachExprTrait< DMatForEachExpr<MT,Abs,false>, Abs >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatForEachExpr<MT,Abs,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatForEachExprTrait< DMatForEachExpr<MT,Abs,true>, Abs >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatForEachExpr<MT,Abs,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatForEachExprTrait< DMatForEachExpr<MT,Floor,false>, Floor >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatForEachExpr<MT,Floor,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatForEachExprTrait< DMatForEachExpr<MT,Floor,true>, Floor >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatForEachExpr<MT,Floor,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatForEachExprTrait< DMatForEachExpr<MT,Ceil,false>, Ceil >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatForEachExpr<MT,Ceil,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatForEachExprTrait< DMatForEachExpr<MT,Ceil,true>, Ceil >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatForEachExpr<MT,Ceil,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatForEachExprTrait< DMatForEachExpr<MT,Conj,false>, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , Operand_< DMatForEachExpr<MT,Conj,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatForEachExprTrait< DMatForEachExpr<MT,Conj,true>, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , Operand_< DMatForEachExpr<MT,Conj,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatForEachExprTrait< DMatTransExpr< DMatForEachExpr<MT,Conj,true>, false >, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatTransExpr<MT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatForEachExprTrait< DMatTransExpr< DMatForEachExpr<MT,Conj,false>, true >, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatTransExpr<MT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatForEachExprTrait< DMatForEachExpr<MT,Real,false>, Real >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatForEachExpr<MT,Real,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatForEachExprTrait< DMatForEachExpr<MT,Real,true>, Real >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatForEachExpr<MT,Real,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatForEachExpr<MT,OP,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = ForEachExprTrait_< SubmatrixExprTrait_<const MT,AF>, OP >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct RowExprTrait< DMatForEachExpr<MT,OP,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = ForEachExprTrait_< RowExprTrait_<const MT>, OP >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct ColumnExprTrait< DMatForEachExpr<MT,OP,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = ForEachExprTrait_< ColumnExprTrait_<const MT>, OP >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatInvExpr.h b/src/cpu/blaze/math/expressions/DMatInvExpr.h
new file mode 100644
index 00000000..1c652bca
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatInvExpr.h
@@ -0,0 +1,617 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatInvExpr.h
+// \brief Header file for the dense matrix inversion expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATINVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATINVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatInvExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/DMatInvExprTrait.h>
+#include <blaze/math/traits/TDMatInvExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATINVEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix inversions.
+// \ingroup dense_matrix_expression
+//
+// The DMatInvExpr class represents the compile time expression for inversions of dense matrices.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+class DMatInvExpr : public DenseMatrix< DMatInvExpr<MT,SO>, SO >
+ , private MatInvExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the dense matrix expression.
+ typedef CompositeType_<MT> CT; //!< Composite type of the dense matrix expression.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatInvExpr<MT,SO> This; //!< Type of this DMatInvExpr instance.
+ typedef ResultType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatInvExpr class.
+ //
+ // \param dm The dense matrix operand of the inversion expression.
+ */
+ explicit inline DMatInvExpr( const MT& dm ) noexcept
+ : dm_( dm ) // Dense matrix of the inversion expression
+ {}
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return dm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return dm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense matrix operand.
+ //
+ // \return The dense matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return dm_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dm_; //!< Dense matrix of the inversion expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix inversion expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side inversion expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix inversion
+ // expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT2,SO2>& lhs, const DMatInvExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !isSame( ~lhs, rhs.dm_ ) ) {
+ assign( ~lhs, rhs.dm_ );
+ }
+
+ invert( ~lhs );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix inversion expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side inversion expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix inversion
+ // expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT2,SO2>& lhs, const DMatInvExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT2, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix inversion expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side inversion expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix
+ // inversion expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT2,SO2>& lhs, const DMatInvExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix inversion expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side inversion expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix
+ // inversion expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT2,SO2>& lhs, const DMatInvExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Calculation of the inverse of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be inverted.
+// \return The inverse of the matrix.
+//
+// This function returns an expression representing the inverse of the given dense matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, B;
+ // ... Resizing and initialization
+ B = inv( A );
+ \endcode
+
+// \note The matrix inversion can only be used for dense matrices with \c float, \c double,
+// \c complex<float> or \c complex<double> element type. The attempt to call the function with
+// matrices of any other element type results in a compile time error!
+//
+// \note It is not possible to use any kind of view on the expression object returned by the
+// \c inv() function. Also, it is not possible to access individual elements via the function
+// call operator on the expression object:
+
+ \code
+ row( inv( A ), 2UL ); // Compilation error: Views cannot be used on an inv() expression!
+ inv( A )(1,2); // Compilation error: It is not possible to access individual elements!
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatInvExpr<MT,SO> inv( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( !isSquare( ~dm ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ return DMatInvExpr<MT,SO>( ~dm );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating the inverse of a dense matrix inversion.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be (re-)inverted.
+// \return The inverse of the inverted matrix.
+//
+// This function implements a performance optimized treatment of the inversion operation on a
+// dense matrix inversion expression. It returns an expression representing the inverse of a
+// dense matrix inversion:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, B;
+ // ... Resizing and initialization
+ B = inv( inv( A ) );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline typename DMatInvExpr<MT,SO>::Operand inv( const DMatInvExpr<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dm.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Rows< DMatInvExpr<MT,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Columns< DMatInvExpr<MT,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< DMatInvExpr<MT,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< DMatInvExpr<MT,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsLower< DMatInvExpr<MT,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniLower< DMatInvExpr<MT,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUpper< DMatInvExpr<MT,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniUpper< DMatInvExpr<MT,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatInvExprTrait< DMatInvExpr<MT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , Operand_< DMatInvExpr<MT,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatInvExprTrait< DMatInvExpr<MT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , Operand_< DMatInvExpr<MT,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatSMatAddExpr.h b/src/cpu/blaze/math/expressions/DMatSMatAddExpr.h
new file mode 100644
index 00000000..21d767f1
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatSMatAddExpr.h
@@ -0,0 +1,1150 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatSMatAddExpr.h
+// \brief Header file for the dense matrix/sparse matrix addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATSMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATSMATADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-sparse matrix additions.
+// \ingroup dense_matrix_expression
+//
+// The DMatSMatAddExpr class represents the compile time expression for additions between
+// a dense matrix and a sparse matrix with identical storage order.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order
+class DMatSMatAddExpr : public DenseMatrix< DMatSMatAddExpr<MT1,MT2,SO>, SO >
+ , private MatMatAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatSMatAddExpr<MT1,MT2,SO> This; //!< Type of this DMatSMatAddExpr instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatSMatAddExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the addition expression.
+ // \param rhs The right-hand side sparse matrix operand of the addition expression.
+ */
+ explicit inline DMatSMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the addition expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) + rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && lhs_.canAlias( alias ) ) ||
+ ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the addition expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const DMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-sparse matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // matrix addition expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-sparse
+ // matrix addition expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-sparse matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-sparse
+ // matrix addition expression to a sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-sparse matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-sparse matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT1, MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a dense matrix and a sparse matrix
+// (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the addition of a dense matrix and a sparse matrix:
+
+ \code
+ blaze::DynamicMatrix<double> A, C;
+ blaze::CompressedMatrix<double> B;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order
+inline const DMatSMatAddExpr<T1,T2,SO>
+ operator+( const DenseMatrix<T1,SO>& lhs, const SparseMatrix<T2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatSMatAddExpr<T1,T2,SO>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a sparse matrix and a dense matrix
+// (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the addition of a sparse matrix and a dense matrix:
+
+ \code
+ blaze::CompressedMatrix<double> A;
+ blaze::DynamicMatrix<double> B, C;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+inline const DMatSMatAddExpr<T2,T1,SO>
+ operator+( const SparseMatrix<T1,SO>& lhs, const DenseMatrix<T2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatSMatAddExpr<T2,T1,SO>( ~rhs, ~lhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a dense matrix-sparse matrix addition
+// expression and a dense matrix (\f$ A=(B+C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-sparse matrix addition.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a dense
+// matrix-sparse matrix addition expression to a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< DMatSMatAddExpr<T1,T2,SO1>, T3 >
+ operator+( const DMatSMatAddExpr<T1,T2,SO1>& lhs, const DenseMatrix<T3,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() + (~rhs) ) + lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a dense matrix-sparse matrix addition
+// expression and a dense matrix (\f$ A=(B+C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-sparse matrix addition.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a dense
+// matrix-sparse matrix addition expression and a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< DMatSMatAddExpr<T1,T2,SO1>, T3 >
+ operator-( const DMatSMatAddExpr<T1,T2,SO1>& lhs, const DenseMatrix<T3,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() - (~rhs) ) + lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Rows< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Columns< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsSymmetric< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsHermitian< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsLower< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniLower< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< Or< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >
+ , And< IsUniLower<MT2>, IsStrictlyLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyLower< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUpper< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniUpper< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< Or< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >
+ , And< IsUniUpper<MT2>, IsStrictlyUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyUpper< DMatSMatAddExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< DMatSMatAddExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< DMatDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< DMatSMatAddExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix <MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix <MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< DMatTDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatDMatAddExprTrait< DMatSMatAddExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix <MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix <MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< TDMatDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatTDMatAddExprTrait< DMatSMatAddExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix <MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix <MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatTSMatAddExprTrait_< TDMatTDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< DMatSMatAddExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< DMatDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< DMatSMatAddExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< DMatTDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatDMatSubExprTrait< DMatSMatAddExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< TDMatDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatTDMatSubExprTrait< DMatSMatAddExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatTSMatAddExprTrait_< TDMatTDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatSMatAddExpr<MT1,MT2,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct RowExprTrait< DMatSMatAddExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct ColumnExprTrait< DMatSMatAddExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatSMatMultExpr.h b/src/cpu/blaze/math/expressions/DMatSMatMultExpr.h
new file mode 100644
index 00000000..a0574b4c
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatSMatMultExpr.h
@@ -0,0 +1,1766 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatSMatMultExpr.h
+// \brief Header file for the dense matrix/sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SMatSVecMultExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-sparse matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The DMatSMatMultExpr class represents the compile time expression for multiplications between
+// a row-major dense matrix and a row-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class DMatSMatMultExpr : public DenseMatrix< DMatSMatMultExpr<MT1,MT2>, false >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case either of the two matrix operands is symmetric, \a value
+ is set to 1 and an optimized evaluation strategy is selected. Otherwise \a value is
+ set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the element type of the target matrix has a fixed size (i.e. is not resizable),
+ the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ !IsResizable< ElementType_<T1> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the element type of the target matrix is resizable, the nested \value will be set
+ to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatSMatMultExpr<MT1,MT2> This; //!< Type of this DMatSMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatSMatMultExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the multiplication expression.
+ // \param rhs The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_DMATSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-sparse matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a dense matrix-sparse matrix
+ // multiplication to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
+ selectSmallAssignKernel( C, A, B );
+ else
+ selectLargeAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense matrix-sparse matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a dense matrix-sparse matrix
+ // multiplication expression to a dense matrix. This assign function is used in case
+ // the element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ reset( C );
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ if( IsDiagonal<MT4>::value )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ for( ; element!=end; ++element ) {
+ C(j,element->index()) = A(j,j) * element->value();
+ }
+ }
+ else
+ {
+ const size_t iibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iiend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
+
+ for( size_t ii=iibegin; ii<iiend; ii+=8UL )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+ const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
+
+ for( ; element!=end; ++element ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ if( isDefault( C(i,element->index()) ) )
+ C(i,element->index()) = A(i,j) * element->value();
+ else
+ C(i,element->index()) += A(i,j) * element->value();
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small dense matrix-sparse matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices (small matrices)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a small dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // matrix multiplication expression to a dense matrix. This assign function is used in case
+ // the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ reset( C );
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ const size_t iibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iiend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
+
+ for( size_t ii=iibegin; ii<iiend; ii+=8UL )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+ const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
+
+ for( ; element!=end; ++element ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ C(i,element->index()) += A(i,j) * element->value();
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large dense matrix-sparse matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices (large matrices)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // matrix multiplication expression to a dense matrix. This assign function is used in case
+ // the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( C, A * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-sparse matrix multiplication to a sparse matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a dense matrix-
+ // sparse matrix multiplication expression. Due to the explicit application of the SFINAE
+ // principle this function can only be selected by the compiler in case the symmetry of
+ // either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-sparse matrix multiplication to a dense matrix
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a dense matrix-sparse matrix
+ // multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
+ selectSmallAddAssignKernel( C, A, B );
+ else
+ selectLargeAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices (small matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a small dense matrix-sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ if( IsDiagonal<MT4>::value )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ for( ; element!=end; ++element ) {
+ C(j,element->index()) += A(j,j) * element->value();
+ }
+ }
+ else
+ {
+ const size_t iibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iiend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
+
+ for( size_t ii=iibegin; ii<iiend; ii+=8UL )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+ const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
+
+ for( ; element!=end; ++element ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ C(i,element->index()) += A(i,j) * element->value();
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices (large matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large dense matrix-sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( C, A * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a dense matrix-sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a dense
+ // matrix-sparse matrix multiplication expression. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case the symmetry
+ // of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-sparse matrix multiplication to a dense
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a dense matrix-sparse matrix
+ // multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
+ selectSmallSubAssignKernel( C, A, B );
+ else
+ selectLargeSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices (small matrices)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a small dense matrix-sparse matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // sparse matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ if( IsDiagonal<MT4>::value )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ for( ; element!=end; ++element ) {
+ C(j,element->index()) -= A(j,j) * element->value();
+ }
+ }
+ else
+ {
+ const size_t iibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iiend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
+
+ for( size_t ii=iibegin; ii<iiend; ii+=8UL )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+ const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
+
+ for( ; element!=end; ++element ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ C(i,element->index()) -= A(i,j) * element->value();
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices (large matrices)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large dense matrix-sparse matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // sparse matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( C, A * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a dense matrix-sparse matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // dense matrix-sparse matrix multiplication expression. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case the
+ // symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-sparse matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-sparse
+ // matrix multiplication expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-sparse matrix multiplication to a sparse matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-sparse
+ // matrix multiplication expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a dense matrix-
+ // sparse matrix multiplication expression. Due to the explicit application of the SFINAE
+ // principle this function can only be selected by the compiler in case the symmetry of either
+ // of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-sparse matrix multiplication to a dense
+ // matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix-
+ // sparse matrix multiplication expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either of
+ // the two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a dense matrix-sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // dense matrix-sparse matrix multiplication expression. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case the
+ // symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-sparse matrix multiplication to a dense
+ // matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-sparse matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a dense matrix-sparse matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of
+ // a dense matrix-sparse matrix multiplication expression. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case the
+ // symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major dense matrix and a
+// row-major sparse matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the multiplication.
+// \param rhs The right-hand side sparse matrix for the multiplication.
+// \return The resulting matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the multiplication of a row-major dense matrix and a row-major
+// sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,rowMajor> B;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const DMatSMatMultExpr<T1,T2>
+ operator*( const DenseMatrix<T1,false>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< DMatSMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< DMatSMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< DMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsAligned<MT1>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< DMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< DMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< DMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< DMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< DMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< DMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatDVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , DMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatSVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , DMatSVecMultExprTrait_< MT1, SMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecSMatMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecSMatMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< DMatSMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< DMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< DMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatSMatSubExpr.h b/src/cpu/blaze/math/expressions/DMatSMatSubExpr.h
new file mode 100644
index 00000000..a7517bab
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatSMatSubExpr.h
@@ -0,0 +1,1107 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatSMatSubExpr.h
+// \brief Header file for the dense matrix/sparse matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATSMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATSMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-sparse matrix subtractions.
+// \ingroup dense_matrix_expression
+//
+// The DMatSMatSubExpr class represents the compile time expression for subtractions between
+// a dense matrix and a sparse matrix with identical storage order.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order
+class DMatSMatSubExpr : public DenseMatrix< DMatSMatSubExpr<MT1,MT2,SO>, SO >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatSMatSubExpr<MT1,MT2,SO> This; //!< Type of this DMatSMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatSMatSubExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the subtraction expression.
+ // \param rhs The right-hand side sparse matrix operand of the subtraction expression.
+ */
+ explicit inline DMatSMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && lhs_.canAlias( alias ) ) ||
+ ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const DMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-sparse matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // matrix subtraction expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-sparse
+ // matrix subtraction expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-sparse matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-sparse
+ // matrix subtraction expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix-
+ // sparse matrix subtraction expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-sparse matrix subtraction expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices************************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT1, MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a dense matrix and a sparse matrix with
+// identical storage order (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side sparse matrix to be subtracted from the dense matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the subtraction of a dense matrix and a sparse matrix with identical
+// storage order:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,rowMajor> B;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order
+inline const DMatSMatSubExpr<T1,T2,SO>
+ operator-( const DenseMatrix<T1,SO>& lhs, const SparseMatrix<T2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatSMatSubExpr<T1,T2,SO>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a dense matrix-sparse matrix subtraction
+// expression and a dense matrix (\f$ A=(B-C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-sparse matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a dense
+// matrix-sparse matrix subtraction expression to a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< DMatSMatSubExpr<T1,T2,SO1>, T3 >
+ operator+( const DMatSMatSubExpr<T1,T2,SO1>& lhs, const DenseMatrix<T3,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() + (~rhs) ) - lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a dense matrix-sparse matrix subtraction
+// expression and a dense matrix (\f$ A=(B-C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-sparse matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a dense
+// matrix-sparse matrix subtraction expression and a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< DMatSMatSubExpr<T1,T2,SO1>, T3 >
+ operator-( const DMatSMatSubExpr<T1,T2,SO1>& lhs, const DenseMatrix<T3,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() - (~rhs) ) - lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Rows< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Columns< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsSymmetric< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsHermitian< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsLower< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniLower< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyLower< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUpper< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniUpper< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyUpper< DMatSMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< DMatSMatSubExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatSubExprTrait_< DMatDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< DMatSMatSubExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatSMatSubExprTrait_< DMatTDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatDMatAddExprTrait< DMatSMatSubExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatSubExprTrait_< TDMatDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatTDMatAddExprTrait< DMatSMatSubExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatTSMatSubExprTrait_< TDMatTDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< DMatSMatSubExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatSubExprTrait_< DMatDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< DMatSMatSubExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatSMatSubExprTrait_< DMatTDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatDMatSubExprTrait< DMatSMatSubExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatSubExprTrait_< TDMatDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatTDMatSubExprTrait< DMatSMatSubExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatTSMatSubExprTrait_< TDMatTDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatSMatSubExpr<MT1,MT2,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct RowExprTrait< DMatSMatSubExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct ColumnExprTrait< DMatSMatSubExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatSVecMultExpr.h b/src/cpu/blaze/math/expressions/DMatSVecMultExpr.h
new file mode 100644
index 00000000..9aaaae4a
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatSVecMultExpr.h
@@ -0,0 +1,1031 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatSVecMultExpr.h
+// \brief Header file for the dense matrix/sparse vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATSVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-sparse vector multiplications.
+// \ingroup dense_vector_expression
+//
+// The DMatSVecMultExpr class represents the compile time expression for multiplications
+// between row-major dense matrices and sparse vectors.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename VT > // Type of the right-hand side sparse vector
+class DMatSVecMultExpr : public DenseVector< DMatSVecMultExpr<MT,VT>, false >
+ , private MatVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side sparse vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the multiplication expression. In case either the matrix or
+ the vector operand requires an intermediate evaluation or the sparse vector expression
+ is a compound expression, \a useAssign will be set to \a true and the multiplication
+ expression will be evaluated via the \a assign function family. Otherwise \a useAssign
+ will be set to \a false and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = evaluateMatrix || evaluateVector };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatSVecMultExpr<MT,VT> This; //!< Type of this DMatSVecMultExpr instance.
+ typedef MultTrait_<MRT,VRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DMatSVecMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatSVecMultExpr class.
+ //
+ // \param mat The left-hand side dense matrix operand of the multiplication expression.
+ // \param vec The right-hand side sparse vector operand of the multiplication expression.
+ */
+ explicit inline DMatSVecMultExpr( const MT& mat, const VT& vec ) noexcept
+ : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
+ , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return mat_(index,index) * vec_[index];
+ }
+ else if( IsLower<MT>::value )
+ {
+ const size_t n( IsStrictlyLower<MT>::value ? index : index+1UL );
+ return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n );
+ }
+ else if( IsUpper<MT>::value )
+ {
+ const size_t begin( IsStrictlyUpper<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.columns() - begin );
+ return subvector( row( mat_, index ), begin, n ) * subvector( vec_, begin, n );
+ }
+ else
+ {
+ return row( mat_, index ) * vec_;
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the given alias is contained in this expression, \a false if not.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return mat_.isAliased( alias ) || vec_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the given alias is contained in this expression, \a false if not.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return mat_.isAliased( alias ) || vec_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return mat_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_DMATSVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand mat_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand vec_; //!< Right-hand side sparse vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-sparse vector multiplication to a dense vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // vector multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ assign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ assign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-sparse vector multiplication to a sparse vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-sparse
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ assign( SparseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-sparse vector multiplication to a dense vector
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // sparse vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ addAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ addAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-sparse vector multiplication to a dense
+ // vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // sparse vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ subAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ subAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense matrix-sparse vector multiplication to a dense
+ // vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either the left-hand side matrix operand requires an intermediate evaluation or
+ // the right-hand side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ multAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense matrix-sparse vector multiplication to a dense vector
+ // (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisior.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense matrix-
+ // sparse vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ divAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-sparse vector multiplication to a dense vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-sparse
+ // vector multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ smpAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-sparse vector multiplication to a sparse vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-sparse
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-sparse vector multiplication to a dense
+ // vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ smpAddAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-sparse vector multiplication to a dense
+ // vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ smpSubAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense matrix-sparse vector multiplication to a
+ // dense vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of
+ // a dense matrix-sparse vector multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP dvision assignment of a dense matrix-sparse vector multiplication to a dense
+ // vector (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense
+ // matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR( MT, VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major dense matrix and a sparse
+// vector (\f$ \vec{y}=A*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side row-major dense matrix for the multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator represents the multiplication between a row-major dense matrix and a sparse
+// vector:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ blaze::DynamicMatrix<double,rowMajor> A;
+ blaze::CompressedVector<double,columnVector> x;
+ blaze::DynamicVector<double,columnVector> y;
+ // ... Resizing and initialization
+ y = A * x;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both the
+// dense matrix type \a T1 and the sparse vector type \a T2 as well as the two element types
+// \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of columns
+// of the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const DisableIf_< Or< IsSymmetric<T1>, IsMatMatMultExpr<T1> >
+ , DMatSVecMultExpr<T1,T2> >
+ operator*( const DenseMatrix<T1,false>& mat, const SparseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return DMatSVecMultExpr<T1,T2>( ~mat, ~vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a symmetric row-major dense matrix
+// and a sparse vector (\f$ \vec{y}=A*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side row-major dense matrix for the multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// symmetric row-major dense matrix and a sparse vector. It restructures the expression
+// \f$ \vec{y}=A*\vec{x} \f$ to the expression \f$ \vec{y}=A^T*\vec{x} \f$.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const EnableIf_< IsSymmetric<T1>, MultExprTrait_<T1,T2> >
+ operator*( const DenseMatrix<T1,false>& mat, const SparseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATMULTEXPR_TYPE( T1 );
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return trans( ~mat ) * (~vec);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-matrix
+// multiplication expression and a sparse vector (\f$ \vec{y}=(A*B)*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side dense matrix-matrix multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The resulting vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a dense
+// matrix-matrix multiplication expression and a sparse vector. It restructures the expression
+// \f$ \vec{y}=(A*B)*\vec{x} \f$ to the expression \f$ \vec{y}=A*(B*\vec{x}) \f$.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const EnableIf_< IsMatMatMultExpr<T1>, MultExprTrait_<T1,T2> >
+ operator*( const DenseMatrix<T1,SO>& mat, const SparseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( T1 );
+
+ return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct Size< DMatSVecMultExpr<MT,VT> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct IsAligned< DMatSVecMultExpr<MT,VT> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, bool AF >
+struct SubvectorExprTrait< DMatSVecMultExpr<MT,VT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>
+ , SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatScalarDivExpr.h b/src/cpu/blaze/math/expressions/DMatScalarDivExpr.h
new file mode 100644
index 00000000..04a4946b
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatScalarDivExpr.h
@@ -0,0 +1,1398 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatScalarDivExpr.h
+// \brief Header file for the dense matrix/scalar division expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATSCALARDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatScalarDivExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMultExpr.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATSCALARDIVEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for divisions of a dense matrix by a scalar.
+// \ingroup dense_matrix_expression
+//
+// The DMatScalarDivExpr class represents the compile time expression for divisions of dense
+// matrices and by scalar values.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST // Type of the right-hand side scalar value
+ , bool SO > // Storage order
+class DMatScalarDivExpr : public DenseMatrix< DMatScalarDivExpr<MT,ST,SO>, SO >
+ , private MatScalarDivExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the dense matrix expression.
+ typedef ReturnType_<MT> RN; //!< Return type of the dense matrix expression.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix expression.
+ typedef CompositeType_<MT> CT; //!< Composite type of the dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If the matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef DivExprTrait_<RN,ST> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the division expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the division expression. In case the given dense
+ matrix expression of type \a MT is a computation expression and requires an intermediate
+ evaluation, \a useAssign will be set to 1 and the division expression will be evaluated
+ via the \a assign function family. Otherwise \a useAssign will be set to 0 and the
+ expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = IsComputation<MT>::value && RequiresEvaluation<MT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target matrix or the dense matrix operand is not SMP assignable
+ and the matrix operand is a computation expression that requires an intermediate evaluation,
+ \a value is set to 1 and the expression specific evaluation strategy is selected. Otherwise
+ \a value is set to 0 and the default strategy is chosen. */
+ template< typename MT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatScalarDivExpr<MT,ST,SO> This; //!< Type of this DMatScalarDivExpr instance.
+ typedef DivTrait_<RT,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DMatScalarDivExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense matrix.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the dense matrix expression.
+ typedef ConstIterator_<MT> IteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ // \param scalar Scalar of the multiplication expression.
+ */
+ explicit inline ConstIterator( IteratorType iterator, RightOperand scalar )
+ : iterator_( iterator ) // Iterator to the current element
+ , scalar_ ( scalar ) // Scalar of the multiplication expression
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( iterator_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( iterator_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return *iterator_ / scalar_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return iterator_.load() / set( scalar_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.iterator_ + inc, it.scalar_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.iterator_ + inc, it.scalar_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.iterator_ - dec, it.scalar_ );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current element.
+ RightOperand scalar_; //!< Scalar of the multiplication expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled &&
+ IsNumeric<ET>::value &&
+ ( HasSIMDDiv<ET,ST>::value ||
+ HasSIMDDiv<UnderlyingElement_<ET>,ST>::value ) };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatScalarDivExpr class.
+ //
+ // \param matrix The left-hand side dense matrix of the division expression.
+ // \param scalar The right-hand side scalar of the division expression.
+ */
+ explicit inline DMatScalarDivExpr( const MT& matrix, ST scalar ) noexcept
+ : matrix_( matrix ) // Left-hand side dense matrix of the division expression
+ , scalar_( scalar ) // Right-hand side scalar of the division expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ return matrix_(i,j) / scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= matrix_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= matrix_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t i, size_t j ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !SO || ( i % SIMDSIZE == 0UL ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( SO || ( j % SIMDSIZE == 0UL ), "Invalid column access index" );
+ return matrix_.load(i,j) / set( scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( matrix_.begin(i), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( matrix_.end(i), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return matrix_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return matrix_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return matrix_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return IsComputation<MT>::value && matrix_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return matrix_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return matrix_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return matrix_.canSMPAssign() ||
+ ( ( ( SO == rowMajor ) ? rows() : columns() ) > SMP_DMATSCALARMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand matrix_; //!< Left-hand side dense matrix of the division expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the division expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-scalar division to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-scalar
+ // division expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the matrix
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.matrix_ );
+ assign( ~lhs, (~lhs) / rhs.scalar_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-scalar division to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-scalar
+ // division expression to a sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the matrix
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( SparseMatrix<MT2,SO2>& lhs, const DMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.matrix_ );
+ (~lhs) /= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-scalar division to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // scalar division expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the matrix
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ addAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-scalar division to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // scalar division expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the matrix operand is
+ // a computation expression and requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ subAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-scalar division to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-scalar
+ // division expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.matrix_ );
+ smpAssign( ~lhs, (~lhs) / rhs.scalar_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-scalar division to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-scalar
+ // division expression to a sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( SparseMatrix<MT2,SO2>& lhs, const DMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.matrix_ );
+ (~lhs) /= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-scalar division to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-scalar division expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-scalar division to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-scalar division expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ElementType );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division operator for the division of a dense matrix by a scalar value (\f$ A=B/s \f$).
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side dense matrix for the division.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result matrix.
+//
+// This operator represents the division of a dense matrix by a scalar value:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = A / 0.24;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the involved data types \a T1::ElementType and \a T2. Note that this operator only
+// works for scalar values of built-in data type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<T2>, DivExprTrait_<T1,T2> >
+ operator/( const DenseMatrix<T1,SO>& mat, T2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_USER_ASSERT( scalar != T2(0), "Division by zero detected" );
+
+ typedef DivExprTrait_<T1,T2> ReturnType;
+ typedef RightOperand_<ReturnType> ScalarType;
+
+ if( IsMultExpr<ReturnType>::value ) {
+ return ReturnType( ~mat, ScalarType(1)/ScalarType(scalar) );
+ }
+ else {
+ return ReturnType( ~mat, scalar );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar division
+// expression and a scalar value (\f$ A=(B/s1)*s2 \f$).
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side dense matrix-scalar division.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// dense matrix-scalar division expression and a scalar value.
+*/
+template< typename MT // Type of the dense matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the dense matrix
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< And< IsNumeric<ST2>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , MultExprTrait_< DMatScalarDivExpr<MT,ST1,SO>, ST2 > >
+ operator*( const DMatScalarDivExpr<MT,ST1,SO>& mat, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( scalar / mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a scalar value and a dense matrix-
+// scalar division expression (\f$ A=s2*(B/s1) \f$).
+// \ingroup dense_matrix
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param mat The right-hand side dense matrix-scalar division.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// scalar value and a dense matrix-scalar division expression.
+*/
+template< typename ST1 // Type of the left-hand side scalar
+ , typename MT // Type of the dense matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the dense matrix
+inline const EnableIf_< And< IsNumeric<ST1>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , MultExprTrait_< ST1, DMatScalarDivExpr<MT,ST2,SO> > >
+ operator*( ST1 scalar, const DMatScalarDivExpr<MT,ST2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( scalar / mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division operator for the division of a dense matrix-scalar division expression
+// and a scalar value (\f$ A=(B/s1)/s2 \f$).
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side dense matrix-scalar division.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the division of a dense
+// matrix-scalar division expression and a scalar value.
+*/
+template< typename MT // Type of the dense matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the dense matrix
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<ST2>
+ , DivExprTrait_< MT, MultTrait_<ST1,ST2> > >
+ operator/( const DMatScalarDivExpr<MT,ST1,SO>& mat, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" );
+
+ typedef MultTrait_<ST1,ST2> MultType;
+ typedef DivExprTrait_<MT,MultType> ReturnType;
+ typedef RightOperand_<ReturnType> ScalarType;
+
+ if( IsMultExpr<ReturnType>::value ) {
+ return ReturnType( mat.leftOperand(), ScalarType(1)/( mat.rightOperand() * scalar ) );
+ }
+ else {
+ return ReturnType( mat.leftOperand(), mat.rightOperand() * scalar );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct Rows< DMatScalarDivExpr<MT,ST,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct Columns< DMatScalarDivExpr<MT,ST,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsAligned< DMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsPadded< DMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsSymmetric< DMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsHermitian< DMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsLower< DMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsStrictlyLower< DMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsUpper< DMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsStrictlyUpper< DMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct DMatScalarMultExprTrait< DMatScalarDivExpr<MT,ST1,false>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ typedef DivTrait_<ST2,ST1> ScalarType;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>, IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , DMatScalarMultExprTrait_<MT,ScalarType>
+ , DMatScalarMultExpr< DMatScalarDivExpr<MT,ST1,false>, ST2, false > >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct TDMatScalarMultExprTrait< DMatScalarDivExpr<MT,ST1,true>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ typedef DivTrait_<ST2,ST1> ScalarType;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>, IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , DMatScalarMultExprTrait_<MT,ScalarType>
+ , DMatScalarMultExpr< DMatScalarDivExpr<MT,ST1,true>, ST2, true > >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatScalarDivExpr<MT,ST,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< SubmatrixExprTrait_<const MT,AF>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct RowExprTrait< DMatScalarDivExpr<MT,ST,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< RowExprTrait_<const MT>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct ColumnExprTrait< DMatScalarDivExpr<MT,ST,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< ColumnExprTrait_<const MT>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatScalarMultExpr.h b/src/cpu/blaze/math/expressions/DMatScalarMultExpr.h
new file mode 100644
index 00000000..da4fe600
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatScalarMultExpr.h
@@ -0,0 +1,2943 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatScalarMultExpr.h
+// \brief Header file for the dense matrix/scalar multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATSCALARMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatScalarMultExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingElement.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATSCALARMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-scalar multiplications.
+// \ingroup dense_matrix_expression
+//
+// The DMatScalarMultExpr class represents the compile time expression for multiplications between
+// a dense matrix and a scalar value.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST // Type of the right-hand side scalar value
+ , bool SO > // Storage order
+class DMatScalarMultExpr : public DenseMatrix< DMatScalarMultExpr<MT,ST,SO>, SO >
+ , private MatScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the dense matrix expression.
+ typedef ReturnType_<MT> RN; //!< Return type of the dense matrix expression.
+ typedef ElementType_<MT> ET; //!< Element type of the dense matrix expression.
+ typedef CompositeType_<MT> CT; //!< Composite type of the dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If the matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN,ST> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the multiplication expression. In case the given dense
+ matrix expression of type \a MT is a computation expression and requires an intermediate
+ evaluation, \a useAssign will be set to 1 and the multiplication expression will be
+ evaluated via the \a assign function family. Otherwise \a useAssign will be set to 0
+ and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = IsComputation<MT>::value && RequiresEvaluation<MT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target matrix or the dense matrix operand is not SMP assignable
+ and the matrix operand is a computation expression that requires an intermediate evaluation,
+ \a value is set to 1 and the expression specific evaluation strategy is selected. Otherwise
+ \a value is set to 0 and the default strategy is chosen. */
+ template< typename MT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatScalarMultExpr<MT,ST,SO> This; //!< Type of this DMatScalarMultExpr instance.
+ typedef MultTrait_<RT,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DMatScalarMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense matrix.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the dense matrix expression.
+ typedef ConstIterator_<MT> IteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ // \param scalar Scalar of the multiplication expression.
+ */
+ explicit inline ConstIterator( IteratorType iterator, RightOperand scalar )
+ : iterator_( iterator ) // Iterator to the current element
+ , scalar_ ( scalar ) // Scalar of the multiplication expression
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( iterator_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( iterator_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return *iterator_ * scalar_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return iterator_.load() * set( scalar_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.iterator_ + inc, it.scalar_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.iterator_ + inc, it.scalar_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.iterator_ - dec, it.scalar_ );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current element.
+ RightOperand scalar_; //!< Scalar of the multiplication expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled &&
+ IsNumeric<ET>::value &&
+ ( HasSIMDMult<ET,ST>::value ||
+ HasSIMDMult<UnderlyingElement_<ET>,ST>::value ) };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatScalarMultExpr class.
+ //
+ // \param matrix The left-hand side dense matrix of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DMatScalarMultExpr( const MT& matrix, ST scalar ) noexcept
+ : matrix_( matrix ) // Left-hand side dense matrix of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ return matrix_(i,j) * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= matrix_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= matrix_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t i, size_t j ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !SO || ( i % SIMDSIZE == 0UL ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( SO || ( j % SIMDSIZE == 0UL ), "Invalid column access index" );
+ return matrix_.load(i,j) * set( scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( matrix_.begin(i), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( matrix_.end(i), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return matrix_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return matrix_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return matrix_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return IsComputation<MT>::value && matrix_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return matrix_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return matrix_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return matrix_.canSMPAssign() ||
+ ( ( ( SO == rowMajor ) ? rows() : columns() ) > SMP_DMATSCALARMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand matrix_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-scalar multiplication to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-scalar
+ // multiplication expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the matrix
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.matrix_ );
+ assign( ~lhs, (~lhs) * rhs.scalar_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-scalar multiplication to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-scalar
+ // multiplication expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the matrix
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( SparseMatrix<MT2,SO2>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.matrix_ );
+ (~lhs) *= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-scalar multiplication to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // scalar multiplication expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // matrix operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ addAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-scalar multiplication to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // scalar multiplication expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the matrix
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ subAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-scalar multiplication to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-scalar
+ // multiplication expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.matrix_ );
+ smpAssign( ~lhs, (~lhs) * rhs.scalar_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-scalar multiplication to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-scalar
+ // multiplication expression to a sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( SparseMatrix<MT2,SO2>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.matrix_ );
+ (~lhs) *= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-scalar multiplication to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-scalar multiplication expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-scalar multiplication to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-scalar multiplication expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL UNARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unary minus operator for the negation of a dense matrix (\f$ A = -B \f$).
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be negated.
+// \return The negation of the matrix.
+//
+// This operator represents the negation of a dense matrix:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = -A;
+ \endcode
+
+// The operator returns an expression representing the negation of the given dense matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatScalarMultExpr<MT,UnderlyingBuiltin_<MT>,SO>
+ operator-( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef UnderlyingBuiltin_<MT> ElementType;
+ return DMatScalarMultExpr<MT,ElementType,SO>( ~dm, ElementType(-1) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a dense matrix and a scalar value
+// (\f$ A=B*s \f$).
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side dense matrix for the multiplication.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result matrix.
+//
+// This operator represents the multiplication between a dense matrix and a scalar value:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = A * 1.25;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the involved data types \a T1::ElementType and \a T2. Note that this operator only
+// works for scalar values of built-in data type.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<T2>, MultExprTrait_<T1,T2> >
+ operator*( const DenseMatrix<T1,SO>& mat, T2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return MultExprTrait_<T1,T2>( ~mat, scalar );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a scalar value and a dense matrix
+// (\f$ A=s*B \f$).
+// \ingroup dense_matrix
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param mat The right-hand side dense matrix for the multiplication.
+// \return The scaled result matrix.
+//
+// This operator represents the multiplication between a a scalar value and dense matrix:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = 1.25 * A;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the involved data types \a T1 and \a T2::ElementType. Note that this operator only
+// works for scalar values of built-in data type.
+*/
+template< typename T1 // Type of the left-hand side scalar
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const EnableIf_< IsNumeric<T1>, MultExprTrait_<T1,T2> >
+ operator*( T1 scalar, const DenseMatrix<T2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return MultExprTrait_<T1,T2>( ~mat, scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING UNARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unary minus operator for the negation of a dense matrix-scalar multiplication
+// (\f$ A = -(B*s) \f$).
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix-scalar multiplication to be negated.
+// \return The negation of the dense matrix-scalar multiplication.
+//
+// This operator implements a performance optimized treatment of the negation of a dense matrix-
+// scalar multiplication expression.
+*/
+template< typename VT // Type of the dense matrix
+ , typename ST // Type of the scalar
+ , bool TF > // Transpose flag
+inline const DMatScalarMultExpr<VT,ST,TF>
+ operator-( const DMatScalarMultExpr<VT,ST,TF>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatScalarMultExpr<VT,ST,TF>( dm.leftOperand(), -dm.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar multiplication
+// expression and a scalar value (\f$ A=(B*s1)*s2 \f$).
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side dense matrix-scalar multiplication.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// dense matrix-scalar multiplication expression and a scalar value.
+*/
+template< typename MT // Type of the dense matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the dense matrix
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<ST2>, MultExprTrait_< DMatScalarMultExpr<MT,ST1,SO>, ST2 > >
+ operator*( const DMatScalarMultExpr<MT,ST1,SO>& mat, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( mat.rightOperand() * scalar );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a scalar value and a dense matrix-
+// scalar multiplication expression (\f$ A=s2*(B*s1) \f$).
+// \ingroup dense_matrix
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param mat The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// scalar value and a dense matrix-scalar multiplication expression.
+*/
+template< typename ST1 // Type of the left-hand side scalar
+ , typename MT // Type of the dense matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the dense matrix
+inline const EnableIf_< IsNumeric<ST1>, MultExprTrait_< ST1, DMatScalarMultExpr<MT,ST2,SO> > >
+ operator*( ST1 scalar, const DMatScalarMultExpr<MT,ST2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( scalar * mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division operator for the division of a dense matrix-scalar multiplication
+// expression by a scalar value (\f$ A=(B*s1)/s2 \f$).
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side dense matrix-scalar multiplication.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the division of a
+// dense matrix-scalar multiplication expression by a scalar value.
+*/
+template< typename MT // Type of the dense matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the dense matrix
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< And< IsNumeric<ST2>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , DivExprTrait_< DMatScalarMultExpr<MT,ST1,SO>, ST2 > >
+ operator/( const DMatScalarMultExpr<MT,ST1,SO>& mat, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( mat.rightOperand() / scalar );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar
+// multiplication expression and a dense vector (\f$ \vec{a}=(B*s1)*\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side dense matrix-scalar multiplication.
+// \param vec The right-hand side dense vector.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense matrix-scalar multiplication and a dense vector. It restructures the expression
+// \f$ \vec{a}=(B*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
+*/
+template< typename MT // Type of the dense matrix of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the left-hand side expression
+ , typename VT > // Type of the right-hand side dense vector
+inline const MultExprTrait_< DMatScalarMultExpr<MT,ST,SO>, VT >
+ operator*( const DMatScalarMultExpr<MT,ST,SO>& mat, const DenseVector<VT,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * (~vec) ) * mat.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector and a dense
+// matrix-scalar multiplication expression (\f$ \vec{a}^T=\vec{c}^T*(B*s1) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector.
+// \param mat The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense vector and a dense matrix-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=\vec{c}^T*(B*s1) \f$ to the expression \f$ \vec{a}^T=(\vec{c}^T*B)*s1 \f$.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename MT // Type of the dense matrix of the right-hand side expression
+ , typename ST // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the right-hand side expression
+inline const MultExprTrait_< VT, DMatScalarMultExpr<MT,ST,SO> >
+ operator*( const DenseVector<VT,true>& vec, const DMatScalarMultExpr<MT,ST,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~vec) * mat.leftOperand() ) * mat.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar
+// multiplication expression and a dense vector-scalar multiplication expression
+// (\f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side dense matrix-scalar multiplication.
+// \param vec The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a dense matrix-scalar multiplication and a dense vector-scalar multiplication. It
+// restructures the expression \f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$ to the expression
+// \f$ \vec{a}=(B*\vec{c})*(s1*s2) \f$.
+*/
+template< typename MT // Type of the dense matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the left-hand side expression
+ , typename VT // Type of the dense vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar of the right-hand side expression
+inline const DVecScalarMultExpr< MultExprTrait_<MT,VT>, MultTrait_<ST1,ST2>, false >
+ operator*( const DMatScalarMultExpr<MT,ST1,SO>& mat, const DVecScalarMultExpr<VT,ST2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * vec.leftOperand() ) * ( mat.rightOperand() * vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector-scalar
+// multiplication expression and a dense matrix-scalar multiplication expression
+// (\f$ \vec{a}^T=\vec{b}^T*(C*s1) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector-scalar multiplication.
+// \param mat The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a dense vector-scalar multiplication and a dense matrix-scalar multiplication. It
+// restructures the expression \f$ \vec{a}=(\vec{b}^T*s1)*(C*s2) \f$ to the expression
+// \f$ \vec{a}^T=(\vec{b}^T*C)*(s1*s2) \f$.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , typename MT // Type of the dense matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the right-hand side expression
+inline const MultExprTrait_< DVecScalarMultExpr<VT,ST1,true>, DMatScalarMultExpr<MT,ST2,SO> >
+ operator*( const DVecScalarMultExpr<VT,ST1,true>& vec, const DMatScalarMultExpr<MT,ST2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( vec.leftOperand() * mat.leftOperand() ) * ( vec.rightOperand() * mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar
+// multiplication expression and a sparse vector (\f$ \vec{a}=(B*s1)*\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side dense matrix-scalar multiplication.
+// \param vec The right-hand side sparse vector.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense matrix-scalar multiplication and a sparse vector. It restructures the expression
+// \f$ \vec{a}=(B*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
+*/
+template< typename MT // Type of the dense matrix of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the left-hand side expression
+ , typename VT > // Type of the right-hand side sparse vector
+inline const MultExprTrait_< DMatScalarMultExpr<MT,ST,SO>, VT >
+ operator*( const DMatScalarMultExpr<MT,ST,SO>& mat, const SparseVector<VT,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * (~vec) ) * mat.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector and a dense
+// matrix-scalar multiplication expression (\f$ \vec{a}^T=\vec{c}^T*(B*s1) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side sparse vector.
+// \param mat The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse vector and a dense matrix-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=\vec{c}^T*(B*s1) \f$ to the expression \f$ \vec{a}^T=(\vec{c}^T*B)*s1 \f$.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename MT // Type of the dense matrix of the right-hand side expression
+ , typename ST // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the right-hand side expression
+inline const MultExprTrait_< VT, DMatScalarMultExpr<MT,ST,SO> >
+ operator*( const SparseVector<VT,true>& vec, const DMatScalarMultExpr<MT,ST,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~vec) * mat.leftOperand() ) * mat.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar
+// multiplication expression and a sparse vector-scalar multiplication expression
+// (\f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side dense matrix-scalar multiplication.
+// \param vec The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a dense matrix-scalar multiplication and a sparse vector-scalar multiplication. It
+// restructures the expression \f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$ to the expression
+// \f$ \vec{a}=(B*\vec{c})*(s1*s2) \f$.
+*/
+template< typename MT // Type of the dense matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the left-hand side expression
+ , typename VT // Type of the sparse vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< DMatScalarMultExpr<MT,ST1,SO>, SVecScalarMultExpr<VT,ST2,false> >
+ operator*( const DMatScalarMultExpr<MT,ST1,SO>& mat, const SVecScalarMultExpr<VT,ST2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * vec.leftOperand() ) * ( mat.rightOperand() * vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector-scalar
+// multiplication expression and a dense matrix-scalar multiplication expression
+// (\f$ \vec{a}^T=\vec{b}^T*(C*s1) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side sparse vector-scalar multiplication.
+// \param mat The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a sparse vector-scalar multiplication and a dense matrix-scalar multiplication. It
+// restructures the expression \f$ \vec{a}=(\vec{b}^T*s1)*(C*s2) \f$ to the expression
+// \f$ \vec{a}^T=(\vec{b}^T*C)*(s1*s2) \f$.
+*/
+template< typename VT // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , typename MT // Type of the dense matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the right-hand side expression
+inline const MultExprTrait_< SVecScalarMultExpr<VT,ST1,true>, DMatScalarMultExpr<MT,ST2,SO> >
+ operator*( const SVecScalarMultExpr<VT,ST1,true>& vec, const DMatScalarMultExpr<MT,ST2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( vec.leftOperand() * mat.leftOperand() ) * ( vec.rightOperand() * mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar multiplication
+// expression and a dense matrix (\f$ A=(B*s1)*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-scalar multiplication.
+// \param rhs The right-hand side dense matrix.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense matrix-scalar multiplication and a dense matrix. It restructures the expression
+// \f$ A=(B*s1)*C \f$ to the expression \f$ A=(B*C)*s1 \f$.
+*/
+template< typename MT1 // Type of the dense matrix of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename MT2 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline const MultExprTrait_< DMatScalarMultExpr<MT1,ST,SO1>, MT2 >
+ operator*( const DMatScalarMultExpr<MT1,ST,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix and a dense matrix-
+// scalar multiplication expression (\f$ A=(B*s1)*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix.
+// \param rhs The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense matrix and a dense matrix-scalar multiplication. It restructures the expression
+// \f$ A=B*(C*s1) \f$ to the expression \f$ A=(B*C)*s1 \f$.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the dense matrix of the right-hand side expression
+ , typename ST // Type of the scalar of the right-hand side expression
+ , bool SO2 > // Storage order of the right-hand side expression
+inline const MultExprTrait_< MT1, DMatScalarMultExpr<MT2,ST,SO2> >
+ operator*( const DenseMatrix<MT1,SO1>& lhs, const DMatScalarMultExpr<MT2,ST,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of two dense matrix-scalar multiplication
+// expressions (\f$ A=(B*s1)*(C*s2) \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-scalar multiplication.
+// \param rhs The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of
+// two dense matrix-scalar multiplication expressions. It restructures the expression
+// \f$ A=(B*s1)*(C*s2) \f$ to the expression \f$ A=(B*C)*(s1*s2) \f$.
+*/
+template< typename MT1 // Type of the dense matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename MT2 // Type of the right-hand side dense matrix
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO2 > // Storage order of the right-hand side expression
+inline const MultExprTrait_< DMatScalarMultExpr<MT1,ST1,SO1>, DMatScalarMultExpr<MT2,ST2,SO2> >
+ operator*( const DMatScalarMultExpr<MT1,ST1,SO1>& lhs, const DMatScalarMultExpr<MT2,ST2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar multiplication
+// expression and a sparse matrix (\f$ A=(B*s1)*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-scalar multiplication.
+// \param rhs The right-hand side sparse matrix.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense matrix-scalar multiplication and a sparse matrix. It restructures the expression
+// \f$ A=(B*s1)*C \f$ to the expression \f$ A=(B*C)*s1 \f$.
+*/
+template< typename MT1 // Type of the dense matrix of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename MT2 // Type of the right-hand side sparse matrix
+ , bool SO2 > // Storage order of the right-hand side sparse matrix
+inline const MultExprTrait_< DMatScalarMultExpr<MT1,ST,SO1>, MT2 >
+ operator*( const DMatScalarMultExpr<MT1,ST,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix and a dense matrix-
+// scalar multiplication expression (\f$ A=(B*s1)*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix.
+// \param rhs The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse matrix and a dense matrix-scalar multiplication. It restructures the expression
+// \f$ A=B*(C*s1) \f$ to the expression \f$ A=(B*C)*s1 \f$.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , bool SO1 // Storage order of the left-hand side sparse matrix
+ , typename MT2 // Type of the dense matrix of the right-hand side expression
+ , typename ST // Type of the scalar of the right-hand side expression
+ , bool SO2 > // Storage order of the right-hand side expression
+inline const MultExprTrait_< MT1, DMatScalarMultExpr<MT2,ST,SO2> >
+ operator*( const SparseMatrix<MT1,SO1>& lhs, const DMatScalarMultExpr<MT2,ST,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix-scalar
+// multiplication expression and a sparse matrix-scalar multiplication expression
+// (\f$ A=(B*s1)*(C*s2) \f$).
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side dense matrix-scalar multiplication.
+// \param vec The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a dense
+// matrix-scalar multiplication and a sparse matrix-scalar multiplication. It restructures the
+// expression \f$ A=(B*s1)*(C*s2) \f$ to the expression \f$ A=(B*C)*(s1*s2) \f$.
+*/
+template< typename MT1 // Type of the dense matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename MT2 // Type of the sparse matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO2 > // Storage order of the right-hand side expression
+inline const MultExprTrait_< DMatScalarMultExpr<MT1,ST1,SO1>, SMatScalarMultExpr<MT2,ST2,SO2> >
+ operator*( const DMatScalarMultExpr<MT1,ST1,SO1>& mat, const SMatScalarMultExpr<MT2,ST2,SO2>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * vec.leftOperand() ) * ( mat.rightOperand() * vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar
+// multiplication expression and a dense matrix-scalar multiplication expression
+// (\f$ A=(B*s1)*(C*s2) \f$).
+// \ingroup dense_matrix
+//
+// \param mat The left-hand side sparse matrix-scalar multiplication.
+// \param vec The right-hand side dense matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a sparse
+// matrix-scalar multiplication and a dense matrix-scalar multiplication. It restructures the
+// expression \f$ A=(B*s1)*(C*s2) \f$ to the expression \f$ A=(B*C)*(s1*s2) \f$.
+*/
+template< typename MT1 // Type of the sparse matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename MT2 // Type of the dense matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO2 > // Storage order of the right-hand side expression
+inline const MultExprTrait_< SMatScalarMultExpr<MT1,ST1,SO1>, DMatScalarMultExpr<MT2,ST2,SO2> >
+ operator*( const SMatScalarMultExpr<MT1,ST1,SO1>& mat, const DMatScalarMultExpr<MT2,ST2,SO2>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * vec.leftOperand() ) * ( mat.rightOperand() * vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct Rows< DMatScalarMultExpr<MT,ST,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct Columns< DMatScalarMultExpr<MT,ST,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsAligned< DMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsPadded< DMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsSymmetric< DMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsHermitian< DMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsLower< DMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsStrictlyLower< DMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsUpper< DMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsStrictlyUpper< DMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct DMatScalarMultExprTrait< DMatScalarMultExpr<MT,ST1,false>, ST2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>, IsNumeric<ST1>, IsNumeric<ST2> >
+ , DMatScalarMultExprTrait_< MT, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct TDMatScalarMultExprTrait< DMatScalarMultExpr<MT,ST1,true>, ST2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>, IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDMatScalarMultExprTrait_< MT, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSCALARDIVEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct DMatScalarDivExprTrait< DMatScalarMultExpr<MT,ST1,false>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ typedef DivTrait_<ST1,ST2> ScalarType;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>, IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , DMatScalarMultExprTrait_<MT,ScalarType>
+ , DMatScalarDivExprTrait_<MT,ScalarType> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATSCALARDIVEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct TDMatScalarDivExprTrait< DMatScalarMultExpr<MT,ST1,true>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ typedef DivTrait_<ST1,ST2> ScalarType;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>, IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , TDMatScalarMultExprTrait_<MT,ScalarType>
+ , TDMatScalarDivExprTrait_<MT,ScalarType> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, typename VT >
+struct DMatDVecMultExprTrait< DMatScalarMultExpr<MT,ST,false>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< DMatDVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename VT, typename ST2 >
+struct DMatDVecMultExprTrait< DMatScalarMultExpr<MT,ST1,false>, DVecScalarMultExpr<VT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DVecScalarMultExprTrait_< DMatDVecMultExprTrait_<MT,VT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, typename VT >
+struct TDMatDVecMultExprTrait< DMatScalarMultExpr<MT,ST,true>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< TDMatDVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename VT, typename ST2 >
+struct TDMatDVecMultExprTrait< DMatScalarMultExpr<MT,ST1,true>, DVecScalarMultExpr<VT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DVecScalarMultExprTrait_< TDMatDVecMultExprTrait_<MT,VT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TDVecDMatMultExprTrait< VT, DMatScalarMultExpr<MT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename MT, typename ST2 >
+struct TDVecDMatMultExprTrait< DVecScalarMultExpr<VT,ST1,true>, DMatScalarMultExpr<MT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDVecScalarMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TDVecTDMatMultExprTrait< VT, DMatScalarMultExpr<MT,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecTDMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename MT, typename ST2 >
+struct TDVecTDMatMultExprTrait< DVecScalarMultExpr<VT,ST1,true>, DMatScalarMultExpr<MT,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDVecScalarMultExprTrait_< TDVecTDMatMultExprTrait_<VT,MT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, typename VT >
+struct DMatSVecMultExprTrait< DMatScalarMultExpr<MT,ST,false>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< DMatSVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename VT, typename ST2 >
+struct DMatSVecMultExprTrait< DMatScalarMultExpr<MT,ST1,false>, SVecScalarMultExpr<VT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DVecScalarMultExprTrait_< DMatSVecMultExprTrait_<MT,VT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, typename VT >
+struct TDMatSVecMultExprTrait< DMatScalarMultExpr<MT,ST,true>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< TDMatSVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename VT, typename ST2 >
+struct TDMatSVecMultExprTrait< DMatScalarMultExpr<MT,ST1,true>, SVecScalarMultExpr<VT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DVecScalarMultExprTrait_< TDMatSVecMultExprTrait_<MT,VT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TSVecDMatMultExprTrait< VT, DMatScalarMultExpr<MT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TSVecDMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename MT, typename ST2 >
+struct TSVecDMatMultExprTrait< SVecScalarMultExpr<VT,ST1,true>, DMatScalarMultExpr<MT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDVecScalarMultExprTrait_< TSVecDMatMultExprTrait_<VT,MT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TSVecTDMatMultExprTrait< VT, DMatScalarMultExpr<MT,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TSVecTDMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename MT, typename ST2 >
+struct TSVecTDMatMultExprTrait< SVecScalarMultExpr<VT,ST1,true>, DMatScalarMultExpr<MT,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDVecScalarMultExprTrait_< TSVecTDMatMultExprTrait_<VT,MT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct DMatDMatMultExprTrait< DMatScalarMultExpr<MT1,ST,false>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DMatDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct DMatDMatMultExprTrait< MT1, DMatScalarMultExpr<MT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DMatDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct DMatDMatMultExprTrait< DMatScalarMultExpr<MT1,ST1,false>, DMatScalarMultExpr<MT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DMatScalarMultExprTrait_< DMatDMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct DMatTDMatMultExprTrait< DMatScalarMultExpr<MT1,ST,false>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DMatTDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct DMatTDMatMultExprTrait< MT1, DMatScalarMultExpr<MT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DMatTDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct DMatTDMatMultExprTrait< DMatScalarMultExpr<MT1,ST1,false>, DMatScalarMultExpr<MT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DMatScalarMultExprTrait_< DMatTDMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TDMatDMatMultExprTrait< DMatScalarMultExpr<MT1,ST,true>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TDMatDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct TDMatDMatMultExprTrait< MT1, DMatScalarMultExpr<MT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TDMatDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct TDMatDMatMultExprTrait< DMatScalarMultExpr<MT1,ST1,true>, DMatScalarMultExpr<MT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDMatScalarMultExprTrait_< TDMatDMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TDMatTDMatMultExprTrait< DMatScalarMultExpr<MT1,ST,true>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TDMatTDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct TDMatTDMatMultExprTrait< MT1, DMatScalarMultExpr<MT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TDMatTDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct TDMatTDMatMultExprTrait< DMatScalarMultExpr<MT1,ST1,true>, DMatScalarMultExpr<MT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDMatScalarMultExprTrait_< TDMatTDMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct DMatSMatMultExprTrait< DMatScalarMultExpr<MT1,ST,false>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DMatSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct DMatSMatMultExprTrait< DMatScalarMultExpr<MT1,ST1,false>, SMatScalarMultExpr<MT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DMatScalarMultExprTrait_< DMatSMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct DMatTSMatMultExprTrait< DMatScalarMultExpr<MT1,ST,false>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DMatTSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct DMatTSMatMultExprTrait< DMatScalarMultExpr<MT1,ST1,false>, SMatScalarMultExpr<MT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DMatScalarMultExprTrait_< DMatTSMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TDMatSMatMultExprTrait< DMatScalarMultExpr<MT1,ST,true>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TDMatSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct TDMatSMatMultExprTrait< DMatScalarMultExpr<MT1,ST1,true>, SMatScalarMultExpr<MT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDMatScalarMultExprTrait_< TDMatSMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TDMatTSMatMultExprTrait< DMatScalarMultExpr<MT1,ST,true>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TDMatTSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct TDMatTSMatMultExprTrait< DMatScalarMultExpr<MT1,ST1,true>, SMatScalarMultExpr<MT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDMatScalarMultExprTrait_< TDMatTSMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct SMatDMatMultExprTrait< MT1, DMatScalarMultExpr<MT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< SMatDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct SMatDMatMultExprTrait< SMatScalarMultExpr<MT1,ST1,false>, DMatScalarMultExpr<MT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DMatScalarMultExprTrait_< SMatDMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct SMatTDMatMultExprTrait< MT1, DMatScalarMultExpr<MT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< SMatTDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct SMatTDMatMultExprTrait< SMatScalarMultExpr<MT1,ST1,false>, DMatScalarMultExpr<MT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DMatScalarMultExprTrait_< SMatTDMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TSMatDMatMultExprTrait< MT1, DMatScalarMultExpr<MT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TSMatDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct TSMatDMatMultExprTrait< SMatScalarMultExpr<MT1,ST1,true>, DMatScalarMultExpr<MT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDMatScalarMultExprTrait_< TSMatDMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TSMatTDMatMultExprTrait< MT1, DMatScalarMultExpr<MT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TSMatTDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct TSMatTDMatMultExprTrait< SMatScalarMultExpr<MT1,ST1,true>, DMatScalarMultExpr<MT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDMatScalarMultExprTrait_< TSMatTDMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatScalarMultExpr<MT,ST,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct RowExprTrait< DMatScalarMultExpr<MT,ST,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct ColumnExprTrait< DMatScalarMultExpr<MT,ST,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< ColumnExprTrait_<const MT>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatSerialExpr.h b/src/cpu/blaze/math/expressions/DMatSerialExpr.h
new file mode 100644
index 00000000..2c7a1e84
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatSerialExpr.h
@@ -0,0 +1,1040 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatSerialExpr.h
+// \brief Header file for the dense matrix serial evaluation expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATSERIALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatSerialExpr.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatSerialExprTrait.h>
+#include <blaze/math/traits/SerialExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatSerialExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATSERIALEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the forced serial evaluation of dense matrices.
+// \ingroup dense_matrix_expression
+//
+// The DMatSerialExpr class represents the compile time expression for the forced serial
+// evaluation of a dense matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+class DMatSerialExpr : public DenseMatrix< DMatSerialExpr<MT,SO>, SO >
+ , private MatSerialExpr
+ , private Computation
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatSerialExpr<MT,SO> This; //!< Type of this DMatSerialExpr instance.
+ typedef ResultType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatSerialExpr class.
+ //
+ // \param dm The dense matrix operand of the serial evaluation expression.
+ */
+ explicit inline DMatSerialExpr( const MT& dm ) noexcept
+ : dm_( dm ) // Dense matrix of the serial evaluation expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < dm_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.columns(), "Invalid column access index" );
+ return dm_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= dm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= dm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return dm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return dm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense matrix operand.
+ //
+ // \return The dense matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return dm_;
+ }
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\brief Conversion to the type of the dense matrix operand.
+ //
+ // \return The dense matrix operand.
+ */
+ inline operator Operand() const noexcept {
+ return dm_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return dm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return dm_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return dm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dm_; //!< Dense matrix of the serial evaluation expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix serial evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix serial
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix serial evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluatin expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix serial
+ // evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( SparseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix serial evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix
+ // serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix serial evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix
+ // serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( SparseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix serial evaluation expression to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix
+ // serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix serial evaluation expression to a sparse
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( SparseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense matrix serial evaluation expression to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // matrix serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void multAssign( DenseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense matrix serial evaluation expression to a sparse
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void multAssign( SparseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix serial evaluation expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAssign( DenseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix serial evaluation expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluatin expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAssign( SparseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix serial evaluation expression to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix
+ // serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix serial evaluation expression to a sparse
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix
+ // serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAddAssign( SparseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix serial evaluation expression to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix serial evaluation expression to a sparse
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpSubAssign( SparseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense matrix serial evaluation expression to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // matrix serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpMultAssign( DenseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense matrix serial evaluation expression to a
+ // sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpMultAssign( SparseMatrix<MT2,SO2>& lhs, const DMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Forces the serial evaluation of the given dense matrix expression \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input matrix.
+// \return The evaluated dense matrix.
+//
+// The \a serial function forces the serial evaluation of the given dense matrix expression
+// \a dm. The function returns an expression representing the operation.\n
+// The following example demonstrates the use of the \a serial function
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = serial( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatSerialExpr<MT,SO> serial( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatSerialExpr<MT,SO>( ~dm );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Evaluation of the given dense matrix serial evaluation expression \a dm.
+// \ingroup dense_matrix
+//
+// \param dm The input serial evaluation expression.
+// \return The evaluated dense matrix.
+//
+// This function implements a performance optimized treatment of the serial evaluation of a dense
+// matrix serial evaluation expression.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatSerialExpr<MT,SO> serial( const DMatSerialExpr<MT,SO>& dm )
+{
+ return dm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Rows< DMatSerialExpr<MT,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Columns< DMatSerialExpr<MT,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsAligned< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsLower< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniLower< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUpper< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniUpper< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatSerialExprTrait< DMatSerialExpr<MT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatSerialExpr<MT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatSerialExprTrait< DMatSerialExpr<MT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatSerialExpr<MT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatSerialExpr<MT,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SerialExprTrait_< SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct RowExprTrait< DMatSerialExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SerialExprTrait_< RowExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct ColumnExprTrait< DMatSerialExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SerialExprTrait_< ColumnExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatTDMatAddExpr.h b/src/cpu/blaze/math/expressions/DMatTDMatAddExpr.h
new file mode 100644
index 00000000..76d8d68f
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatTDMatAddExpr.h
@@ -0,0 +1,1270 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatTDMatAddExpr.h
+// \brief Header file for the dense matrix/transpose dense matrix addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATTDMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATTDMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATTDMATADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-transpose dense matrix additions.
+// \ingroup dense_matrix_expression
+//
+// The DMatTDMatAddExpr class represents the compile time expression for additions between a
+// row-major dense matrix and column-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class DMatTDMatAddExpr : public DenseMatrix< DMatTDMatAddExpr<MT1,MT2>, false >
+ , private MatMatAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the addition expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the addition expression. In case either of the two
+ dense matrix operands requires an intermediate evaluation or the subscript operator
+ can only return by value, \a useAssign will be set to 1 and the addition expression
+ will be evaluated via the \a assign function family. Otherwise \a useAssign will be
+ set to 0 and the expression will be evaluated via the function call operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT1>::value || RequiresEvaluation<MT2>::value || !returnExpr };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable and at
+ least one of the two operands requires an intermediate evaluation, \a value is set to 1
+ and the expression specific evaluation strategy is selected. Otherwise \a value is set
+ to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTDMatAddExpr<MT1,MT2> This; //!< Type of this DMatTDMatAdd instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT1::smpAssignable && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTDMatAddExpr class.
+ //
+ // \param lhs The left-hand side operand of the addition expression.
+ // \param rhs The right-hand side operand of the addition expression.
+ */
+ explicit inline DMatTDMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the addition expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) + rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && ( RequiresEvaluation<MT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
+ ( IsExpression<MT2>::value && ( RequiresEvaluation<MT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
+ ( rows() > SMP_DMATTDMATADD_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the addition expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // dense matrix addition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case neither of
+ // the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline DisableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ (~lhs)(i,j) = rhs.lhs_(i,j) + rhs.rhs_(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // dense matrix addition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( !IsExpression<MT2>::value && isSame( ~lhs, rhs.rhs_ ) ) {
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose dense matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // dense matrix addition expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-tranpose dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose dense matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case neither
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline DisableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ (~lhs)(i,j) += rhs.lhs_(i,j) + rhs.rhs_(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-tranpose dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose dense matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either of
+ // the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-transpose dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // transpose dense matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case neither
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline DisableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ (~lhs)(i,j) -= rhs.lhs_(i,j) + rhs.rhs_(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-transpose dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // transpose dense matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either of
+ // the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose dense matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // dense matrix addition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( !IsExpression<MT2>::value && isSame( ~lhs, rhs.rhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose dense matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // dense matrix addition expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-tranpose dense matrix addition to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix-
+ // transpose dense matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-transpose dense matrix addition to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-transpose dense matrix addition expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a row-major and a colum-major dense matrix
+// (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the addition of a row-major and a column-major dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, C;
+ blaze::DynamicMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< And< Not< IsSymmetric<T1> >, Not< IsSymmetric<T2> > >
+ , const DMatTDMatAddExpr<T1,T2> >
+ operator+( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTDMatAddExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a column-major and a row-major dense matrix
+// (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the addition of a column-major and a row-major dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,columnMajor> A;
+ blaze::DynamicMatrix<double,rowMajor> B, C;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< And< Not< IsSymmetric<T1> >, Not< IsSymmetric<T2> > >
+ , const DMatTDMatAddExpr<T2,T1> >
+ operator+( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTDMatAddExpr<T2,T1>( ~rhs, ~lhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a symmetric row-major and a colum-major dense
+// matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator implements a performance optimized treatment of the addition of a symmetric
+// row-major dense matrix and a column-major dense matrix.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< And< IsSymmetric<T1>, Not< IsSymmetric<T2> > >, const AddExprTrait_<T1,T2> >
+ operator+( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return trans( ~lhs ) + ~rhs;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a row-major and a symmetric column-major dense
+// matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator implements a performance optimized treatment of the addition of a (potentially
+// symmetric) row-major dense matrix and a symmetric column-major dense matrix.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< IsSymmetric<T2>, const AddExprTrait_<T1,T2> >
+ operator+( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return (~lhs) + trans( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a column-major and a symmetric row-major dense
+// matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator implements a performance optimized treatment of the addition of a column-major
+// dense matrix and a symmetric row-major dense matrix.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< And< Not< IsSymmetric<T1> >, IsSymmetric<T2> >, const AddExprTrait_<T2,T1> >
+ operator+( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return trans( ~rhs ) + (~lhs);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a symmetric column-major and a row-major dense
+// matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator implements a performance optimized treatment of the addition of a symmetric
+// column-major dense matrix and a (potentially symmetric) row-major dense matrix.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< IsSymmetric<T1>, const AddExprTrait_<T2,T1> >
+ operator+( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return (~rhs) + trans( ~lhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< DMatTDMatAddExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< DMatTDMatAddExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsAligned<MT1>, IsAligned<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >
+ , And< IsUniLower<MT2>, IsStrictlyLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >
+ , And< IsUniUpper<MT2>, IsStrictlyUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< DMatTDMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< DMatTDMatAddExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< DMatTDMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< DMatTDMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatTDMatMultExpr.h b/src/cpu/blaze/math/expressions/DMatTDMatMultExpr.h
new file mode 100644
index 00000000..3bfdd4f0
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatTDMatMultExpr.h
@@ -0,0 +1,8114 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatTDMatMultExpr.h
+// \brief Header file for the dense matrix/transpose dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATTDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATTDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/gemm.h>
+#include <blaze/math/blas/trmm.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/expressions/MatScalarMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATTDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-transpose dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The DMatTDMatMultExpr class represents the compile time expression for multiplications between
+// a row-major dense matrix and a column-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class DMatTDMatMultExpr : public DenseMatrix< DMatTDMatMultExpr<MT1,MT2>, false >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the types of all three involved matrices are suited for a BLAS kernel, the nested
+ \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTDMatMultExpr<MT1,MT2> This; //!< Type of this DMatTDMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT1>::value && !IsDiagonal<MT2>::value &&
+ MT1::simdEnabled && MT2::simdEnabled &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTDMatMultExpr class.
+ //
+ // \param lhs The left-hand side operand of the multiplication expression.
+ // \param rhs The right-hand side operand of the multiplication expression.
+ */
+ explicit inline DMatTDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( rows() * columns() < DMATTDMATMULT_THRESHOLD ) ) &&
+ ( rows() > SMP_DMATTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose dense matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const DMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( rhs.lhs_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatTDMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value || IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATTDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( C, A, B );
+ else
+ selectBlasAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (general/general)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general dense matrix-general transpose
+ // dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const size_t ibegin( ( IsStrictlyLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT5>::value && M > 1UL ) ? 2UL : 1UL )
+ :( 0UL ) );
+ const size_t iend( ( IsStrictlyUpper<MT4>::value )
+ ?( ( IsStrictlyUpper<MT5>::value && M > 1UL ) ? M-2UL : M-1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+2UL : i+1UL )
+ :( IsStrictlyUpper<MT5>::value ? i+1UL : i ) )
+ :( IsStrictlyUpper<MT5>::value ? 1UL : 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value )
+ ?( IsStrictlyLower<MT5>::value ? i-1UL : i )
+ :( IsStrictlyLower<MT5>::value ? i : i+1UL ) )
+ :( IsStrictlyLower<MT5>::value ? N-1UL : N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) ) );
+ BLAZE_INTERNAL_ASSERT( kbegin < kend, "Invalid loop indices detected" );
+
+ (~C)(i,j) = A(i,kbegin) * B(kbegin,j);
+ for( size_t k=kbegin+1UL; k<kend; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ }
+ for( size_t j=jend; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=iend; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (general/general)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general dense matrix-general transpose
+ // dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const size_t jbegin( ( IsStrictlyUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value && N > 1UL ) ? 2UL : 1UL )
+ :( 0UL ) );
+ const size_t jend( ( IsStrictlyLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value && N > 1UL ) ? N-2UL : N-1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+2UL : j+1UL )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsStrictlyLower<MT4>::value ? 1UL : 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value )
+ ?( ( IsStrictlyUpper<MT5>::value )?( j-1UL ):( j ) )
+ :( ( IsStrictlyUpper<MT5>::value )?( j ):( j+1UL ) ) )
+ :( IsStrictlyUpper<MT4>::value ? M-1UL : M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) ) );
+ BLAZE_INTERNAL_ASSERT( kbegin < kend, "Invalid loop indices detected" );
+
+ (~C)(i,j) = A(i,kbegin) * B(kbegin,j);
+ for( size_t k=kbegin+1UL; k<kend; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ }
+ for( size_t i=iend; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jend; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (general/diagonal)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general dense matrix-diagonal transpose
+ // dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT4>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) = A(i,j) * B(j,j);
+ }
+ if( IsLower<MT4>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (general/diagonal)************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general dense matrix-diagonal transpose
+ // dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ( IsStrictlyLower<MT4>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT4>::value )
+ ?( min( ( IsStrictlyUpper<MT4>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ if( IsLower<MT4>::value ) {
+ for( size_t i=ii; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) = A(i,j) * B(j,j);
+ }
+ if( IsUpper<MT4>::value ) {
+ for( size_t i=ipos; i<iend; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (diagonal/general)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal dense matrix-general transpose
+ // dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT5>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT5>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ if( IsUpper<MT5>::value ) {
+ for( size_t j=jj; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) = A(i,i) * B(i,j);
+ }
+ if( IsLower<MT5>::value ) {
+ for( size_t j=jpos; j<jend; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (diagonal/general)************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal dense matrix-general transpose
+ // dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT5>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) = A(i,i) * B(i,j);
+ }
+ if( IsUpper<MT5>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/diagonal)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal dense matrix-diagonal transpose
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) = A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small dense matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (small matrices)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small dense matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a dense matrix-transpose dense
+ // matrix multiplication expression to a row-major dense matrix. This kernel is optimized for
+ // small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+4UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+4UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ const SIMDType b3( B.load(k,j+2UL) );
+ const SIMDType b4( B.load(k,j+3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C)(i ,j ) = sum( xmm1 );
+ (~C)(i ,j+1UL) = sum( xmm2 );
+ (~C)(i ,j+2UL) = sum( xmm3 );
+ (~C)(i ,j+3UL) = sum( xmm4 );
+ (~C)(i+1UL,j ) = sum( xmm5 );
+ (~C)(i+1UL,j+1UL) = sum( xmm6 );
+ (~C)(i+1UL,j+2UL) = sum( xmm7 );
+ (~C)(i+1UL,j+3UL) = sum( xmm8 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL);
+ (~C)(i ,j+2UL) += A(i ,k) * B(k,j+2UL);
+ (~C)(i ,j+3UL) += A(i ,k) * B(k,j+3UL);
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL);
+ (~C)(i+1UL,j+2UL) += A(i+1UL,k) * B(k,j+2UL);
+ (~C)(i+1UL,j+3UL) += A(i+1UL,k) * B(k,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) = sum( xmm1 );
+ (~C)(i ,j+1UL) = sum( xmm2 );
+ (~C)(i+1UL,j ) = sum( xmm3 );
+ (~C)(i+1UL,j+1UL) = sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) = sum( xmm1 );
+ (~C)(i+1UL,j) = sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j);
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ xmm3 = xmm3 + a1 * B.load(k,j+2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+3UL);
+ }
+
+ (~C)(i,j ) = sum( xmm1 );
+ (~C)(i,j+1UL) = sum( xmm2 );
+ (~C)(i,j+2UL) = sum( xmm3 );
+ (~C)(i,j+3UL) = sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j );
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL);
+ (~C)(i,j+2UL) += A(i,k) * B(k,j+2UL);
+ (~C)(i,j+3UL) += A(i,k) * B(k,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) = sum( xmm1 );
+ (~C)(i,j+1UL) = sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j );
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) = sum( xmm1 );
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (small matrices)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small dense matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a dense matrix-transpose dense
+ // matrix multiplication expression to a column-major dense matrix. This kernel is optimized for
+ // small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+4UL, j+2UL ) : ( i+4UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType a3( A.load(i+2UL,k) );
+ const SIMDType a4( A.load(i+3UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C)(i ,j ) = sum( xmm1 );
+ (~C)(i ,j+1UL) = sum( xmm2 );
+ (~C)(i+1UL,j ) = sum( xmm3 );
+ (~C)(i+1UL,j+1UL) = sum( xmm4 );
+ (~C)(i+2UL,j ) = sum( xmm5 );
+ (~C)(i+2UL,j+1UL) = sum( xmm6 );
+ (~C)(i+3UL,j ) = sum( xmm7 );
+ (~C)(i+3UL,j+1UL) = sum( xmm8 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL);
+ (~C)(i+2UL,j ) += A(i+2UL,k) * B(k,j );
+ (~C)(i+2UL,j+1UL) += A(i+2UL,k) * B(k,j+1UL);
+ (~C)(i+3UL,j ) += A(i+3UL,k) * B(k,j );
+ (~C)(i+3UL,j+1UL) += A(i+3UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ xmm3 = xmm3 + A.load(i+2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+3UL,k) * b1;
+ }
+
+ (~C)(i ,j) = sum( xmm1 );
+ (~C)(i+1UL,j) = sum( xmm2 );
+ (~C)(i+2UL,j) = sum( xmm3 );
+ (~C)(i+3UL,j) = sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j);
+ (~C)(i+2UL,j) += A(i+2UL,k) * B(k,j);
+ (~C)(i+3UL,j) += A(i+3UL,k) * B(k,j);
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) = sum( xmm1 );
+ (~C)(i ,j+1UL) = sum( xmm2 );
+ (~C)(i+1UL,j ) = sum( xmm3 );
+ (~C)(i+1UL,j+1UL) = sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) = sum( xmm1 );
+ (~C)(i+1UL,j) = sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j);
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) = sum( xmm1 );
+ (~C)(i,j+1UL) = sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j );
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) = sum( xmm1 );
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large dense matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (large matrices)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large dense matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a dense matrix-transpose dense
+ // matrix multiplication expression to a row-major dense matrix. This kernel is optimized for
+ // large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ // TODO
+ selectSmallAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (large matrices)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large dense matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a dense matrix-transpose dense
+ // matrix multiplication expression to a column-major dense matrix. This kernel is optimized for
+ // large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ // TODO
+ selectSmallAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices*****************************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based assignment of a dense matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the dense matrix-transpose dense matrix multiplication precision
+ // matrices based on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ assign( C, B );
+ trmm( C, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ assign( C, A );
+ trmm( C, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ }
+ else {
+ gemm( C, A, B, ET(1), ET(0) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose dense matrix multiplication to a sparse matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO>& lhs, const DMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-transpose dense matrix multiplication to a
+ // dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a dense matrix-transpose dense
+ // matrix multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value || IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATTDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( C, A, B );
+ else
+ selectBlasAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (general/general)*******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general dense matrix-general transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general dense matrix-general
+ // transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const size_t ibegin( ( IsStrictlyLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT5>::value && M > 1UL ) ? 2UL : 1UL )
+ :( 0UL ) );
+ const size_t iend( ( IsStrictlyUpper<MT4>::value )
+ ?( ( IsStrictlyUpper<MT5>::value && M > 1UL ) ? M-2UL : M-1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+2UL : i+1UL )
+ :( IsStrictlyUpper<MT5>::value ? i+1UL : i ) )
+ :( IsStrictlyUpper<MT5>::value ? 1UL : 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value )
+ ?( IsStrictlyLower<MT5>::value ? i-1UL : i )
+ :( IsStrictlyLower<MT5>::value ? i : i+1UL ) )
+ :( IsStrictlyLower<MT5>::value ? N-1UL : N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) ) );
+ BLAZE_INTERNAL_ASSERT( kbegin < kend, "Invalid loop indices detected" );
+
+ const size_t knum( kend - kbegin );
+ const size_t kpos( kbegin + ( knum & size_t(-2) ) );
+
+ for( size_t k=kbegin; k<kpos; k+=2UL ) {
+ (~C)(i,j) += A(i,k ) * B(k ,j);
+ (~C)(i,j) += A(i,k+1UL) * B(k+1UL,j);
+ }
+ if( kpos < kend ) {
+ (~C)(i,j) += A(i,kpos) * B(kpos,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (general/general)****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general dense matrix-general transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general dense matrix-general
+ // transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const size_t jbegin( ( IsStrictlyUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value && N > 1UL ) ? 2UL : 1UL )
+ :( 0UL ) );
+ const size_t jend( ( IsStrictlyLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value && N > 1UL ) ? N-2UL : N-1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+2UL : j+1UL )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsStrictlyLower<MT4>::value ? 1UL : 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value )
+ ?( ( IsStrictlyUpper<MT5>::value )?( j-1UL ):( j ) )
+ :( ( IsStrictlyUpper<MT5>::value )?( j ):( j+1UL ) ) )
+ :( IsStrictlyUpper<MT4>::value ? M-1UL : M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) ) );
+ BLAZE_INTERNAL_ASSERT( kbegin < kend, "Invalid loop indices detected" );
+
+ const size_t knum( kend - kbegin );
+ const size_t kpos( kbegin + ( knum & size_t(-2) ) );
+
+ for( size_t k=kbegin; k<kpos; k+=2UL ) {
+ (~C)(i,j) += A(i,k ) * B(k ,j);
+ (~C)(i,j) += A(i,k+1UL) * B(k+1UL,j);
+ }
+ if( kpos < kend ) {
+ (~C)(i,j) += A(i,kpos) * B(kpos,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (general/diagonal)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general dense matrix-diagonal
+ // transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) += A(i,j ) * B(j ,j );
+ (~C)(i,j+1UL) += A(i,j+1UL) * B(j+1UL,j+1UL);
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) += A(i,jpos) * B(jpos,jpos);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (general/diagonal)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general dense matrix-diagonal
+ // transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ( IsStrictlyLower<MT4>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT4>::value )
+ ?( min( ( IsStrictlyUpper<MT4>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) += A(i,j) * B(j,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (diagonal/general)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal dense matrix-general transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal dense matrix-general
+ // transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT5>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT5>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) += A(i,i) * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (diagonal/general)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal dense matrix-general transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal dense matrix-general
+ // transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) += A(i ,i ) * B(i ,j);
+ (~C)(i+1UL,j) += A(i+1UL,i+1UL) * B(i+1UL,j);
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) += A(ipos,ipos) * B(ipos,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/diagonal)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal dense matrix-diagonal
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) += A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (small matrices)*********
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a dense matrix-
+ // transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+4UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+4UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ const SIMDType b3( B.load(k,j+2UL) );
+ const SIMDType b4( B.load(k,j+3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C)(i ,j ) += sum( xmm1 );
+ (~C)(i ,j+1UL) += sum( xmm2 );
+ (~C)(i ,j+2UL) += sum( xmm3 );
+ (~C)(i ,j+3UL) += sum( xmm4 );
+ (~C)(i+1UL,j ) += sum( xmm5 );
+ (~C)(i+1UL,j+1UL) += sum( xmm6 );
+ (~C)(i+1UL,j+2UL) += sum( xmm7 );
+ (~C)(i+1UL,j+3UL) += sum( xmm8 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL);
+ (~C)(i ,j+2UL) += A(i ,k) * B(k,j+2UL);
+ (~C)(i ,j+3UL) += A(i ,k) * B(k,j+3UL);
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL);
+ (~C)(i+1UL,j+2UL) += A(i+1UL,k) * B(k,j+2UL);
+ (~C)(i+1UL,j+3UL) += A(i+1UL,k) * B(k,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) += sum( xmm1 );
+ (~C)(i ,j+1UL) += sum( xmm2 );
+ (~C)(i+1UL,j ) += sum( xmm3 );
+ (~C)(i+1UL,j+1UL) += sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) += sum( xmm1 );
+ (~C)(i+1UL,j) += sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j);
+ }
+ }
+ }
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ xmm3 = xmm3 + a1 * B.load(k,j+2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+3UL);
+ }
+
+ (~C)(i,j ) += sum( xmm1 );
+ (~C)(i,j+1UL) += sum( xmm2 );
+ (~C)(i,j+2UL) += sum( xmm3 );
+ (~C)(i,j+3UL) += sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j );
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL);
+ (~C)(i,j+2UL) += A(i,k) * B(k,j+2UL);
+ (~C)(i,j+3UL) += A(i,k) * B(k,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) += sum( xmm1 );
+ (~C)(i,j+1UL) += sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j );
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) += sum( xmm1 );
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (small matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a dense matrix-
+ // transpose dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+4UL, j+2UL ) : ( i+4UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType a3( A.load(i+2UL,k) );
+ const SIMDType a4( A.load(i+3UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C)(i ,j ) += sum( xmm1 );
+ (~C)(i ,j+1UL) += sum( xmm2 );
+ (~C)(i+1UL,j ) += sum( xmm3 );
+ (~C)(i+1UL,j+1UL) += sum( xmm4 );
+ (~C)(i+2UL,j ) += sum( xmm5 );
+ (~C)(i+2UL,j+1UL) += sum( xmm6 );
+ (~C)(i+3UL,j ) += sum( xmm7 );
+ (~C)(i+3UL,j+1UL) += sum( xmm8 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL);
+ (~C)(i+2UL,j ) += A(i+2UL,k) * B(k,j );
+ (~C)(i+2UL,j+1UL) += A(i+2UL,k) * B(k,j+1UL);
+ (~C)(i+3UL,j ) += A(i+3UL,k) * B(k,j );
+ (~C)(i+3UL,j+1UL) += A(i+3UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ xmm3 = xmm3 + A.load(i+2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+3UL,k) * b1;
+ }
+
+ (~C)(i ,j) += sum( xmm1 );
+ (~C)(i+1UL,j) += sum( xmm2 );
+ (~C)(i+2UL,j) += sum( xmm3 );
+ (~C)(i+3UL,j) += sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j);
+ (~C)(i+2UL,j) += A(i+2UL,k) * B(k,j);
+ (~C)(i+3UL,j) += A(i+3UL,k) * B(k,j);
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) += sum( xmm1 );
+ (~C)(i ,j+1UL) += sum( xmm2 );
+ (~C)(i+1UL,j ) += sum( xmm3 );
+ (~C)(i+1UL,j+1UL) += sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) += sum( xmm1 );
+ (~C)(i+1UL,j) += sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j);
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) += sum( xmm1 );
+ (~C)(i,j+1UL) += sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j );
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) += sum( xmm1 );
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (large matrices)*********
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a dense matrix-
+ // transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ // TODO
+ selectSmallAddAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (large matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a dense matrix-
+ // transpose dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ // TODO
+ selectSmallAddAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a dense matrix-transpose dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices********************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based addition assignment of a dense matrix-transpose dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the dense matrix-transpose dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ addAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ addAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-transpose dense matrix multiplication to a
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ DMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a dense matrix-transpose
+ // dense matrix multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value || IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATTDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( C, A, B );
+ else
+ selectBlasSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (general/general)****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general dense matrix-general transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general dense matrix-
+ // general transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const size_t ibegin( ( IsStrictlyLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT5>::value && M > 1UL ) ? 2UL : 1UL )
+ :( 0UL ) );
+ const size_t iend( ( IsStrictlyUpper<MT4>::value )
+ ?( ( IsStrictlyUpper<MT5>::value && M > 1UL ) ? M-2UL : M-1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+2UL : i+1UL )
+ :( IsStrictlyUpper<MT5>::value ? i+1UL : i ) )
+ :( IsStrictlyUpper<MT5>::value ? 1UL : 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value )
+ ?( IsStrictlyLower<MT5>::value ? i-1UL : i )
+ :( IsStrictlyLower<MT5>::value ? i : i+1UL ) )
+ :( IsStrictlyLower<MT5>::value ? N-1UL : N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) ) );
+ BLAZE_INTERNAL_ASSERT( kbegin < kend, "Invalid loop indices detected" );
+
+ const size_t knum( kend - kbegin );
+ const size_t kpos( kbegin + ( knum & size_t(-2) ) );
+
+ for( size_t k=kbegin; k<kpos; k+=2UL ) {
+ (~C)(i,j) -= A(i,k ) * B(k ,j);
+ (~C)(i,j) -= A(i,k+1UL) * B(k+1UL,j);
+ }
+ if( kpos < kend ) {
+ (~C)(i,j) -= A(i,kpos) * B(kpos,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (general/general)*************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general dense matrix-general transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general dense matrix-
+ // general transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const size_t jbegin( ( IsStrictlyUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value && N > 1UL ) ? 2UL : 1UL )
+ :( 0UL ) );
+ const size_t jend( ( IsStrictlyLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value && N > 1UL ) ? N-2UL : N-1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+2UL : j+1UL )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsStrictlyLower<MT4>::value ? 1UL : 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value )
+ ?( ( IsStrictlyUpper<MT5>::value )?( j-1UL ):( j ) )
+ :( ( IsStrictlyUpper<MT5>::value )?( j ):( j+1UL ) ) )
+ :( IsStrictlyUpper<MT4>::value ? M-1UL : M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) ) );
+ BLAZE_INTERNAL_ASSERT( kbegin < kend, "Invalid loop indices detected" );
+
+ const size_t knum( kend - kbegin );
+ const size_t kpos( kbegin + ( knum & size_t(-2) ) );
+
+ for( size_t k=kbegin; k<kpos; k+=2UL ) {
+ (~C)(i,j) -= A(i,k ) * B(k ,j);
+ (~C)(i,j) -= A(i,k+1UL) * B(k+1UL,j);
+ }
+ if( kpos < kend ) {
+ (~C)(i,j) -= A(i,kpos) * B(kpos,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (general/diagonal)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general dense matrix-diagonal transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) -= A(i,j ) * B(j ,j );
+ (~C)(i,j+1UL) -= A(i,j+1UL) * B(j+1UL,j+1UL);
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) -= A(i,jpos) * B(jpos,jpos);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (general/diagonal)************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general dense matrix-diagonal transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ( IsStrictlyLower<MT4>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT4>::value )
+ ?( min( ( IsStrictlyUpper<MT4>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) -= A(i,j) * B(j,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (diagonal/general)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal dense matrix-general transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal dense matrix-
+ // general transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT5>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT5>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) -= A(i,i) * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (diagonal/general)************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal dense matrix-general transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal dense matrix-
+ // general transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) -= A(i ,i ) * B(i ,j);
+ (~C)(i+1UL,j) -= A(i+1UL,i+1UL) * B(i+1UL,j);
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) -= A(ipos,ipos) * B(ipos,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/diagonal)************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal dense matrix-diagonal transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) -= A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (small matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a dense matrix-transpose
+ // dense matrix multiplication expression to a row-major dense matrix. This kernel is
+ // optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+4UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+4UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ const SIMDType b3( B.load(k,j+2UL) );
+ const SIMDType b4( B.load(k,j+3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C)(i ,j ) -= sum( xmm1 );
+ (~C)(i ,j+1UL) -= sum( xmm2 );
+ (~C)(i ,j+2UL) -= sum( xmm3 );
+ (~C)(i ,j+3UL) -= sum( xmm4 );
+ (~C)(i+1UL,j ) -= sum( xmm5 );
+ (~C)(i+1UL,j+1UL) -= sum( xmm6 );
+ (~C)(i+1UL,j+2UL) -= sum( xmm7 );
+ (~C)(i+1UL,j+3UL) -= sum( xmm8 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) -= A(i ,k) * B(k,j+1UL);
+ (~C)(i ,j+2UL) -= A(i ,k) * B(k,j+2UL);
+ (~C)(i ,j+3UL) -= A(i ,k) * B(k,j+3UL);
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) -= A(i+1UL,k) * B(k,j+1UL);
+ (~C)(i+1UL,j+2UL) -= A(i+1UL,k) * B(k,j+2UL);
+ (~C)(i+1UL,j+3UL) -= A(i+1UL,k) * B(k,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) -= sum( xmm1 );
+ (~C)(i ,j+1UL) -= sum( xmm2 );
+ (~C)(i+1UL,j ) -= sum( xmm3 );
+ (~C)(i+1UL,j+1UL) -= sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) -= A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) -= A(i+1UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) -= sum( xmm1 );
+ (~C)(i+1UL,j) -= sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) -= A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) -= A(i+1UL,k) * B(k,j);
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ xmm3 = xmm3 + a1 * B.load(k,j+2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+3UL);
+ }
+
+ (~C)(i,j ) -= sum( xmm1 );
+ (~C)(i,j+1UL) -= sum( xmm2 );
+ (~C)(i,j+2UL) -= sum( xmm3 );
+ (~C)(i,j+3UL) -= sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) -= A(i,k) * B(k,j );
+ (~C)(i,j+1UL) -= A(i,k) * B(k,j+1UL);
+ (~C)(i,j+2UL) -= A(i,k) * B(k,j+2UL);
+ (~C)(i,j+3UL) -= A(i,k) * B(k,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) -= sum( xmm1 );
+ (~C)(i,j+1UL) -= sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) -= A(i,k) * B(k,j );
+ (~C)(i,j+1UL) -= A(i,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) -= sum( xmm1 );
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) -= A(i,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (small matrices)**************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a dense matrix-transpose
+ // dense matrix multiplication expression to a column-major dense matrix. This kernel is
+ // optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+4UL, j+2UL ) : ( i+4UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType a3( A.load(i+2UL,k) );
+ const SIMDType a4( A.load(i+3UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C)(i ,j ) -= sum( xmm1 );
+ (~C)(i ,j+1UL) -= sum( xmm2 );
+ (~C)(i+1UL,j ) -= sum( xmm3 );
+ (~C)(i+1UL,j+1UL) -= sum( xmm4 );
+ (~C)(i+2UL,j ) -= sum( xmm5 );
+ (~C)(i+2UL,j+1UL) -= sum( xmm6 );
+ (~C)(i+3UL,j ) -= sum( xmm7 );
+ (~C)(i+3UL,j+1UL) -= sum( xmm8 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) -= A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) -= A(i+1UL,k) * B(k,j+1UL);
+ (~C)(i+2UL,j ) -= A(i+2UL,k) * B(k,j );
+ (~C)(i+2UL,j+1UL) -= A(i+2UL,k) * B(k,j+1UL);
+ (~C)(i+3UL,j ) -= A(i+3UL,k) * B(k,j );
+ (~C)(i+3UL,j+1UL) -= A(i+3UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ xmm3 = xmm3 + A.load(i+2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+3UL,k) * b1;
+ }
+
+ (~C)(i ,j) -= sum( xmm1 );
+ (~C)(i+1UL,j) -= sum( xmm2 );
+ (~C)(i+2UL,j) -= sum( xmm3 );
+ (~C)(i+3UL,j) -= sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j );
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j );
+ (~C)(i+2UL,j ) -= A(i+2UL,k) * B(k,j );
+ (~C)(i+3UL,j ) -= A(i+3UL,k) * B(k,j );
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) -= sum( xmm1 );
+ (~C)(i ,j+1UL) -= sum( xmm2 );
+ (~C)(i+1UL,j ) -= sum( xmm3 );
+ (~C)(i+1UL,j+1UL) -= sum( xmm4 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j );
+ (~C)(i ,j+1UL) -= A(i ,k) * B(k,j+1UL);
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j );
+ (~C)(i+1UL,j+1UL) -= A(i+1UL,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) -= sum( xmm1 );
+ (~C)(i+1UL,j) -= sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) -= A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) -= A(i+1UL,k) * B(k,j);
+ }
+ }
+ }
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) -= sum( xmm1 );
+ (~C)(i,j+1UL) -= sum( xmm2 );
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) -= A(i,k) * B(k,j );
+ (~C)(i,j+1UL) -= A(i,k) * B(k,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) -= sum( xmm1 );
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) -= A(i,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (large matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a dense matrix-transpose
+ // dense matrix multiplication expression to a row-major dense matrix. This kernel is
+ // optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ // TODO
+ selectSmallSubAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (large matrices)**************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a dense matrix-transpose
+ // dense matrix multiplication expression to a column-major dense matrix. This kernel is
+ // optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ // TODO
+ selectSmallSubAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subraction assignment to dense matrices******************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based subraction assignment of a dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the dense matrix-transpose dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ subAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ subAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(-1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose dense matrix multiplication to a dense
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // dense matrix multiplication expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either of
+ // the two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( rhs.lhs_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose dense matrix multiplication to a sparse
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // dense matrix multiplication expression to a sparse matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either of
+ // the two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix-
+ // transpose dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case either of the two matrix operands requires an intermediate evaluation and no symmetry
+ // can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSCALARMULTEXPR SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Expression object for scaled dense matrix-transpose dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// This specialization of the DMatScalarMultExpr class represents the compile time expression
+// for scaled multiplications between a row-major dense matrix and a column-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar value
+class DMatScalarMultExpr< DMatTDMatMultExpr<MT1,MT2>, ST, false >
+ : public DenseMatrix< DMatScalarMultExpr< DMatTDMatMultExpr<MT1,MT2>, ST, false >, false >
+ , private MatScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef DMatTDMatMultExpr<MT1,MT2> MMM; //!< Type of the dense matrix multiplication expression.
+ typedef ResultType_<MMM> RES; //!< Result type of the dense matrix multiplication expression.
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the types of all three involved matrices and the scalar type are suited for a BLAS
+ kernel, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ !( IsBuiltin< ElementType_<T1> >::value && IsComplex<T4>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all four involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3>
+ , T4 >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatScalarMultExpr<MMM,ST,false> This; //!< Type of this DMatScalarMultExpr instance.
+ typedef MultTrait_<RES,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef const DMatTDMatMultExpr<MT1,MT2> LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT1>::value && !IsDiagonal<MT2>::value &&
+ MT1::simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable<ET1,ET2,ST>::value &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatScalarMultExpr class.
+ //
+ // \param matrix The left-hand side dense matrix of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DMatScalarMultExpr( const MMM& matrix, ST scalar )
+ : matrix_( matrix ) // Left-hand side dense matrix of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ return matrix_(i,j) * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= matrix_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= matrix_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const {
+ return matrix_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const {
+ return matrix_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return matrix_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const {
+ return matrix_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return matrix_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const {
+ return matrix_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const {
+ LeftOperand_<MMM> A( matrix_.leftOperand() );
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( rows() * columns() < DMATTDMATMULT_THRESHOLD ) ) &&
+ ( A.rows() > SMP_DMATTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand matrix_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*!\brief Assignment of a scaled dense matrix-transpose dense matrix multiplication to a
+ // dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled dense matrix-
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*!\brief Selection of the kernel for an assignment of a scaled dense matrix-transpose dense
+ // matrix multiplication to a dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value || IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATTDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( C, A, B, scalar );
+ else
+ selectBlasAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (general/general)****************************
+ /*!\brief Default assignment of a scaled general dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general dense matrix-general
+ // transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const size_t ibegin( ( IsStrictlyLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT5>::value && M > 1UL ) ? 2UL : 1UL )
+ :( 0UL ) );
+ const size_t iend( ( IsStrictlyUpper<MT4>::value )
+ ?( ( IsStrictlyUpper<MT5>::value && M > 1UL ) ? M-2UL : M-1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+2UL : i+1UL )
+ :( IsStrictlyUpper<MT5>::value ? i+1UL : i ) )
+ :( IsStrictlyUpper<MT5>::value ? 1UL : 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value )
+ ?( IsStrictlyLower<MT5>::value ? i-1UL : i )
+ :( IsStrictlyLower<MT5>::value ? i : i+1UL ) )
+ :( IsStrictlyLower<MT5>::value ? N-1UL : N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) ) );
+ BLAZE_INTERNAL_ASSERT( kbegin < kend, "Invalid loop indices detected" );
+
+ (~C)(i,j) = A(i,kbegin) * B(kbegin,j);
+ for( size_t k=kbegin+1UL; k<kend; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ (~C)(i,j) *= scalar;
+ }
+ for( size_t j=jend; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=iend; i<M; ++i ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (general/general)*************************
+ /*!\brief Default assignment of a scaled general dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general dense matrix-general
+ // transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const size_t jbegin( ( IsStrictlyUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value && N > 1UL ) ? 2UL : 1UL )
+ :( 0UL ) );
+ const size_t jend( ( IsStrictlyLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value && N > 1UL ) ? N-2UL : N-1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( ( IsStrictlyLower<MT4>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+2UL : j+1UL )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsStrictlyLower<MT4>::value ? 1UL : 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT4>::value )
+ ?( ( IsStrictlyUpper<MT5>::value )?( j-1UL ):( j ) )
+ :( ( IsStrictlyUpper<MT5>::value )?( j ):( j+1UL ) ) )
+ :( IsStrictlyUpper<MT4>::value ? M-1UL : M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) ) );
+ BLAZE_INTERNAL_ASSERT( kbegin < kend, "Invalid loop indices detected" );
+
+ (~C)(i,j) = A(i,kbegin) * B(kbegin,j);
+ for( size_t k=kbegin+1UL; k<kend; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ (~C)(i,j) *= scalar;
+ }
+ for( size_t i=iend; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jend; j<N; ++j ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (general/diagonal)***************************
+ /*!\brief Default assignment of a scaled general dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general dense matrix-diagonal
+ // transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT4>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) = A(i,j) * B(j,j) * scalar;
+ }
+ if( IsLower<MT4>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (general/diagonal)************************
+ /*!\brief Default assignment of a scaled general dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general dense matrix-diagonal
+ // transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ( IsStrictlyLower<MT4>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT4>::value )
+ ?( min( ( IsStrictlyUpper<MT4>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ if( IsLower<MT4>::value ) {
+ for( size_t i=ii; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) = A(i,j) * B(j,j) * scalar;
+ }
+ if( IsUpper<MT4>::value ) {
+ for( size_t i=ipos; i<iend; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (diagonal/general)***************************
+ /*!\brief Default assignment of a scaled diagonal dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal dense matrix-general
+ // transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT5>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT5>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ if( IsUpper<MT5>::value ) {
+ for( size_t j=jj; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) = A(i,i) * B(i,j) * scalar;
+ }
+ if( IsLower<MT5>::value ) {
+ for( size_t j=jpos; j<jend; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (diagonal/general)************************
+ /*!\brief Default assignment of a scaled diagonal dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal dense matrix-general
+ // transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT5>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) = A(i,i) * B(i,j) * scalar;
+ }
+ if( IsUpper<MT5>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/diagonal)************************************
+ /*!\brief Default assignment of a scaled diagonal dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal dense matrix-diagonal
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) = A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*!\brief Default assignment of a small scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (small matrices)******************
+ /*!\brief Vectorized default assignment of a small scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a small scaled dense matrix-
+ // transpose dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+4UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+4UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ const SIMDType b3( B.load(k,j+2UL) );
+ const SIMDType b4( B.load(k,j+3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C)(i ,j ) = sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) = sum( xmm2 ) * scalar;
+ (~C)(i ,j+2UL) = sum( xmm3 ) * scalar;
+ (~C)(i ,j+3UL) = sum( xmm4 ) * scalar;
+ (~C)(i+1UL,j ) = sum( xmm5 ) * scalar;
+ (~C)(i+1UL,j+1UL) = sum( xmm6 ) * scalar;
+ (~C)(i+1UL,j+2UL) = sum( xmm7 ) * scalar;
+ (~C)(i+1UL,j+3UL) = sum( xmm8 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i ,j+2UL) += A(i ,k) * B(k,j+2UL) * scalar;
+ (~C)(i ,j+3UL) += A(i ,k) * B(k,j+3UL) * scalar;
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j+2UL) += A(i+1UL,k) * B(k,j+2UL) * scalar;
+ (~C)(i+1UL,j+3UL) += A(i+1UL,k) * B(k,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) = sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) = sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) = sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) = sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) = sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) = sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ xmm3 = xmm3 + a1 * B.load(k,j+2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+3UL);
+ }
+
+ (~C)(i,j ) = sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) = sum( xmm2 ) * scalar;
+ (~C)(i,j+2UL) = sum( xmm3 ) * scalar;
+ (~C)(i,j+3UL) = sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL) * scalar;
+ (~C)(i,j+2UL) += A(i,k) * B(k,j+2UL) * scalar;
+ (~C)(i,j+3UL) += A(i,k) * B(k,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) = sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) = sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) = sum( xmm1 ) * scalar;
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j) * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (small matrices)***************
+ /*!\brief Vectorized default assignment of a small scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a small scaled dense matrix-
+ // transpose dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+4UL, j+2UL ) : ( i+4UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType a3( A.load(i+2UL,k) );
+ const SIMDType a4( A.load(i+3UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C)(i ,j ) = sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) = sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) = sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) = sum( xmm4 ) * scalar;
+ (~C)(i+2UL,j ) = sum( xmm5 ) * scalar;
+ (~C)(i+2UL,j+1UL) = sum( xmm6 ) * scalar;
+ (~C)(i+3UL,j ) = sum( xmm7 ) * scalar;
+ (~C)(i+3UL,j+1UL) = sum( xmm8 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+2UL,j ) += A(i+2UL,k) * B(k,j ) * scalar;
+ (~C)(i+2UL,j+1UL) += A(i+2UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+3UL,j ) += A(i+3UL,k) * B(k,j ) * scalar;
+ (~C)(i+3UL,j+1UL) += A(i+3UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ xmm3 = xmm3 + A.load(i+2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+3UL,k) * b1;
+ }
+
+ (~C)(i ,j) = sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) = sum( xmm2 ) * scalar;
+ (~C)(i+2UL,j) = sum( xmm3 ) * scalar;
+ (~C)(i+3UL,j) = sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j) * scalar;
+ (~C)(i+2UL,j) += A(i+2UL,k) * B(k,j) * scalar;
+ (~C)(i+3UL,j) += A(i+3UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) = sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) = sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) = sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) = sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) = sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) = sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) = sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) = sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) = sum( xmm1 ) * scalar;
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j) * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*!\brief Default assignment of a large scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (large matrices)******************
+ /*!\brief Vectorized default assignment of a large scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled dense matrix-
+ // transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ // TODO
+ selectSmallAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (large matrices)***************
+ /*!\brief Vectorized default assignment of a large scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled dense matrix-
+ // transpose dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ // TODO
+ selectSmallAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices (default)*******************************************
+ /*!\brief Default assignment of a scaled dense matrix-transpose dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large scaled
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices*****************************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based assignment of a scaled dense matrix-transpose dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-transpose dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ assign( C, B );
+ trmm( C, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ assign( C, A );
+ trmm( C, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ }
+ else {
+ gemm( C, A, B, ET(scalar), ET(0) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*!\brief Assignment of a scaled dense matrix-transpose dense matrix multiplication to a
+ // sparse matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled dense matrix-
+ // transpose dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*!\brief Addition assignment of a scaled dense matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectAddAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*!\brief Selection of the kernel for an addition assignment of a scaled dense matrix-
+ // transpose dense matrix multiplication to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value || IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATTDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( C, A, B, scalar );
+ else
+ selectBlasAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/general)*****************************
+ /*!\brief Default addition assignment of a scaled general dense matrix-general transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general dense matrix-
+ // general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const ResultType tmp( serial( A * B * scalar ) );
+ addAssign( C, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (general/diagonal)******************
+ /*!\brief Default addition assignment of a scaled general dense matrix-diagonal transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) += A(i,j ) * B(j ,j ) * scalar;
+ (~C)(i,j+1UL) += A(i,j+1UL) * B(j+1UL,j+1UL) * scalar;
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) += A(i,jpos) * B(jpos,jpos) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (general/diagonal)***************
+ /*!\brief Default addition assignment of a scaled general dense matrix-diagonal transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ( IsStrictlyLower<MT4>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT4>::value )
+ ?( min( ( IsStrictlyUpper<MT4>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) += A(i,j) * B(j,j) * scalar;
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (diagonal/general)******************
+ /*!\brief Default addition assignment of a scaled diagonal dense matrix-general transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal dense matrix-
+ // general transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT5>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT5>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) += A(i,i) * B(i,j) * scalar;
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (diagonal/general)***************
+ /*!\brief Default addition assignment of a scaled diagonal dense matrix-general transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal dense matrix-
+ // general transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) += A(i ,i ) * B(i ,j) * scalar;
+ (~C)(i+1UL,j) += A(i+1UL,i+1UL) * B(i+1UL,j) * scalar;
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) += A(ipos,ipos) * B(ipos,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/diagonal)***************************
+ /*!\brief Default addition assignment of a scaled diagonal dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) += A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*!\brief Default addition assignment of a small scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (small matrices)*********
+ /*!\brief Vectorized default addition assignment of a small scaled dense matrix-transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+4UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+4UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ const SIMDType b3( B.load(k,j+2UL) );
+ const SIMDType b4( B.load(k,j+3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C)(i ,j ) += sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) += sum( xmm2 ) * scalar;
+ (~C)(i ,j+2UL) += sum( xmm3 ) * scalar;
+ (~C)(i ,j+3UL) += sum( xmm4 ) * scalar;
+ (~C)(i+1UL,j ) += sum( xmm5 ) * scalar;
+ (~C)(i+1UL,j+1UL) += sum( xmm6 ) * scalar;
+ (~C)(i+1UL,j+2UL) += sum( xmm7 ) * scalar;
+ (~C)(i+1UL,j+3UL) += sum( xmm8 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i ,j+2UL) += A(i ,k) * B(k,j+2UL) * scalar;
+ (~C)(i ,j+3UL) += A(i ,k) * B(k,j+3UL) * scalar;
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j+2UL) += A(i+1UL,k) * B(k,j+2UL) * scalar;
+ (~C)(i+1UL,j+3UL) += A(i+1UL,k) * B(k,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) += sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) += sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) += sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) += sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) += sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) += sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ xmm3 = xmm3 + a1 * B.load(k,j+2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+3UL);
+ }
+
+ (~C)(i,j ) += sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) += sum( xmm2 ) * scalar;
+ (~C)(i,j+2UL) += sum( xmm3 ) * scalar;
+ (~C)(i,j+3UL) += sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL) * scalar;
+ (~C)(i,j+2UL) += A(i,k) * B(k,j+2UL) * scalar;
+ (~C)(i,j+3UL) += A(i,k) * B(k,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) += sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) += sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) += sum( xmm1 ) * scalar;
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j) * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (small matrices)******
+ /*!\brief Vectorized default addition assignment of a small scaled dense matrix-transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+4UL, j+2UL ) : ( i+4UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType a3( A.load(i+2UL,k) );
+ const SIMDType a4( A.load(i+3UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C)(i ,j ) += sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) += sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) += sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) += sum( xmm4 ) * scalar;
+ (~C)(i+2UL,j ) += sum( xmm5 ) * scalar;
+ (~C)(i+2UL,j+1UL) += sum( xmm6 ) * scalar;
+ (~C)(i+3UL,j ) += sum( xmm7 ) * scalar;
+ (~C)(i+3UL,j+1UL) += sum( xmm8 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+2UL,j ) += A(i+2UL,k) * B(k,j ) * scalar;
+ (~C)(i+2UL,j+1UL) += A(i+2UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+3UL,j ) += A(i+3UL,k) * B(k,j ) * scalar;
+ (~C)(i+3UL,j+1UL) += A(i+3UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ xmm3 = xmm3 + A.load(i+2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+3UL,k) * b1;
+ }
+
+ (~C)(i ,j) += sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) += sum( xmm2 ) * scalar;
+ (~C)(i+2UL,j) += sum( xmm3 ) * scalar;
+ (~C)(i+3UL,j) += sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j) * scalar;
+ (~C)(i+2UL,j) += A(i+2UL,k) * B(k,j) * scalar;
+ (~C)(i+3UL,j) += A(i+3UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) += sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) += sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) += sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) += sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) += A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) += A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) += A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) += A(i+1UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) += sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) += sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) += sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) += sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) += A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) += sum( xmm1 ) * scalar;
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) += A(i,k) * B(k,j) * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*!\brief Default addition assignment of a large scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (large matrices)*********
+ /*!\brief Vectorized default addition assignment of a large scaled dense matrix-transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ // TODO
+ selectSmallAddAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (large matrices)******
+ /*!\brief Vectorized default addition assignment of a large scaled dense matrix-transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ // TODO
+ selectSmallAddAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices (default)**********************************
+ /*!\brief Default addition assignment of a scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // scaled dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices********************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based addition assignment of a scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-transpose dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ addAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ addAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*!\brief Subtraction assignment of a scaled dense matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectSubAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*!\brief Selection of the kernel for a subtraction assignment of a scaled dense matrix-
+ // transpose dense matrix multiplication to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value || IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < DMATTDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( C, A, B, scalar );
+ else
+ selectBlasSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/general)**************************
+ /*!\brief Default subtraction assignment of a scaled general dense matrix-general transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general dense matrix-
+ // general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const ResultType tmp( serial( A * B * scalar ) );
+ subAssign( C, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (general/diagonal)***************
+ /*!\brief Default subtraction assignment of a scaled general dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) -= A(i,j ) * B(j ,j ) * scalar;
+ (~C)(i,j+1UL) -= A(i,j+1UL) * B(j+1UL,j+1UL) * scalar;
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) -= A(i,jpos) * B(jpos,jpos) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (general/diagonal)************
+ /*!\brief Default subtraction assignment of a scaled general dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ( IsStrictlyLower<MT4>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT4>::value )
+ ?( min( ( IsStrictlyUpper<MT4>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) -= A(i,j) * B(j,j) * scalar;
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (diagonal/general)***************
+ /*!\brief Default subtraction assignment of a scaled diagonal dense matrix-general transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal dense
+ // matrix-general transpose dense matrix multiplication expression to a row-major dense
+ // matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT5>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT5>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) -= A(i,i) * B(i,j) * scalar;
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (diagonal/general)************
+ /*!\brief Default subtraction assignment of a scaled diagonal dense matrix-general transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal dense
+ // matrix-general transpose dense matrix multiplication expression to a column-major dense
+ // matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) -= A(i ,i ) * B(i ,j) * scalar;
+ (~C)(i+1UL,j) -= A(i+1UL,i+1UL) * B(i+1UL,j) * scalar;
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) -= A(ipos,ipos) * B(ipos,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/diagonal)************************
+ /*!\brief Default subtraction assignment of a scaled diagonal dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal dense
+ // matrix-diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) -= A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*!\brief Default subtraction assignment of a small scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (small matrices)******
+ /*!\brief Vectorized default subtraction assignment of a small scaled dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+4UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+4UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ const SIMDType b3( B.load(k,j+2UL) );
+ const SIMDType b4( B.load(k,j+3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C)(i ,j ) -= sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) -= sum( xmm2 ) * scalar;
+ (~C)(i ,j+2UL) -= sum( xmm3 ) * scalar;
+ (~C)(i ,j+3UL) -= sum( xmm4 ) * scalar;
+ (~C)(i+1UL,j ) -= sum( xmm5 ) * scalar;
+ (~C)(i+1UL,j+1UL) -= sum( xmm6 ) * scalar;
+ (~C)(i+1UL,j+2UL) -= sum( xmm7 ) * scalar;
+ (~C)(i+1UL,j+3UL) -= sum( xmm8 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) -= A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i ,j+2UL) -= A(i ,k) * B(k,j+2UL) * scalar;
+ (~C)(i ,j+3UL) -= A(i ,k) * B(k,j+3UL) * scalar;
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) -= A(i+1UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j+2UL) -= A(i+1UL,k) * B(k,j+2UL) * scalar;
+ (~C)(i+1UL,j+3UL) -= A(i+1UL,k) * B(k,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) -= sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) -= sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) -= sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) -= sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) -= A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) -= A(i+1UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) -= sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) -= sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) -= A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) -= A(i+1UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ xmm3 = xmm3 + a1 * B.load(k,j+2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+3UL);
+ }
+
+ (~C)(i,j ) -= sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) -= sum( xmm2 ) * scalar;
+ (~C)(i,j+2UL) -= sum( xmm3 ) * scalar;
+ (~C)(i,j+3UL) -= sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) -= A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) -= A(i,k) * B(k,j+1UL) * scalar;
+ (~C)(i,j+2UL) -= A(i,k) * B(k,j+2UL) * scalar;
+ (~C)(i,j+3UL) -= A(i,k) * B(k,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) -= sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) -= sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) -= A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) -= A(i,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) -= sum( xmm1 ) * scalar;
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) -= A(i,k) * B(k,j) * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (small matrices)***
+ /*!\brief Vectorized default subtraction assignment of a small scaled dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT4>::value || !IsPadded<MT5>::value );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= M; i+=4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+4UL, j+2UL ) : ( i+4UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE )
+ {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType a3( A.load(i+2UL,k) );
+ const SIMDType a4( A.load(i+3UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C)(i ,j ) -= sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) -= sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) -= sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) -= sum( xmm4 ) * scalar;
+ (~C)(i+2UL,j ) -= sum( xmm5 ) * scalar;
+ (~C)(i+2UL,j+1UL) -= sum( xmm6 ) * scalar;
+ (~C)(i+3UL,j ) -= sum( xmm7 ) * scalar;
+ (~C)(i+3UL,j+1UL) -= sum( xmm8 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) -= A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) -= A(i+1UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+2UL,j ) -= A(i+2UL,k) * B(k,j ) * scalar;
+ (~C)(i+2UL,j+1UL) -= A(i+2UL,k) * B(k,j+1UL) * scalar;
+ (~C)(i+3UL,j ) -= A(i+3UL,k) * B(k,j ) * scalar;
+ (~C)(i+3UL,j+1UL) -= A(i+3UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+4UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ xmm3 = xmm3 + A.load(i+2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+3UL,k) * b1;
+ }
+
+ (~C)(i ,j) -= sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) -= sum( xmm2 ) * scalar;
+ (~C)(i+2UL,j) -= sum( xmm3 ) * scalar;
+ (~C)(i+3UL,j) -= sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) -= A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) -= A(i+1UL,k) * B(k,j) * scalar;
+ (~C)(i+2UL,j) -= A(i+2UL,k) * B(k,j) * scalar;
+ (~C)(i+3UL,j) -= A(i+3UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsUpper<MT5>::value ? min( i+2UL, j+2UL ) : ( i+2UL ) )
+ :( IsUpper<MT5>::value ? ( j+2UL ) : K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+1UL,k) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+1UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C)(i ,j ) -= sum( xmm1 ) * scalar;
+ (~C)(i ,j+1UL) -= sum( xmm2 ) * scalar;
+ (~C)(i+1UL,j ) -= sum( xmm3 ) * scalar;
+ (~C)(i+1UL,j+1UL) -= sum( xmm4 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j ) -= A(i ,k) * B(k,j ) * scalar;
+ (~C)(i ,j+1UL) -= A(i ,k) * B(k,j+1UL) * scalar;
+ (~C)(i+1UL,j ) -= A(i+1UL,k) * B(k,j ) * scalar;
+ (~C)(i+1UL,j+1UL) -= A(i+1UL,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( i+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+1UL,k) * b1;
+ }
+
+ (~C)(i ,j) -= sum( xmm1 ) * scalar;
+ (~C)(i+1UL,j) -= sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i ,j) -= A(i ,k) * B(k,j) * scalar;
+ (~C)(i+1UL,j) -= A(i+1UL,k) * B(k,j) * scalar;
+ }
+ }
+ }
+
+ if( i < M )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( j+2UL ):( K ) );
+
+ const size_t kpos( remainder ? ( kend & size_t(-SIMDSIZE) ) : kend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( kend - ( kend % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+1UL);
+ }
+
+ (~C)(i,j ) -= sum( xmm1 ) * scalar;
+ (~C)(i,j+1UL) -= sum( xmm2 ) * scalar;
+
+ for( ; remainder && k<kend; ++k ) {
+ (~C)(i,j ) -= A(i,k) * B(k,j ) * scalar;
+ (~C)(i,j+1UL) -= A(i,k) * B(k,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) )
+ :( IsLower<MT5>::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) );
+
+ const size_t kpos( remainder ? ( K & size_t(-SIMDSIZE) ) : K );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( K - ( K % (SIMDSIZE) ) ) == kpos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t k( kbegin );
+
+ for( ; k<kpos; k+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,k) * B.load(k,j);
+ }
+
+ (~C)(i,j) -= sum( xmm1 ) * scalar;
+
+ for( ; remainder && k<K; ++k ) {
+ (~C)(i,j) -= A(i,k) * B(k,j) * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*!\brief Default subtraction assignment of a large scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (large matrices)******
+ /*!\brief Vectorized default subtraction assignment of a large scaled dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ // TODO
+ selectSmallSubAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (large matrices)***
+ /*!\brief Vectorized default subtraction assignment of a large scaled dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ // TODO
+ selectSmallSubAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense matrices (default)*******************************
+ /*!\brief Default subtraction assignment of a scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // scaled dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subraction assignment to dense matrices******************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based subraction assignment of a scaled dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled dense matrix-transpose dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ subAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ subAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(-scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*!\brief SMP Assignment of a scaled dense matrix-transpose dense matrix multiplication to a
+ // dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled dense matrix-
+ // transpose dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*!\brief SMP assignment of a scaled dense matrix-transpose dense matrix multiplication to a
+ // sparse matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled dense matrix-
+ // transpose dense matrix multiplication expression to a sparse matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*!\brief SMP addition assignment of a scaled dense matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a scaled
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*!\brief SMP subtraction assignment of a scaled dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a scaled
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MMM );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MMM );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major dense matrix and a
+// column-major dense matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side matrix for the multiplication.
+// \param rhs The right-hand side matrix for the multiplication.
+// \return The resulting matrix.
+//
+// This operator represents the multiplication of a row-major dense matrix and a column-major
+// dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, C;
+ blaze::DynamicMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current number of columns of \a lhs and the current number of rows of \a rhs
+// don't match, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const DMatTDMatMultExpr<T1,T2>
+ operator*( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< DMatTDMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< DMatTDMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< DMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsAligned<MT1>, IsAligned<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< DMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< DMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< DMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< DMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< DMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< DMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatDVecMultExprTrait< DMatTDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , DMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatSVecMultExprTrait< DMatTDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , DMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecDMatMultExprTrait< VT, DMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTDMatMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecDMatMultExprTrait< VT, DMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTDMatMultExprTrait_< TSVecDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< DMatTDMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< DMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< DMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatTDMatSubExpr.h b/src/cpu/blaze/math/expressions/DMatTDMatSubExpr.h
new file mode 100644
index 00000000..5c2d4ed5
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatTDMatSubExpr.h
@@ -0,0 +1,1264 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatTDMatSubExpr.h
+// \brief Header file for the dense matrix/transpose dense matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATTDMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATTDMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATTDMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-transpose dense matrix subtractions.
+// \ingroup dense_matrix_expression
+//
+// The DMatTDMatSubExpr class represents the compile time expression for subtractions between
+// a row-major dense matrix and a column-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class DMatTDMatSubExpr : public DenseMatrix< DMatTDMatSubExpr<MT1,MT2>, false >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the subtraction expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for the
+ serial evaluation strategy of the subtraction expression. In case either of the two dense
+ matrix operands requires an intermediate evaluation or the subscript operator can only
+ return by value, \a useAssign will be set to 1 and the subtraction expression will be
+ evaluated via the \a assign function family. Otherwise \a useAssign will be set to 0
+ and the expression will be evaluated via the function call operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT1>::value || RequiresEvaluation<MT2>::value || !returnExpr };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable and at
+ least one of the two operands requires an intermediate evaluation, \a value is set to 1
+ and the expression specific evaluation strategy is selected. Otherwise \a value is set
+ to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTDMatSubExpr<MT1,MT2> This; //!< Type of this DMatTDMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT1::smpAssignable && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTDMatSubExpr class.
+ //
+ // \param lhs The left-hand side operand of the subtraction expression.
+ // \param rhs The right-hand side operand of the subtraction expression.
+ */
+ explicit inline DMatTDMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && ( RequiresEvaluation<MT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
+ ( IsExpression<MT2>::value && ( RequiresEvaluation<MT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
+ ( rows() > SMP_DMATTDMATSUB_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // dense matrix subtraction expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case neither
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline DisableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ (~lhs)(i,j) = rhs.lhs_(i,j) - rhs.rhs_(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // dense matrix subtraction expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // dense matrix subtraction expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-transpose dense matrix subtraction to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case neither of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline DisableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ (~lhs)(i,j) += rhs.lhs_(i,j) - rhs.rhs_(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-transpose dense matrix subtraction to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // matrix-transpose dense matrix subtraction expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case neither of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline DisableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ (~lhs)(i,j) -= rhs.lhs_(i,j) - rhs.rhs_(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // matrix-transpose dense matrix subtraction expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-
+ // transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-
+ // transpose dense matrix subtraction expression to a sparse matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_DIFFERENT_STORAGE_ORDER( MT1, MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a row-major and a column-major dense matrix
+// (\f$ A=B-C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the left-hand side matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the subtraction of a row-major and a column-major dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, C;
+ blaze::DynamicMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< And< Not< IsSymmetric<T1> >, Not< IsSymmetric<T2> > >
+ , const DMatTDMatSubExpr<T1,T2> >
+ operator-( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTDMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a column-major and a row-major dense matrix
+// (\f$ A=B-C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the left-hand side matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the subtraction of a column-major and a row-major dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,columnMajor> A;
+ blaze::DynamicMatrix<double,rowMajor> B, C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< And< Not< IsSymmetric<T1> >, Not< IsSymmetric<T2> > >
+ , const DMatTDMatSubExpr<T1,T2> >
+ operator-( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTDMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a symmetric row-major and a colum-major dense
+// matrix (\f$ A=B-C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the left-hand side matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator implements a performance optimized treatment of the subtraction of a symmetric
+// row-major dense matrix and a column-major dense matrix.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< And< IsSymmetric<T1>, Not< IsSymmetric<T2> > >, const SubExprTrait_<T1,T2> >
+ operator-( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return trans( ~lhs ) - ~rhs;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a row-major and a symmetric column-major
+// dense matrix (\f$ A=B-C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator implements a performance optimized treatment of the subtraction of a (potentially
+// symmetric) row-major dense matrix and a symmetric column-major dense matrix.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< IsSymmetric<T2>, const SubExprTrait_<T1,T2> >
+ operator-( const DenseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return (~lhs) - trans( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a column-major and a symmetric row-major
+// dense matrix (\f$ A=B-C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator implements a performance optimized treatment of the subtraction of a column-major
+// dense matrix and a symmetric row-major dense matrix.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< And< Not< IsSymmetric<T1> >, IsSymmetric<T2> >, const SubExprTrait_<T1,T2> >
+ operator-( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return (~lhs) - trans( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a symmetric column-major and a row-major
+// dense matrix (\f$ A=B-C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator implements a performance optimized treatment of the subtraction of a symmetric
+// column-major dense matrix and a (potentially symmetric) row-major dense matrix.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline EnableIf_< IsSymmetric<T1>, const SubExprTrait_<T1,T2> >
+ operator-( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return trans( ~lhs ) - (~rhs);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< DMatTDMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< DMatTDMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsAligned<MT1>, IsAligned<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< DMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< DMatTDMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< DMatTDMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< DMatTDMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatTSMatAddExpr.h b/src/cpu/blaze/math/expressions/DMatTSMatAddExpr.h
new file mode 100644
index 00000000..13a18ad9
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatTSMatAddExpr.h
@@ -0,0 +1,1080 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatTSMatAddExpr.h
+// \brief Header file for the dense matrix/transpose sparse matrix addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATTSMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATTSMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATTSMATADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-sparse matrix additions.
+// \ingroup dense_matrix_expression
+//
+// The DMatTSMatAddExpr class represents the compile time expression for additions between
+// a row-major dense matrix and a column-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class DMatTSMatAddExpr : public DenseMatrix< DMatTSMatAddExpr<MT1,MT2>, false >
+ , private MatMatAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTSMatAddExpr<MT1,MT2> This; //!< Type of this DMatTSMatAddExpr instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTSMatAddExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the addition expression.
+ // \param rhs The right-hand side sparse matrix operand of the addition expression.
+ */
+ explicit inline DMatTSMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the addition expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) + rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && lhs_.canAlias( alias ) ) ||
+ ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the addition expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose sparse matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // sparse matrix addition expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-transpose sparse matrix addition to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-transpose sparse matrix addition to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // transpose sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // sparse matrix addition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose sparse matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // sparse matrix addition expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-transpose sparse matrix addition to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose sparse matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-transpose sparse matrix addition to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-transpose sparse matrix addition expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a row-major dense matrix and a column-major
+// sparse matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the addition of a row-major dense matrix and a column-major sparse
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+const DMatTSMatAddExpr<T1,T2>
+ operator+( const DenseMatrix<T1,false>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTSMatAddExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a column-major sparse matrix and a row-major
+// dense matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the addition of a column-major sparse matrix and a row-major dense
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,columnMajor> A;
+ blaze::DynamicMatrix<double,rowMajor> B, C;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+const DMatTSMatAddExpr<T1,T2>
+ operator+( const SparseMatrix<T2,true>& lhs, const DenseMatrix<T1,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTSMatAddExpr<T1,T2>( ~rhs, ~lhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a dense matrix-transpose sparse matrix
+// addition expression and a dense matrix (\f$ A=(B+C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-transpose sparse matrix addition.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a dense
+// matrix-transpose sparse matrix addition expression to a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< DMatTSMatAddExpr<T1,T2>, T3 >
+ operator+( const DMatTSMatAddExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() + (~rhs) ) + lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a dense matrix-transpose sparse matrix
+// addition expression and a dense matrix (\f$ A=(B+C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-transpose sparse matrix addition.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a dense
+// matrix-transpose sparse matrix addition expression and a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< DMatTSMatAddExpr<T1,T2>, T3 >
+ operator-( const DMatTSMatAddExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() - (~rhs) ) + lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< DMatTSMatAddExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< DMatTSMatAddExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< DMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< DMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< DMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< DMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >
+ , And< IsUniLower<MT2>, IsStrictlyLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< DMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< DMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< DMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >
+ , And< IsUniUpper<MT2>, IsStrictlyUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< DMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< DMatTSMatAddExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< DMatDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< DMatTSMatAddExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< DMatTDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< DMatTSMatAddExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< DMatDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< DMatTSMatAddExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< DMatTDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< DMatTSMatAddExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< DMatTSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< DMatTSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatTSMatMultExpr.h b/src/cpu/blaze/math/expressions/DMatTSMatMultExpr.h
new file mode 100644
index 00000000..0121f266
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatTSMatMultExpr.h
@@ -0,0 +1,2075 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatTSMatMultExpr.h
+// \brief Header file for the dense matrix/transpose sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATTSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-transpose sparse matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The DMatTSMatMultExpr class represents the compile time expression for multiplications between
+// a row-major dense matrix and a column-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class DMatTSMatMultExpr : public DenseMatrix< DMatTSMatMultExpr<MT1,MT2>, false >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the left-hand side matrix operand of type \a T2 is
+ symmetric, \a value is set to 1 and an optimized evaluation strategy is selected.
+ Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsSymmetric<T2>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the left-hand side matrix is not a diagonal and a loop-unrolled computation is
+ feasible, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !IsResizable<ET2>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTSMatMultExpr<MT1,MT2> This; //!< Type of this DMatTSMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTSMatMultExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the multiplication expression.
+ // \param rhs The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline DMatTSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_DMATTSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose sparse matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense matrix-transpose sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the dense matrix-transpose
+ // sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jend( min( jj+block, B.columns() ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= A.rows(); i+=4UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
+ :( B.end(j) ) );
+
+ if( element == end ) {
+ reset( C(i ,j) );
+ reset( C(i+1UL,j) );
+ reset( C(i+2UL,j) );
+ reset( C(i+3UL,j) );
+ continue;
+ }
+
+ C(i ,j) = A(i ,element->index()) * element->value();
+ C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
+ C(i+2UL,j) = A(i+2UL,element->index()) * element->value();
+ C(i+3UL,j) = A(i+3UL,element->index()) * element->value();
+ ++element;
+ for( ; element!=end; ++element ) {
+ C(i ,j) += A(i ,element->index()) * element->value();
+ C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
+ C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
+ C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= A.rows(); i+=2UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
+ :( B.end(j) ) );
+
+ if( element == end ) {
+ reset( C(i ,j) );
+ reset( C(i+1UL,j) );
+ continue;
+ }
+
+ C(i ,j) = A(i ,element->index()) * element->value();
+ C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
+ ++element;
+ for( ; element!=end; ++element ) {
+ C(i ,j) += A(i ,element->index()) * element->value();
+ C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
+ }
+ }
+ }
+
+ for( ; i<A.rows(); ++i ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
+ :( B.end(j) ) );
+
+ if( element == end ) {
+ reset( C(i,j) );
+ continue;
+ }
+
+ C(i,j) = A(i,element->index()) * element->value();
+ ++element;
+ for( ; element!=end; ++element )
+ C(i,j) += A(i,element->index()) * element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a dense matrix-transpose sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the optimized assignment kernel for the dense matrix-transpose
+ // sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
+
+ reset( C );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jend( min( jj+block, B.columns() ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= A.rows(); i+=4UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
+ C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i ,j) += A(i ,j1) * v1;
+ C(i+1UL,j) += A(i+1UL,j1) * v1;
+ C(i+2UL,j) += A(i+2UL,j1) * v1;
+ C(i+3UL,j) += A(i+3UL,j1) * v1;
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= A.rows(); i+=2UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i ,j) += A(i ,j1) * v1;
+ C(i+1UL,j) += A(i+1UL,j1) * v1;
+ }
+ }
+ }
+
+ for( ; i<A.rows(); ++i ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i,j) += A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose sparse matrix multiplication to a sparse
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // sparse matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a dense matrix-transpose sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a dense matrix-
+ // transpose sparse matrix multiplication expression. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case the symmetry
+ // of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-transpose sparse matrix multiplication to a
+ // dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a dense matrix-transpose sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the dense matrix-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jend( min( jj+block, B.columns() ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= A.rows(); i+=4UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
+ :( B.end(j) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i ,j) += A(i ,element->index()) * element->value();
+ C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
+ C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
+ C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= A.rows(); i+=2UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
+ :( B.end(j) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i ,j) += A(i ,element->index()) * element->value();
+ C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
+ }
+ }
+ }
+
+ for( ; i<A.rows(); ++i ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
+ :( B.end(j) ) );
+
+ for( ; element!=end; ++element )
+ C(i,j) += A(i,element->index()) * element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a dense matrix-transpose sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the optimized addition assignment kernel for the dense matrix-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jend( min( jj+block, B.columns() ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= A.rows(); i+=4UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
+ C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i ,j) += A(i ,j1) * v1;
+ C(i+1UL,j) += A(i+1UL,j1) * v1;
+ C(i+2UL,j) += A(i+2UL,j1) * v1;
+ C(i+3UL,j) += A(i+3UL,j1) * v1;
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= A.rows(); i+=2UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i ,j) += A(i ,j1) * v1;
+ C(i+1UL,j) += A(i+1UL,j1) * v1;
+ }
+ }
+ }
+
+ for( ; i<A.rows(); ++i ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i,j) += A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a dense matrix-transpose sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a dense
+ // matrix-transpose sparse matrix multiplication expression. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case the
+ // symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-transpose sparse matrix multiplication to a
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // transpose sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a dense matrix-transpose sparse matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the dense matrix-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jend( min( jj+block, B.columns() ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= A.rows(); i+=4UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
+ :( B.end(j) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i ,j) -= A(i ,element->index()) * element->value();
+ C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
+ C(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
+ C(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= A.rows(); i+=2UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
+ :( B.end(j) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i ,j) -= A(i ,element->index()) * element->value();
+ C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
+ }
+ }
+ }
+
+ for( ; i<A.rows(); ++i ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
+ :( B.end(j) ) );
+
+ for( ; element!=end; ++element )
+ C(i,j) -= A(i,element->index()) * element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a dense matrix-transpose sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the optimized subtraction assignment kernel for the dense matrix-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jend( min( jj+block, B.columns() ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+4UL) <= A.rows(); i+=4UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ C(i+2UL,j) -= A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
+ C(i+3UL,j) -= A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i ,j) -= A(i ,j1) * v1;
+ C(i+1UL,j) -= A(i+1UL,j1) * v1;
+ C(i+2UL,j) -= A(i+2UL,j1) * v1;
+ C(i+3UL,j) -= A(i+3UL,j1) * v1;
+ }
+ }
+ }
+
+ for( ; (i+2UL) <= A.rows(); i+=2UL ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i ,j) -= A(i ,j1) * v1;
+ C(i+1UL,j) -= A(i+1UL,j1) * v1;
+ }
+ }
+ }
+
+ for( ; i<A.rows(); ++i ) {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ ConstIterator element( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
+ :( B.begin(j) ) );
+ const ConstIterator end( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
+ :( B.end(j) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ C(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ C(i,j) -= A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a dense matrix-transpose sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a dense
+ // matrix-transpose sparse matrix multiplication expression. Due to the explicit application of
+ // the SFINAE principle this function can only be selected by the compiler in case the symmetry
+ // of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose sparse matrix multiplication to a dense
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // sparse matrix multiplication expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose sparse matrix multiplication to a sparse
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // sparse matrix multiplication expression to a sparse matrix. Due to the explicit application of
+ // the SFINAE principle this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a dense matrix-transpose sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a dense matrix-
+ // transpose sparse matrix multiplication expression. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case the symmetry of
+ // either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-transpose sparse matrix multiplication to a
+ // dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense matrix-
+ // transpose sparse matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case either of the two matrix operands requires an intermediate evaluation and no symmetry
+ // can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a dense matrix-transpose sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a dense
+ // matrix-transpose sparse matrix multiplication expression. Due to the explicit application of
+ // the SFINAE principle this function can only be selected by the compiler in case the symmetry
+ // of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-transpose sparse matrix multiplication
+ // to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-transpose sparse matrix multiplication expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a dense matrix-transpose sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of
+ // a dense matrix-transpose sparse matrix multiplication expression. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major dense matrix and a
+// column-major sparse matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the multiplication.
+// \param rhs The right-hand side sparse matrix for the multiplication.
+// \return The resulting matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the multiplication of a row-major dense matrix and a column-major
+// sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const DMatTSMatMultExpr<T1,T2>
+ operator*( const DenseMatrix<T1,false>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< DMatTSMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< DMatTSMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< DMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsAligned<MT1>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< DMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsLower<MT1>::value && IsLower<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< DMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsUniLower<MT1>::value && IsUniLower<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< DMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< DMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsUpper<MT1>::value && IsUpper<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< DMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsUniUpper<MT1>::value && IsUniUpper<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< DMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatDVecMultExprTrait< DMatTSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , DMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatSVecMultExprTrait< DMatTSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , DMatSVecMultExprTrait_< MT1, TSMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecDMatMultExprTrait< VT, DMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTSMatMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecDMatMultExprTrait< VT, DMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTSMatMultExprTrait_< TSVecDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< DMatTSMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< DMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< DMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatTSMatSubExpr.h b/src/cpu/blaze/math/expressions/DMatTSMatSubExpr.h
new file mode 100644
index 00000000..b225aa4e
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatTSMatSubExpr.h
@@ -0,0 +1,1031 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatTSMatSubExpr.h
+// \brief Header file for the dense matrix/transpose sparse matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATTSMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATTSMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATTSMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-transpose sparse matrix subtractions.
+// \ingroup dense_matrix_expression
+//
+// The DMatTSMatSubExpr class represents the compile time expression for subtractions between
+// a row-major dense matrix and a column-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class DMatTSMatSubExpr : public DenseMatrix< DMatTSMatSubExpr<MT1,MT2>, false >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTSMatSubExpr<MT1,MT2> This; //!< Type of this DMatTSMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTSMatSubExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the subtraction expression.
+ // \param rhs The right-hand side sparse matrix operand of the subtraction expression.
+ */
+ explicit inline DMatTSMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && lhs_.canAlias( alias ) ) ||
+ ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix-transpose sparse matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix-transpose
+ // sparse matrix subtraction expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix-transpose sparse matrix subtraction to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense matrix-
+ // transpose sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix-transpose sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense matrix-
+ // transpose sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // sparse matrix subtraction expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix-transpose sparse matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix-transpose
+ // sparse matrix subtraction expression to a sparse matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const DMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix-transpose sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix-transpose sparse matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix-transpose sparse matrix subtraction to
+ // a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix-transpose sparse matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const DMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a row-major dense matrix and a column-major
+// sparse matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side sparse matrix to be subtracted from the dense matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the subtraction of a row-major dense matrix and a column-major sparse
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const DMatTSMatSubExpr<T1,T2>
+ operator-( const DenseMatrix<T1,false>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return DMatTSMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a dense matrix-transpose sparse matrix
+// subtraction expression and a dense matrix (\f$ A=(B-C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-transpose sparse matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a dense
+// matrix-transpose sparse matrix subtraction expression to a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< DMatTSMatSubExpr<T1,T2>, T3 >
+ operator+( const DMatTSMatSubExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() + (~rhs) ) - lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a dense matrix-transpose sparse matrix
+// subtraction expression and a dense matrix (\f$ A=(B-C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix-transpose sparse matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a dense
+// matrix-transpose sparse matrix subtraction expression and a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< DMatTSMatSubExpr<T1,T2>, T3 >
+ operator-( const DMatTSMatSubExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() - (~rhs) ) - lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< DMatTSMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< DMatTSMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< DMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< DMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< DMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< DMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< DMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< DMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< DMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< DMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< DMatTSMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatSubExprTrait_< DMatDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< DMatTSMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatTSMatSubExprTrait_< DMatTDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< DMatTSMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatSubExprTrait_< DMatDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< DMatTSMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatTSMatSubExprTrait_< DMatTDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< DMatTSMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< DMatTSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< DMatTSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatTransExpr.h b/src/cpu/blaze/math/expressions/DMatTransExpr.h
new file mode 100644
index 00000000..804514af
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatTransExpr.h
@@ -0,0 +1,1296 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatTransExpr.h
+// \brief Header file for the dense matrix transpose expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATTRANSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DMatTransposer.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatTransExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EmptyType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATTRANSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix transpositions.
+// \ingroup dense_matrix_expression
+//
+// The DMatTransExpr class represents the compile time expression for transpositions of
+// dense matrices.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+class DMatTransExpr : public DenseMatrix< DMatTransExpr<MT,SO>, SO >
+ , private MatTransExpr
+ , private If< IsComputation<MT>, Computation, EmptyType >::Type
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the dense matrix expression.
+ typedef CompositeType_<MT> CT; //!< Composite type of the dense matrix expression.
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the transposition expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the transposition expression. In case the given dense
+ matrix expression of type \a MT requires an intermediate evaluation, \a useAssign will
+ be set to 1 and the transposition expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to 0 and the expression will be evaluated
+ via the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable and the dense matrix operand requires
+ an intermediate evaluation, \a value is set to 1 and the expression specific evaluation
+ strategy is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename MT2 >
+ struct UseSMPAssign {
+ enum : bool { value = MT2::smpAssignable && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTransExpr<MT,SO> This; //!< Type of this DMatTransExpr instance.
+ typedef TransposeType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef ResultType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DMatTransExpr& > CompositeType;
+
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense matrix.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the dense matrix expression.
+ typedef ConstIterator_<MT> IteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ */
+ explicit inline ConstIterator( IteratorType iterator )
+ : iterator_( iterator ) // Iterator to the current element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( iterator_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( iterator_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return *iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return iterator_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.iterator_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.iterator_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.iterator_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTransExpr class.
+ //
+ // \param dm The dense matrix operand of the transposition expression.
+ */
+ explicit inline DMatTransExpr( const MT& dm ) noexcept
+ : dm_( dm ) // Dense matrix of the transposition expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < dm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.rows() , "Invalid column access index" );
+ return dm_(j,i);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= dm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= dm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t i, size_t j ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( i < dm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.rows() , "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( !SO || ( i % SIMDSIZE == 0UL ), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( SO || ( j % SIMDSIZE == 0UL ), "Invalid column access index" );
+ return dm_.load(j,i);
+ }
+ //**********************************************************************************************
+
+ //**Low-level data access***********************************************************************
+ /*!\brief Low-level data access to the matrix elements.
+ //
+ // \return Pointer to the internal element storage.
+ */
+ inline const ElementType* data() const noexcept {
+ return dm_.data();
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator to the first non-zero element of row/column \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( dm_.begin(i) );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator just past the last non-zero element of row/column \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( dm_.end(i) );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return dm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return dm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Spacing function****************************************************************************
+ /*!\brief Returns the spacing between the beginning of two rows/columns.
+ //
+ // \return The spacing between the beginning of two rows/columns.
+ */
+ inline size_t spacing() const noexcept {
+ return dm_.spacing();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the dense matrix.
+ //
+ // \return The number of non-zero elements in the dense matrix.
+ */
+ inline size_t nonZeros() const {
+ return dm_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row/column.
+ //
+ // \param i The index of the row/column.
+ // \return The number of non-zero elements of row/column \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return dm_.nonZeros( i );
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense matrix operand.
+ //
+ // \return The dense matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return dm_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return dm_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return dm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dm_; //!< Dense matrix of the transposition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix transposition expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix
+ // transposition expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( DenseMatrix<MT2,SO2>& lhs, const DMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ assign( tmp, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense matrix transposition expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense matrix
+ // transposition expression to a sparse matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( SparseMatrix<MT2,SO2>& lhs, const DMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT2, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense matrix transposition expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense
+ // matrix transposition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ addAssign( DenseMatrix<MT2,SO2>& lhs, const DMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ addAssign( tmp, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense matrix transposition expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // matrix transposition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ subAssign( DenseMatrix<MT2,SO2>& lhs, const DMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ subAssign( tmp, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix transposition expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // transposition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( DenseMatrix<MT2,SO2>& lhs, const DMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ smpAssign( tmp, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense matrix transposition expression to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense matrix
+ // transposition expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( SparseMatrix<MT2,SO2>& lhs, const DMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT2, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense matrix transposition expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // matrix transposition expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const DMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ smpAddAssign( tmp, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense matrix transposition expression to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // matrix transposition expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const DMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ smpSubAssign( tmp, rhs.dm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, !SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Calculation of the transpose of the given dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be transposed.
+// \return The transpose of the matrix.
+//
+// This function returns an expression representing the transpose of the given dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A;
+ blaze::DynamicMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ B = trans( A );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline const DMatTransExpr<MT,!SO> trans( const DenseMatrix<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DMatTransExpr<MT,!SO>( ~dm );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating the transpose of a transpose dense matrix.
+// \ingroup dense_matrix
+//
+// \param dm The dense matrix to be (re-)transposed.
+// \return The transpose of the transpose matrix.
+//
+// This function implements a performance optimized treatment of the transpose operation on a
+// dense matrix transpose expression. It returns an expression representing the transpose of a
+// transpose dense matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::DynamicMatrix<double,rowMajor> A, B;
+ // ... Resizing and initialization
+ B = trans( trans( A ) );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline typename DMatTransExpr<MT,SO>::Operand trans( const DMatTransExpr<MT,SO>& dm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dm.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Rows< DMatTransExpr<MT,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Columns< DMatTransExpr<MT,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsAligned< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsPadded< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsLower< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniLower< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyLower< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUpper< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniUpper< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyUpper< DMatTransExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct DMatTransExprTrait< DMatTransExpr<MT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , Operand_< DMatTransExpr<MT,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TDMatTransExprTrait< DMatTransExpr<MT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , Operand_< DMatTransExpr<MT,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool AF >
+struct SubmatrixExprTrait< DMatTransExpr<MT,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = TransExprTrait_< SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct RowExprTrait< DMatTransExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = TransExprTrait_< ColumnExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct ColumnExprTrait< DMatTransExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = TransExprTrait_< RowExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DMatTransposer.h b/src/cpu/blaze/math/expressions/DMatTransposer.h
new file mode 100644
index 00000000..999f8637
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DMatTransposer.h
@@ -0,0 +1,1968 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DMatTransposer.h
+// \brief Header file for the dense matrix transposer
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DMATTRANSPOSER_H_
+#define _BLAZE_MATH_EXPRESSIONS_DMATTRANSPOSER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/simd/SIMDTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DMATTRANSPOSER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the transposition of a dense matrix.
+// \ingroup dense_matrix_expression
+//
+// The DMatTransposer class is a wrapper object for the temporary transposition of a dense matrix.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+class DMatTransposer : public DenseMatrix< DMatTransposer<MT,SO>, SO >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTransposer<MT,SO> This; //!< Type of this DMatTransposer instance.
+ typedef TransposeType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef ResultType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the dense matrix operand is vectorizable,
+ the \a simdEnabled compilation flag is set to \a true, otherwise it is set to \a false. */
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTransposer class.
+ //
+ // \param dm The dense matrix operand.
+ */
+ explicit inline DMatTransposer( MT& dm ) noexcept
+ : dm_( dm ) // The dense matrix operand
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline Reference operator()( size_t i, size_t j ) {
+ BLAZE_INTERNAL_ASSERT( i < dm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.rows() , "Invalid column access index" );
+ return dm_(j,i);
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline ConstReference operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < dm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.rows() , "Invalid column access index" );
+ return dm_(j,i);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline Reference at( size_t i, size_t j ) {
+ if( i >= dm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= dm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ConstReference at( size_t i, size_t j ) const {
+ if( i >= dm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= dm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Low-level data access***********************************************************************
+ /*!\brief Low-level data access to the matrix elements.
+ //
+ // \return Pointer to the internal element storage.
+ */
+ inline Pointer data() noexcept {
+ return dm_.data();
+ }
+ //**********************************************************************************************
+
+ //**Low-level data access***********************************************************************
+ /*!\brief Low-level data access to the matrix elements.
+ //
+ // \return Pointer to the internal element storage.
+ */
+ inline ConstPointer data() const noexcept {
+ return dm_.data();
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator to the first non-zero element of row/column \a i.
+ //
+ // This function returns a row/column iterator to the first non-zero element of row/column \a i.
+ // In case the storage order is set to \a rowMajor the function returns an iterator to the first
+ // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+ // returns an iterator to the first non-zero element of column \a i.
+ */
+ inline Iterator begin( size_t i ) {
+ return dm_.begin( i );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator to the first non-zero element of row/column \a i.
+ //
+ // This function returns a row/column iterator to the first non-zero element of row/column \a i.
+ // In case the storage order is set to \a rowMajor the function returns an iterator to the first
+ // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+ // returns an iterator to the first non-zero element of column \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return dm_.cbegin( i );
+ }
+ //**********************************************************************************************
+
+ //**Cbegin function*****************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator to the first non-zero element of row/column \a i.
+ //
+ // This function returns a row/column iterator to the first non-zero element of row/column \a i.
+ // In case the storage order is set to \a rowMajor the function returns an iterator to the first
+ // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+ // returns an iterator to the first non-zero element of column \a i.
+ */
+ inline ConstIterator cbegin( size_t i ) const {
+ return dm_.cbegin( i );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator just past the last non-zero element of row/column \a i.
+ //
+ // This function returns an row/column iterator just past the last non-zero element of row/column
+ // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+ // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+ // the function returns an iterator just past the last non-zero element of column \a i.
+ */
+ inline Iterator end( size_t i ) {
+ return dm_.end( i );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator just past the last non-zero element of row/column \a i.
+ //
+ // This function returns an row/column iterator just past the last non-zero element of row/column
+ // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+ // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+ // the function returns an iterator just past the last non-zero element of column \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return dm_.cend( i );
+ }
+ //**********************************************************************************************
+
+ //**Cend function*******************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator just past the last non-zero element of row/column \a i.
+ //
+ // This function returns an row/column iterator just past the last non-zero element of row/column
+ // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+ // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+ // the function returns an iterator just past the last non-zero element of column \a i.
+ */
+ inline ConstIterator cend( size_t i ) const {
+ return dm_.cend( i );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment operator**********************************************************
+ /*!\brief Multiplication assignment operator for the multiplication between a matrix and
+ // a scalar value (\f$ A*=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the multiplication.
+ // \return Reference to this DMatTransposer.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, DMatTransposer >& operator*=( Other rhs )
+ {
+ (~dm_) *= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Division assignment operator****************************************************************
+ /*!\brief Division assignment operator for the division of a matrix by a scalar value
+ // (\f$ A/=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the division.
+ // \return Reference to this DMatTransposer.
+ //
+ // \note A division by zero is only checked by an user assert.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, DMatTransposer >& operator/=( Other rhs )
+ {
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ (~dm_) /= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return dm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return dm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Spacing function****************************************************************************
+ /*!\brief Returns the spacing between the beginning of two rows.
+ //
+ // \return The spacing between the beginning of two rows.
+ */
+ inline size_t spacing() const noexcept {
+ return dm_.spacing();
+ }
+ //**********************************************************************************************
+
+ //**Reset function******************************************************************************
+ /*!\brief Resets the matrix elements.
+ //
+ // \return void
+ */
+ inline void reset() {
+ return dm_.reset();
+ }
+ //**********************************************************************************************
+
+ //**IsIntact function***************************************************************************
+ /*!\brief Returns whether the invariants of the matrix are intact.
+ //
+ // \return \a true in case the matrix's invariants are intact, \a false otherwise.
+ */
+ inline bool isIntact() const noexcept {
+ using blaze::isIntact;
+ return isIntact( dm_ );
+ }
+ //**********************************************************************************************
+
+ //**CanAliased function*************************************************************************
+ /*!\brief Returns whether the matrix can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this matrix, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool canAlias( const Other* alias ) const noexcept
+ {
+ return dm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**IsAliased function**************************************************************************
+ /*!\brief Returns whether the matrix is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this matrix, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool isAliased( const Other* alias ) const noexcept
+ {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**IsAligned function**************************************************************************
+ /*!\brief Returns whether the matrix is properly aligned in memory.
+ //
+ // \return \a true in case the matrix is aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept
+ {
+ return dm_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**CanSMPAssign function***********************************************************************
+ /*!\brief Returns whether the matrix can be used in SMP assignments.
+ //
+ // \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept
+ {
+ return dm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Load of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType load( size_t i, size_t j ) const noexcept
+ {
+ return dm_.load( j, i );
+ }
+ //**********************************************************************************************
+
+ //**Loada function******************************************************************************
+ /*!\brief Aligned load of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept
+ {
+ return dm_.loada( j, i );
+ }
+ //**********************************************************************************************
+
+ //**Loadu function******************************************************************************
+ /*!\brief Unaligned load of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept
+ {
+ return dm_.loadu( j, i );
+ }
+ //**********************************************************************************************
+
+ //**Store function******************************************************************************
+ /*!\brief Store of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void store( size_t i, size_t j, const SIMDType& value ) noexcept
+ {
+ dm_.store( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Storea function******************************************************************************
+ /*!\brief Aligned store of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept
+ {
+ dm_.storea( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Storeu function*****************************************************************************
+ /*!\brief Unaligned store of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+ {
+ dm_.storeu( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Stream function*****************************************************************************
+ /*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept
+ {
+ dm_.stream( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of row-major dense matrices********************************************
+ /*!\brief Implementation of the transpose assignment of a row-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void assign( const DenseMatrix<MT2,SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+
+ const size_t jpos( n & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n - ( n % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ dm_(j ,i) = (~rhs)(i,j );
+ dm_(j+1UL,i) = (~rhs)(i,j+1UL);
+ }
+ if( jpos < n ) {
+ dm_(jpos,i) = (~rhs)(i,jpos);
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of column-major dense matrices*****************************************
+ /*!\brief Implementation of the transpose assignment of a column-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void assign( const DenseMatrix<MT2,!SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ dm_(j,i) = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of row-major sparse matrices*******************************************
+ /*!\brief Implementation of the transpose assignment of a row-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void assign( const SparseMatrix<MT2,SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( RhsConstIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ dm_(element->index(),i) = element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of column-major sparse matrices****************************************
+ /*!\brief Implementation of the transpose assignment of a column-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void assign( const SparseMatrix<MT2,!SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( RhsConstIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ dm_(j,element->index()) = element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of row-major dense matrices***********************************
+ /*!\brief Implementation of the transpose addition assignment of a row-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void addAssign( const DenseMatrix<MT2,SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+
+ const size_t jpos( n & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n - ( n % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ dm_(j ,i) += (~rhs)(i,j );
+ dm_(j+1UL,i) += (~rhs)(i,j+1UL);
+
+ }
+ if( jpos < n ) {
+ dm_(jpos,i) += (~rhs)(i,jpos);
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of column-major dense matrices********************************
+ /*!\brief Implementation of the transpose addition assignment of a column-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void addAssign( const DenseMatrix<MT2,!SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ dm_(j,i) += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of row-major sparse matrices**********************************
+ /*!\brief Implementation of the transpose addition assignment of a row-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void addAssign( const SparseMatrix<MT2,SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( RhsConstIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ dm_(element->index(),i) += element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of column-major sparse matrices*******************************
+ /*!\brief Implementation of the transpose addition assignment of a column-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void addAssign( const SparseMatrix<MT2,!SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( RhsConstIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ dm_(j,element->index()) += element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of row-major dense matrices********************************
+ /*!\brief Implementation of the transpose subtraction assignment of a row-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void subAssign( const DenseMatrix<MT2,SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+
+ const size_t jpos( n & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n - ( n % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ dm_(j ,i) -= (~rhs)(i,j );
+ dm_(j+1UL,i) -= (~rhs)(i,j+1UL);
+
+ }
+ if( jpos < n ) {
+ dm_(jpos,i) -= (~rhs)(i,jpos);
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of column-major dense matrices*****************************
+ /*!\brief Implementation of the transpose subtraction assignment of a column-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void subAssign( const DenseMatrix<MT2,!SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ dm_(j,i) -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of row-major sparse matrices*******************************
+ /*!\brief Implementation of the transpose subtraction assignment of a row-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void subAssign( const SparseMatrix<MT2,SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( RhsConstIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ dm_(element->index(),i) -= element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of column-major dense matrices*****************************
+ /*!\brief Implementation of the transpose subtraction assignment of a column-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void subAssign( const SparseMatrix<MT2,!SO>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( RhsConstIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ dm_(j,element->index()) -= element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose multiplication assignment of dense matrices***************************************
+ // No special implementation for the transpose multiplication assignment of dense matrices.
+ //**********************************************************************************************
+
+ //**Transpose multiplication assignment of sparse matrices**************************************
+ // No special implementation for the transpose multiplication assignment of sparse matrices.
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ MT& dm_; //!< The dense matrix operand.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR ROW-MAJOR MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of DMatTransposer for row-major matrices.
+// \ingroup dense_matrix_expression
+//
+// This specialization of DMatTransposer adapts the class template to the requirements of
+// row-major matrices.
+*/
+template< typename MT > // Type of the dense matrix
+class DMatTransposer<MT,true> : public DenseMatrix< DMatTransposer<MT,true>, true >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatTransposer<MT,true> This; //!< Type of this DMatTransposer instance.
+ typedef TransposeType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef ResultType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the matrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
+ in can be optimized via SIMD operations. In case the dense matrix operand is vectorizable,
+ the \a simdEnabled compilation flag is set to \a true, otherwise it is set to \a false. */
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatTransposer class.
+ //
+ // \param dm The dense matrix operand.
+ */
+ explicit inline DMatTransposer( MT& dm ) noexcept
+ : dm_( dm ) // The dense matrix operand
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline Reference operator()( size_t i, size_t j ) {
+ BLAZE_INTERNAL_ASSERT( i < dm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.rows() , "Invalid column access index" );
+ return dm_(j,i);
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline ConstReference operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < dm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < dm_.rows() , "Invalid column access index" );
+ return dm_(j,i);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline Reference at( size_t i, size_t j ) {
+ if( i >= dm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= dm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ConstReference at( size_t i, size_t j ) const {
+ if( i >= dm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= dm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Low-level data access***********************************************************************
+ /*!\brief Low-level data access to the matrix elements.
+ //
+ // \return Pointer to the internal element storage.
+ */
+ inline Pointer data() noexcept {
+ return dm_.data();
+ }
+ //**********************************************************************************************
+
+ //**Low-level data access***********************************************************************
+ /*!\brief Low-level data access to the matrix elements.
+ //
+ // \return Pointer to the internal element storage.
+ */
+ inline ConstPointer data() const noexcept {
+ return dm_.data();
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator to the first non-zero element of column \a i.
+ */
+ inline Iterator begin( size_t j ) {
+ return dm_.begin(j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator to the first non-zero element of column \a i.
+ */
+ inline ConstIterator begin( size_t j ) const {
+ return dm_.cbegin(j);
+ }
+ //**********************************************************************************************
+
+ //**Cbegin function*****************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator to the first non-zero element of column \a j.
+ */
+ inline ConstIterator cbegin( size_t j ) const {
+ return dm_.cbegin(j);
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator just past the last non-zero element of column \a j.
+ */
+ inline Iterator end( size_t j ) {
+ return dm_.end(j);
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator just past the last non-zero element of column \a j.
+ */
+ inline ConstIterator end( size_t j ) const {
+ return dm_.cend(j);
+ }
+ //**********************************************************************************************
+
+ //**Cend function*******************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator just past the last non-zero element of column \a j.
+ */
+ inline ConstIterator cend( size_t j ) const {
+ return dm_.cend(j);
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment operator**********************************************************
+ /*!\brief Multiplication assignment operator for the multiplication between a matrix and
+ // a scalar value (\f$ A*=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the multiplication.
+ // \return Reference to this DMatTransposer.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, DMatTransposer >& operator*=( Other rhs )
+ {
+ (~dm_) *= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Division assignment operator****************************************************************
+ /*!\brief Division assignment operator for the division of a matrix by a scalar value
+ // (\f$ A/=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the division.
+ // \return Reference to this DMatTransposer.
+ //
+ // \note A division by zero is only checked by an user assert.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, DMatTransposer >& operator/=( Other rhs )
+ {
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ (~dm_) /= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return dm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return dm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Spacing function****************************************************************************
+ /*!\brief Returns the spacing between the beginning of two columns.
+ //
+ // \return The spacing between the beginning of two columns.
+ */
+ inline size_t spacing() const noexcept {
+ return dm_.spacing();
+ }
+ //**********************************************************************************************
+
+ //**Reset function******************************************************************************
+ /*!\brief Resets the matrix elements.
+ //
+ // \return void
+ */
+ inline void reset() {
+ return dm_.reset();
+ }
+ //**********************************************************************************************
+
+ //**IsIntact function***************************************************************************
+ /*!\brief Returns whether the invariants of the matrix are intact.
+ //
+ // \return \a true in case the matrix's invariants are intact, \a false otherwise.
+ */
+ inline bool isIntact() const noexcept {
+ using blaze::isIntact;
+ return isIntact( dm_ );
+ }
+ //**********************************************************************************************
+
+ //**CanAliased function*************************************************************************
+ /*!\brief Returns whether the matrix can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this matrix, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool canAlias( const Other* alias ) const noexcept
+ {
+ return dm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**IsAliased function**************************************************************************
+ /*!\brief Returns whether the matrix is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this matrix, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool isAliased( const Other* alias ) const noexcept
+ {
+ return dm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**IsAligned function**************************************************************************
+ /*!\brief Returns whether the matrix is properly aligned in memory.
+ //
+ // \return \a true in case the matrix is aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept
+ {
+ return dm_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**CanSMPAssign function***********************************************************************
+ /*!\brief Returns whether the matrix can be used in SMP assignments.
+ //
+ // \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept
+ {
+ return dm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Load of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType load( size_t i, size_t j ) const noexcept
+ {
+ return dm_.load( j, i );
+ }
+ //**********************************************************************************************
+
+ //**Loada function*******************************************************************************
+ /*!\brief Aligned load of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept
+ {
+ return dm_.loada( j, i );
+ }
+ //**********************************************************************************************
+
+ //**Loadu function******************************************************************************
+ /*!\brief Unaligned load of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept
+ {
+ return dm_.loadu( j, i );
+ }
+ //**********************************************************************************************
+
+ //**Store function******************************************************************************
+ /*!\brief Store of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void store( size_t i, size_t j, const SIMDType& value ) noexcept
+ {
+ dm_.store( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Storea function******************************************************************************
+ /*!\brief Aligned store of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept
+ {
+ dm_.storea( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Storeu function*****************************************************************************
+ /*!\brief Unaligned store of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+ {
+ dm_.storeu( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Stream function*****************************************************************************
+ /*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range [0..M-1].
+ // \param j Access index for the column. The index has to be in the range [0..N-1].
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept
+ {
+ dm_.stream( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of column-major dense matrices*****************************************
+ /*!\brief Implementation of the transpose assignment of a column-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void assign( const DenseMatrix<MT2,true>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+
+ const size_t ipos( m & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m - ( m % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ dm_(j,i ) = (~rhs)(i ,j);
+ dm_(j,i+1UL) = (~rhs)(i+1UL,j);
+ }
+ if( ipos < m ) {
+ dm_(j,ipos) = (~rhs)(ipos,j);
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of row-major dense matrices********************************************
+ /*!\brief Implementation of the transpose assignment of a row-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void assign( const DenseMatrix<MT2,false>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ dm_(j,i) = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of column-major sparse matrices****************************************
+ /*!\brief Implementation of the transpose assignment of a column-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void assign( const SparseMatrix<MT2,true>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( RhsConstIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ dm_(j,element->index()) = element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of row-major sparse matrices*******************************************
+ /*!\brief Implementation of the transpose assignment of a row-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void assign( const SparseMatrix<MT2,false>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( RhsConstIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ dm_(element->index(),i) = element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of column-major dense matrices********************************
+ /*!\brief Implementation of the transpose addition assignment of a column-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void addAssign( const DenseMatrix<MT2,true>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+
+ const size_t ipos( m & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m - ( m % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ dm_(j,i ) += (~rhs)(i ,j);
+ dm_(j,i+1UL) += (~rhs)(i+1UL,j);
+ }
+ if( ipos < m ) {
+ dm_(j,ipos) += (~rhs)(ipos,j);
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of row-major dense matrices***********************************
+ /*!\brief Implementation of the transpose addition assignment of a row-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void addAssign( const DenseMatrix<MT2,false>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ dm_(j,i) += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of column-major sparse matrices*******************************
+ /*!\brief Implementation of the transpose addition assignment of a column-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void addAssign( const SparseMatrix<MT2,true>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( RhsConstIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ dm_(j,element->index()) += element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of row-major sparse matrices**********************************
+ /*!\brief Implementation of the transpose addition assignment of a row-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void addAssign( const SparseMatrix<MT2,false>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( RhsConstIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ dm_(element->index(),i) += element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of column-major dense matrices*****************************
+ /*!\brief Implementation of the transpose subtraction assignment of a column-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void subAssign( const DenseMatrix<MT2,true>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+
+ const size_t ipos( m & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m - ( m % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ dm_(j,i ) -= (~rhs)(i ,j);
+ dm_(j,i+1UL) -= (~rhs)(i+1UL,j);
+ }
+ if( ipos < m ) {
+ dm_(j,ipos) -= (~rhs)(ipos,j);
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of row-major dense matrices********************************
+ /*!\brief Implementation of the transpose subtraction assignment of a row-major dense matrix.
+ //
+ // \param rhs The right-hand side dense matrix to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side dense matrix
+ inline void subAssign( const DenseMatrix<MT2,false>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n; jj+=block ) {
+ const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
+ for( size_t ii=0UL; ii<m; ii+=block ) {
+ const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ dm_(j,i) -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of column-major sparse matrices****************************
+ /*!\brief Implementation of the transpose subtraction assignment of a column-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void subAssign( const SparseMatrix<MT2,true>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j )
+ for( RhsConstIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ dm_(j,element->index()) -= element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of row-major dense matrices********************************
+ /*!\brief Implementation of the transpose subtraction assignment of a row-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void subAssign( const SparseMatrix<MT2,false>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( dm_.columns() == (~rhs).rows(), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( dm_.rows() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsConstIterator;
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i )
+ for( RhsConstIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ dm_(element->index(),i) -= element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose multiplication assignment of dense matrices***************************************
+ // No special implementation for the transpose multiplication assignment of dense matrices.
+ //**********************************************************************************************
+
+ //**Transpose multiplication assignment of sparse matrices**************************************
+ // No special implementation for the transpose multiplication assignment of sparse matrices.
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ MT& dm_; //!< The dense matrix operand.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resetting the dense matrix contained in a DMatTransposer.
+// \ingroup dense_matrix_expression
+//
+// \param m The dense matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline void reset( DMatTransposer<MT,SO>& m )
+{
+ m.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the given DMatTransposer are intact.
+// \ingroup dense_matrix_expression
+//
+// \param m The dense matrix to be tested.
+// \return \a true in caes the given matrix's invariants are intact, \a false otherwise.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline bool isIntact( const DMatTransposer<MT,SO>& m ) noexcept
+{
+ return m.isIntact();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct HasMutableDataAccess< DMatTransposer<MT,SO> >
+ : public BoolConstant< HasMutableDataAccess<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsAligned< DMatTransposer<MT,SO> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsPadded< DMatTransposer<MT,SO> >
+ : public BoolConstant< IsPadded<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct SubmatrixTrait< DMatTransposer<MT,SO> >
+{
+ using Type = SubmatrixTrait_< ResultType_< DMatTransposer<MT,SO> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecDVecAddExpr.h b/src/cpu/blaze/math/expressions/DVecDVecAddExpr.h
new file mode 100644
index 00000000..20ac49c3
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecDVecAddExpr.h
@@ -0,0 +1,1150 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecDVecAddExpr.h
+// \brief Header file for the dense vector/dense vector addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECDVECADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECDVECADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecAddExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecVecAddExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Double.h>
+#include <blaze/util/constraints/Float.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECDVECADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-dense vector additions.
+// \ingroup dense_vector_expression
+//
+// The DVecDVecAddExpr class represents the compile time expression for additions between
+// dense vectors.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class DVecDVecAddExpr : public DenseVector< DVecDVecAddExpr<VT1,VT2,TF>, TF >
+ , private VecVecAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RE1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RE2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side dense vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to 0 and the subscript operator will return
+ it's result by value. Otherwise \a returnExpr will be set to 1 and the subscript
+ operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the addition expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the addition expression. In case either of the two
+ dense vector operands requires an intermediate evaluation or the subscript operator
+ can only return by value, \a useAssign will be set to 1 and the addition expression
+ will be evaluated via the \a assign function family. Otherwise \a useAssign will be
+ set to 0 and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = ( RequiresEvaluation<VT1>::value || RequiresEvaluation<VT2>::value || !returnExpr ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two dense vector operands is not SMP assignable and
+ at least one of the two operands requires an intermediate evaluation, \a value is set to 1
+ and the expression specific evaluation strategy is selected. Otherwise \a value is set to
+ 0 and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT1::smpAssignable || !VT2::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecDVecAddExpr<VT1,VT2,TF> This; //!< Type of this DVecDVecAddExpr instance.
+ typedef AddTrait_<RE1,RE2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecDVecAddExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the left-hand side dense vector expression.
+ typedef ConstIterator_<VT1> LeftIteratorType;
+
+ //! ConstIterator type of the right-hand side dense vector expression.
+ typedef ConstIterator_<VT2> RightIteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param left Iterator to the initial left-hand side element.
+ // \param right Iterator to the initial right-hand side element.
+ */
+ explicit inline ConstIterator( LeftIteratorType left, RightIteratorType right )
+ : left_ ( left ) // Iterator to the current left-hand side element
+ , right_( right ) // Iterator to the current right-hand side element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ left_ += inc;
+ right_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ left_ -= dec;
+ right_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++left_;
+ ++right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( left_++, right_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --left_;
+ --right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( left_--, right_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return (*left_) + (*right_);
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return left_.load() + right_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return left_ == rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return left_ != rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return left_ < rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return left_ > rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return left_ <= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return left_ >= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return left_ - rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.left_ - dec, it.right_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftIteratorType left_; //!< Iterator to the current left-hand side element.
+ RightIteratorType right_; //!< Iterator to the current right-hand side element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT1::simdEnabled && VT2::simdEnabled &&
+ HasSIMDAdd<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT1::smpAssignable && VT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecDVecAddExpr class.
+ //
+ // \param lhs The left-hand side operand of the addition expression.
+ // \param rhs The right-hand side operand of the addition expression.
+ */
+ explicit inline DVecDVecAddExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the addition expression
+ , rhs_( rhs ) // Right-hand side dense vector of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] + rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t index ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size() , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ return lhs_.load( index ) + rhs_.load( index );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the dense vector.
+ //
+ // \return Iterator to the first non-zero element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( lhs_.begin(), rhs_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
+ //
+ // \return Iterator just past the last non-zero element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( lhs_.end(), rhs_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<VT1>::value && ( RequiresEvaluation<VT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
+ ( IsExpression<VT2>::value && ( RequiresEvaluation<VT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
+ ( size() > SMP_DVECDVECADD_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the addition expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector addition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( !IsComputation<VT2>::value && isSame( ~lhs, rhs.rhs_ ) ) {
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector addition to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector addition expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( SparseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // dense vector addition expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ addAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // dense vector addition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ subAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-dense vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ multAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // dense vector addition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ divAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector addition expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression specific
+ // parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( !IsComputation<VT2>::value && isSame( ~lhs, rhs.rhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector addition to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector addition expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( SparseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector-dense vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector-dense vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector-dense vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector-dense vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense
+ // vector-dense vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpDivAssign( DenseVector<VT,TF>& lhs, const DVecDVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECADDEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of two dense vectors (\f$ \vec{a}=\vec{b}+\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the vector addition.
+// \param rhs The right-hand side dense vector for the vector addition.
+// \return The sum of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the addition of two dense vectors:
+
+ \code
+ blaze::DynamicVector<double> a, b, c;
+ // ... Resizing and initialization
+ c = a + b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const DVecDVecAddExpr<T1,T2,TF>
+ operator+( const DenseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return DVecDVecAddExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecDVecAddExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct IsAligned< DVecDVecAddExpr<VT1,VT2,TF> >
+ : public BoolConstant< And< IsAligned<VT1>, IsAligned<VT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct IsPadded< DVecDVecAddExpr<VT1,VT2,TF> >
+ : public BoolConstant< And< IsPadded<VT1>, IsPadded<VT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecDVecAddExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecDVecCrossExpr.h b/src/cpu/blaze/math/expressions/DVecDVecCrossExpr.h
new file mode 100644
index 00000000..2697ebd3
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecDVecCrossExpr.h
@@ -0,0 +1,569 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecDVecCrossExpr.h
+// \brief Header file for the dense vector/dense vector cross product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECDVECCROSSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECDVECCROSSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/dense/Forward.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/CrossExpr.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECDVECCROSSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-dense vector cross products.
+// \ingroup dense_vector_expression
+//
+// The DVecDVecCrossExpr class represents the compile time expression for cross products
+// between dense vectors.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class DVecDVecCrossExpr : public DenseVector< DVecDVecCrossExpr<VT1,VT2,TF>, TF >
+ , private CrossExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side dense vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_< MultExprTrait_<RN1,RN2>, MultExprTrait_<RN1,RN2> > ExprReturnType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecDVecCrossExpr<VT1,VT2,TF> This; //!< Type of this DVecDVecCrossExpr instance.
+ typedef CrossTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsComputation<VT1>, const StaticVector<ET1,3UL,TF>, CT1 > LT;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsComputation<VT2>, const StaticVector<ET2,3UL,TF>, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecDVecCrossExpr class.
+ //
+ // \param lhs The left-hand side operand of the cross product expression.
+ // \param rhs The right-hand side operand of the cross product expression.
+ */
+ explicit inline DVecDVecCrossExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the cross product expression
+ , rhs_( rhs ) // Right-hand side dense vector of the cross product expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( rhs.size() == 3UL, "Invalid vector size" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..2]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < 3UL, "Invalid vector access index" );
+
+ if( index == 0UL )
+ return lhs_[1UL] * rhs_[2UL] - lhs_[2UL] * rhs_[1UL];
+ else if( index == 1UL )
+ return lhs_[2UL] * rhs_[0UL] - lhs_[0UL] * rhs_[2UL];
+ else
+ return lhs_[0UL] * rhs_[1UL] - lhs_[1UL] * rhs_[0UL];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= 3UL ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline constexpr size_t size() const noexcept {
+ return 3UL;
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the cross product expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the cross product expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT,TF>& lhs, const DVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] = x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] = x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] = x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector cross product to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side cross product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector cross product expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const DVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // dense vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const DVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] += x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] += x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] += x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // dense vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const DVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] -= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] -= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] -= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-dense vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const DVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] *= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] *= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] *= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // dense vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT,TF>& lhs, const DVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] /= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] /= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] /= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Operator for the cross product of two dense vectors (\f$ \vec{a}=\vec{b} \times \vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the cross product.
+// \param rhs The right-hand side dense vector for the cross product.
+// \return The cross product of the two vectors.
+// \exception std::invalid_argument Invalid vector size for cross product.
+//
+// This operator represents the cross product of two dense vectors:
+
+ \code
+ blaze::DynamicVector<double> a( 3UL ), b( 3UL );
+ blaze::StaticVector<double,3UL> c;
+ // ... Resizing and initialization
+ c = a % b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the CrossTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const DVecDVecCrossExpr<T1,T2,TF>
+ operator%( const DenseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != 3UL || (~rhs).size() != 3UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" );
+ }
+
+ return DVecDVecCrossExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Cross product of two dense vectors (\f$ \vec{a}=\vec{b} \times \vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the cross product.
+// \param rhs The right-hand side dense vector for the cross product.
+// \return The cross product of the two vectors.
+// \exception std::invalid_argument Invalid vector size for cross product.
+//
+// This function computes the cross product of two dense vectors:
+
+ \code
+ blaze::DynamicVector<double> a( 3UL ), b( 3UL );
+ blaze::StaticVector<double,3UL> c;
+ // ... Resizing and initialization
+ c = a % b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the CrossTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const DVecDVecCrossExpr<T1,T2,TF>
+ cross( const DenseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ return lhs % rhs;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecDVecCrossExpr<VT1,VT2,TF> > : public SizeT<3UL>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecDVecDivExpr.h b/src/cpu/blaze/math/expressions/DVecDVecDivExpr.h
new file mode 100644
index 00000000..36b641ce
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecDVecDivExpr.h
@@ -0,0 +1,1151 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecDVecDivExpr.h
+// \brief Header file for the dense vector/dense vector division expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECDVECDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECDVECDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecDivExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecVecDivExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECDVECDIVEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-dense vector divisions.
+// \ingroup dense_vector_expression
+//
+// The DVecDVecDivExpr class represents the compile time expression for componentwise divisions
+// between dense vectors.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class DVecDVecDivExpr : public DenseVector< DVecDVecDivExpr<VT1,VT2,TF>, TF >
+ , private VecVecDivExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side dense vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to 0 and the subscript operator will return
+ it's result by value. Otherwise \a returnExpr will be set to 1 and the subscript
+ operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef DivExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the division expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the division expression. In case either of the two
+ dense vector operands requires an intermediate evaluation or the subscript operator
+ can only return by value, \a useAssign will be set to 1 and the division expression
+ will be evaluated via the \a assign function family. Otherwise \a useAssign will be
+ set to 0 and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = ( RequiresEvaluation<VT1>::value || RequiresEvaluation<VT2>::value || !returnExpr ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two dense vector operands is not SMP assignable and
+ at least one of the two operands requires an intermediate evaluation, \a value is set to 1
+ and the expression specific evaluation strategy is selected. Otherwise \a value is set to
+ 0 and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT1::smpAssignable || !VT2::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecDVecDivExpr<VT1,VT2,TF> This; //!< Type of this DVecDVecDivExpr instance.
+ typedef DivTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecDVecDivExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the left-hand side dense vector expression.
+ typedef ConstIterator_<VT1> LeftIteratorType;
+
+ //! ConstIterator type of the right-hand side dense vector expression.
+ typedef ConstIterator_<VT2> RightIteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param left Iterator to the initial left-hand side element.
+ // \param right Iterator to the initial right-hand side element.
+ */
+ explicit inline ConstIterator( LeftIteratorType left, RightIteratorType right )
+ : left_ ( left ) // Iterator to the current left-hand side element
+ , right_( right ) // Iterator to the current right-hand side element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ left_ += inc;
+ right_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ left_ -= dec;
+ right_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++left_;
+ ++right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( left_++, right_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --left_;
+ --right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( left_--, right_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return (*left_) / (*right_);
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return left_.load() / right_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return left_ == rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return left_ != rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return left_ < rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return left_ > rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return left_ <= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return left_ >= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return left_ - rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.left_ - dec, it.right_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftIteratorType left_; //!< Iterator to the current left-hand side element.
+ RightIteratorType right_; //!< Iterator to the current right-hand side element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT1::simdEnabled && VT2::simdEnabled &&
+ HasSIMDDiv<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT1::smpAssignable && VT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecDVecDivExpr class.
+ //
+ // \param lhs The left-hand side operand of the division expression.
+ // \param rhs The right-hand side operand of the division expression.
+ */
+ explicit inline DVecDVecDivExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the division expression
+ , rhs_( rhs ) // Right-hand side dense vector of the division expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] / rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t index ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size() , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ return lhs_.load( index ) / rhs_.load( index );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the dense vector.
+ //
+ // \return Iterator to the first non-zero element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( lhs_.begin(), rhs_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
+ //
+ // \return Iterator just past the last non-zero element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( lhs_.end(), rhs_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<VT1>::value && ( RequiresEvaluation<VT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
+ ( IsExpression<VT2>::value && ( RequiresEvaluation<VT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
+ ( size() > SMP_DVECDVECDIV_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the division expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the division expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ divAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( IsSame<VT,ResultType>::value ||
+ IsSame< ElementType_<VT>, ElementType_<VT1> >::value ) {
+ assign ( ~lhs, rhs.lhs_ );
+ divAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector division to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector division expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( SparseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // dense vector division expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ addAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // dense vector division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ subAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-dense vector division expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ multAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // dense vector division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ divAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector division expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpDivAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( IsSame<VT,ResultType>::value ||
+ IsSame< ElementType_<VT>, ElementType_<VT1> >::value ) {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpDivAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector division to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector division expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( SparseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense vector-
+ // dense vector division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector-dense vector division expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // dense vector-dense vector division expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector-dense vector division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense vector-
+ // dense vector division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpDivAssign( DenseVector<VT,TF>& lhs, const DVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECDIVEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division operator for the componentwise product of two dense vectors
+// (\f$ \vec{a}=\vec{b}/\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the component product.
+// \param rhs The right-hand side dense vector for the component product.
+// \return The quotient of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the component quotient of two dense vectors:
+
+ \code
+ blaze::DynamicVector<double> a, b, c;
+ // ... Resizing and initialization
+ c = a / b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the DivTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const DVecDVecDivExpr<T1,T2,TF>
+ operator/( const DenseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return DVecDVecDivExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecDVecDivExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct IsAligned< DVecDVecDivExpr<VT1,VT2,TF> >
+ : public BoolConstant< And< IsAligned<VT1>, IsAligned<VT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecDVecDivExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecDVecMultExpr.h b/src/cpu/blaze/math/expressions/DVecDVecMultExpr.h
new file mode 100644
index 00000000..0d9b65a3
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecDVecMultExpr.h
@@ -0,0 +1,1208 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecDVecMultExpr.h
+// \brief Header file for the dense vector/dense vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecVecMultExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-dense vector multiplications.
+// \ingroup dense_vector_expression
+//
+// The DVecDVecMultExpr class represents the compile time expression for componentwise
+// multiplications between dense vectors.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class DVecDVecMultExpr : public DenseVector< DVecDVecMultExpr<VT1,VT2,TF>, TF >
+ , private VecVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side dense vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to 0 and the subscript operator will return
+ it's result by value. Otherwise \a returnExpr will be set to 1 and the subscript
+ operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for the
+ serial evaluation strategy of the multiplication expression. In case either of the two
+ dense vector operands requires an intermediate evaluation or the subscript operator can
+ only return by value, \a useAssign will be set to 1 and the multiplication expression will
+ be evaluated via the \a assign function family. Otherwise \a useAssign will be set to 0
+ and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = ( RequiresEvaluation<VT1>::value || RequiresEvaluation<VT2>::value || !returnExpr ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two dense vector operands is not SMP assignable and
+ at least one of the two operands requires an intermediate evaluation, \a value is set to 1
+ and the expression specific evaluation strategy is selected. Otherwise \a value is set to
+ 0 and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT1::smpAssignable || !VT2::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecDVecMultExpr<VT1,VT2,TF> This; //!< Type of this DVecDVecMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecDVecMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the left-hand side dense vector expression.
+ typedef ConstIterator_<VT1> LeftIteratorType;
+
+ //! ConstIterator type of the right-hand side dense vector expression.
+ typedef ConstIterator_<VT2> RightIteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param left Iterator to the initial left-hand side element.
+ // \param right Iterator to the initial right-hand side element.
+ */
+ explicit inline ConstIterator( LeftIteratorType left, RightIteratorType right )
+ : left_ ( left ) // Iterator to the current left-hand side element
+ , right_( right ) // Iterator to the current right-hand side element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ left_ += inc;
+ right_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ left_ -= dec;
+ right_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++left_;
+ ++right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( left_++, right_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --left_;
+ --right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( left_--, right_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return (*left_) * (*right_);
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return left_.load() * right_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return left_ == rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return left_ != rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return left_ < rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return left_ > rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return left_ <= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return left_ >= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return left_ - rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.left_ - dec, it.right_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftIteratorType left_; //!< Iterator to the current left-hand side element.
+ RightIteratorType right_; //!< Iterator to the current right-hand side element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT1::simdEnabled && VT2::simdEnabled &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT1::smpAssignable && VT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecDVecMultExpr class.
+ //
+ // \param lhs The left-hand side operand of the multiplication expression.
+ // \param rhs The right-hand side operand of the multiplication expression.
+ */
+ explicit inline DVecDVecMultExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] * rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t index ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size() , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ return lhs_.load( index ) * rhs_.load( index );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the dense vector.
+ //
+ // \return Iterator to the first non-zero element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( lhs_.begin(), rhs_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
+ //
+ // \return Iterator just past the last non-zero element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( lhs_.end(), rhs_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<VT1>::value && ( RequiresEvaluation<VT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
+ ( IsExpression<VT2>::value && ( RequiresEvaluation<VT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
+ ( size() > SMP_DVECDVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ multAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( !IsComputation<VT2>::value && isSame( ~lhs, rhs.rhs_ ) ) {
+ multAssign( ~lhs, rhs.lhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ multAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector multiplication to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( SparseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-dense vector multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ addAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-dense vector multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either of
+ // the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ subAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-dense vector multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ multAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.lhs_ );
+ multAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-dense vector multiplication to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-dense vector multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT> >
+ multAssign( SparseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.lhs_ );
+ multAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-dense vector multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ divAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpMultAssign( ~lhs, rhs.rhs_ );
+ }
+ else if( !IsComputation<VT2>::value && isSame( ~lhs, rhs.rhs_ ) ) {
+ smpMultAssign( ~lhs, rhs.lhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpMultAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector multiplication to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( SparseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-dense vector multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense vector-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-dense vector multiplication to a dense
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-dense vector multiplication to a
+ // dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // dense vector-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpMultAssign( ~lhs, rhs.lhs_ );
+ smpMultAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-dense vector multiplication to a
+ // sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // dense vector-dense vector multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( SparseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpMultAssign( ~lhs, rhs.lhs_ );
+ smpMultAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector-dense vector multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense
+ // vector-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpDivAssign( DenseVector<VT,TF>& lhs, const DVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECMULTEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the componentwise product of two dense vectors
+// (\f$ \vec{a}=\vec{b}*\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the component product.
+// \param rhs The right-hand side dense vector for the component product.
+// \return The product of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the component product of two dense vectors:
+
+ \code
+ blaze::DynamicVector<double> a, b, c;
+ // ... Resizing and initialization
+ c = a * b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const DVecDVecMultExpr<T1,T2,TF>
+ operator*( const DenseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return DVecDVecMultExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecDVecMultExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct IsAligned< DVecDVecMultExpr<VT1,VT2,TF> >
+ : public BoolConstant< And< IsAligned<VT1>, IsAligned<VT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct IsPadded< DVecDVecMultExpr<VT1,VT2,TF> >
+ : public BoolConstant< And< IsPadded<VT1>, IsPadded<VT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecDVecMultExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecDVecSubExpr.h b/src/cpu/blaze/math/expressions/DVecDVecSubExpr.h
new file mode 100644
index 00000000..4c5c1b8c
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecDVecSubExpr.h
@@ -0,0 +1,1142 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecDVecSubExpr.h
+// \brief Header file for the dense vector/dense vector subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECDVECSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECDVECSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecSubExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecVecSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECDVECSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-dense vector subtractions.
+// \ingroup dense_vector_expression
+//
+// The DVecDVecSubExpr class represents the compile time expression for subtractions between
+// dense vectors.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class DVecDVecSubExpr : public DenseVector< DVecDVecSubExpr<VT1,VT2,TF>, TF >
+ , private VecVecSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side dense vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to 0 and the subscript operator will return
+ it's result by value. Otherwise \a returnExpr will be set to 1 and the subscript
+ operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the subtraction expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for the
+ serial evaluation strategy of the subtraction expression. In case either of the two dense
+ vector operands requires an intermediate evaluation or the subscript operator can only
+ return by value, \a useAssign will be set to 1 and the subtraction expression will be
+ evaluated via the \a assign function family. Otherwise \a useAssign will be set to 0 and
+ the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = ( RequiresEvaluation<VT1>::value || RequiresEvaluation<VT2>::value || !returnExpr ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two dense vector operands is not SMP assignable and
+ at least one of the two operands requires an intermediate evaluation, \a value is set to 1
+ and the expression specific evaluation strategy is selected. Otherwise \a value is set to
+ 0 and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT1::smpAssignable || !VT2::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecDVecSubExpr<VT1,VT2,TF> This; //!< Type of this DVecDVecSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecDVecSubExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the left-hand side dense vector expression.
+ typedef ConstIterator_<VT1> LeftIteratorType;
+
+ //! ConstIterator type of the right-hand side dense vector expression.
+ typedef ConstIterator_<VT2> RightIteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param left Iterator to the initial left-hand side element.
+ // \param right Iterator to the initial right-hand side element.
+ */
+ explicit inline ConstIterator( LeftIteratorType left, RightIteratorType right )
+ : left_ ( left ) // Iterator to the current left-hand side element
+ , right_( right ) // Iterator to the current right-hand side element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ left_ += inc;
+ right_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ left_ -= dec;
+ right_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++left_;
+ ++right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( left_++, right_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --left_;
+ --right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( left_--, right_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return (*left_) - (*right_);
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return left_.load() - right_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return left_ == rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return left_ != rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return left_ < rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return left_ > rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return left_ <= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return left_ >= rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return left_ - rhs.left_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.left_ + inc, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.left_ - dec, it.right_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftIteratorType left_; //!< Iterator to the current left-hand side element.
+ RightIteratorType right_; //!< Iterator to the current right-hand side element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT1::simdEnabled && VT2::simdEnabled &&
+ HasSIMDSub<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT1::smpAssignable && VT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecDVecSubExpr class.
+ //
+ // \param lhs The left-hand side operand of the subtraction expression.
+ // \param rhs The right-hand side operand of the subtraction expression.
+ */
+ explicit inline DVecDVecSubExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the subtraction expression
+ , rhs_( rhs ) // Right-hand side dense vector of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] - rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t index ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size() , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ return lhs_.load( index ) - rhs_.load( index );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the dense vector.
+ //
+ // \return Iterator to the first non-zero element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( lhs_.begin(), rhs_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
+ //
+ // \return Iterator just past the last non-zero element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( lhs_.end(), rhs_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<VT1>::value && ( RequiresEvaluation<VT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
+ ( IsExpression<VT2>::value && ( RequiresEvaluation<VT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
+ ( size() > SMP_DVECDVECSUB_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector subtraction expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector subtraction to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector subtraction expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( SparseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // dense vector subtraction expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ addAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // dense vector subtraction expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either of
+ // the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ subAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-dense vector subtraction expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ multAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // dense vector subtraction expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ divAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector subtraction expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector subtraction to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector subtraction expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( SparseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense vector-
+ // dense vector subtraction expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector-dense vector subtraction expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector-dense vector subtraction expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense vector-
+ // dense vector subtraction expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpDivAssign( DenseVector<VT,TF>& lhs, const DVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECSUBEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of two dense vectors (\f$ \vec{a}=\vec{b}-\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the vector subtraction.
+// \param rhs The right-hand side dense vector to be subtracted from the vector.
+// \return The difference of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the subtraction of two dense vectors:
+
+ \code
+ blaze::DynamicVector<double> a, b, c;
+ // ... Resizing and initialization
+ c = a - b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const DVecDVecSubExpr<T1,T2,TF>
+ operator-( const DenseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return DVecDVecSubExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecDVecSubExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct IsAligned< DVecDVecSubExpr<VT1,VT2,TF> >
+ : public BoolConstant< And< IsAligned<VT1>, IsAligned<VT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct IsPadded< DVecDVecSubExpr<VT1,VT2,TF> >
+ : public BoolConstant< And< IsPadded<VT1>, IsPadded<VT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecDVecSubExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecEvalExpr.h b/src/cpu/blaze/math/expressions/DVecEvalExpr.h
new file mode 100644
index 00000000..155136d5
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecEvalExpr.h
@@ -0,0 +1,867 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecEvalExpr.h
+// \brief Header file for the dense vector evaluation expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECEVALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecEvalExpr.h>
+#include <blaze/math/traits/DVecEvalExprTrait.h>
+#include <blaze/math/traits/EvalExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/TDVecEvalExprTrait.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECEVALEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the forced evaluation of dense vectors.
+// \ingroup dense_vector_expression
+//
+// The DVecEvalExpr class represents the compile time expression for the forced evaluation
+// of a dense vector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+class DVecEvalExpr : public DenseVector< DVecEvalExpr<VT,TF>, TF >
+ , private VecEvalExpr
+ , private Computation
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecEvalExpr<VT,TF> This; //!< Type of this DVecEvalExpr instance.
+ typedef ResultType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecEvalExpr class.
+ //
+ // \param dv The dense vector operand of the evaluation expression.
+ */
+ explicit inline DVecEvalExpr( const VT& dv ) noexcept
+ : dv_( dv ) // Dense vector of the evaluation expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < dv_.size(), "Invalid vector access index" );
+ return dv_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= dv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return dv_.size();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense vector operand.
+ //
+ // \return The dense vector operand.
+ */
+ inline Operand operand() const noexcept {
+ return dv_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return dv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return dv_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return dv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dv_; //!< Dense vector of the evaluation expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector evaluation
+ // expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector evaluation
+ // expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector
+ // evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaulation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector
+ // evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void addAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void subAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void multAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector
+ // evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ divAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector
+ // evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void divAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ divAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpAddAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpAddAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpSubAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpSubAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpMultAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpMultAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpMultAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpMultAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense vector
+ // evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpDivAssign( DenseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpDivAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense vector
+ // evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpDivAssign( SparseVector<VT2,TF>& lhs, const DVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpDivAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Forces the evaluation of the given dense vector expression \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The evaluated dense vector.
+//
+// The \a eval function forces the evaluation of the given dense vector expression \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a eval function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = eval( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecEvalExpr<VT,TF> eval( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecEvalExpr<VT,TF>( ~dv );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Evaluation of the given dense vector evaluation expression \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input evaluation expression.
+// \return The evaluated dense vector.
+//
+// This function implements a performance optimized treatment of the evaluation of a dense vector
+// evaluation expression.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecEvalExpr<VT,TF> eval( const DVecEvalExpr<VT,TF>& dv )
+{
+ return dv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct Size< DVecEvalExpr<VT,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct IsAligned< DVecEvalExpr<VT,TF> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecEvalExprTrait< DVecEvalExpr<VT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecEvalExpr<VT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecEvalExprTrait< DVecEvalExpr<VT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecEvalExpr<VT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF, bool AF >
+struct SubvectorExprTrait< DVecEvalExpr<VT,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = EvalExprTrait_< SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecForEachExpr.h b/src/cpu/blaze/math/expressions/DVecForEachExpr.h
new file mode 100644
index 00000000..2b0b15f1
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecForEachExpr.h
@@ -0,0 +1,2404 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecForEachExpr.h
+// \brief Header file for the dense vector for-each expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECFOREACHEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecForEachExpr.h>
+#include <blaze/math/Functors.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/ForEachExprTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/HasMember.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECFOREACHEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the dense vector forEach() function.
+// \ingroup dense_vector_expression
+//
+// The DVecForEachExpr class represents the compile time expression for the evaluation of a
+// custom operation on each element of a dense vector via the forEach() function.
+*/
+template< typename VT // Type of the dense vector
+ , typename OP // Type of the custom operation
+ , bool TF > // Transpose flag
+class DVecForEachExpr : public DenseVector< DVecForEachExpr<VT,OP,TF>, TF >
+ , private VecForEachExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> RT; //!< Result type of the dense vector expression.
+ typedef ElementType_<VT> ET; //!< Element type of the dense vector expression.
+ typedef ReturnType_<VT> RN; //!< Return type of the dense vector expression.
+
+ //! Definition of the HasSIMDEnabled type trait.
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasSIMDEnabled, simdEnabled );
+
+ //! Definition of the HasLoad type trait.
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasLoad, load );
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the for-each expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the for-each expression. In case the given dense
+ vector expression of type \a VT requires an intermediate evaluation, \a useAssign will
+ be set to 1 and the for-each expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to 0 and the expression will be evaluated
+ via the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<VT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target vector or the dense vector operand is not SMP
+ assignable and the vector operand requires an intermediate evaluation, \a value is set
+ to 1 and the expression specific evaluation strategy is selected. Otherwise \a value is
+ set to 0 and the default strategy is chosen. */
+ template< typename VT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT2::smpAssignable || !VT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SIMD support detection**********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the detection of the SIMD capabilities of the given custom operation.
+ struct UseSIMDEnabledFlag {
+ enum : bool { value = OP::BLAZE_TEMPLATE simdEnabled<ET>() };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecForEachExpr<VT,OP,TF> This; //!< Type of this DVecForEachExpr instance.
+ typedef ForEachTrait_<VT,OP> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef decltype( std::declval<OP>()( std::declval<RN>() ) ) ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecForEachExpr& > CompositeType;
+
+ //! Composite data type of the dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > Operand;
+
+ //! Data type of the custom unary operation.
+ typedef OP Operation;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the left-hand side dense vector expression.
+ typedef ConstIterator_<VT> IteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param it Iterator to the initial vector element.
+ // \param op The custom unary operation.
+ */
+ explicit inline ConstIterator( IteratorType it, OP op )
+ : it_( it ) // Iterator to the current vector element
+ , op_( op ) // The custom unary operation
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ it_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ it_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( it_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( it_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return op_( *it_ );
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return op_.load( it_.load() );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return it_ < rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return it_ > rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return it_ <= rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return it_ >= rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.it_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.it_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.it_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator to the current vector element.
+ OP op_; //!< The custom unary operation.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT::simdEnabled &&
+ If_< HasSIMDEnabled<OP>, UseSIMDEnabledFlag, HasLoad<OP> >::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecForEachExpr class.
+ //
+ // \param dv The dense vector operand of the for-each expression.
+ // \param op The custom unary operation.
+ */
+ explicit inline DVecForEachExpr( const VT& dv, OP op ) noexcept
+ : dv_( dv ) // Dense vector of the for-each expression
+ , op_( op ) // The custom unary operation
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < dv_.size(), "Invalid vector access index" );
+ return op_( dv_[index] );
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= dv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t index ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( index < dv_.size() , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ return op_.load( dv_.load( index ) );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the dense vector.
+ //
+ // \return Iterator to the first non-zero element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( dv_.begin(), op_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
+ //
+ // \return Iterator just past the last non-zero element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( dv_.end(), op_ );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return dv_.size();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense vector operand.
+ //
+ // \return The dense vector operand.
+ */
+ inline Operand operand() const noexcept {
+ return dv_;
+ }
+ //**********************************************************************************************
+
+ //**Operation access****************************************************************************
+ /*!\brief Returns a copy of the custom operation.
+ //
+ // \return A copy of the custom operation.
+ */
+ inline Operation operation() const {
+ return op_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return IsComputation<VT>::value && dv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return dv_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return dv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dv_; //!< Dense vector of the for-each expression.
+ Operation op_; //!< The custom unary operation.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector for-each
+ // expression to a dense vector. Due to the explicit application of the SFINAE principle,
+ // this function can only be selected by the compiler in case the operand requires an
+ // intermediate evaluation and the underlying numeric data type of the operand and the
+ // target vector are identical.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< And< UseAssign<VT2>
+ , IsSame< UnderlyingNumeric<VT>, UnderlyingNumeric<VT2> > > >
+ assign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.dv_ );
+ assign( ~lhs, forEach( ~lhs, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector for-each
+ // expression to a dense vector. Due to the explicit application of the SFINAE principle,
+ // this function can only be selected by the compiler in case the operand requires an
+ // intermediate evaluation and the underlying numeric data type of the operand and the
+ // target vector differ.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< And< UseAssign<VT2>
+ , Not< IsSame< UnderlyingNumeric<VT>, UnderlyingNumeric<VT2> > > > >
+ assign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.dv_ ) );
+ assign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector for-each expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector for-each
+ // expression to a sparse vector. Due to the explicit application of the SFINAE principle,
+ // this function can only be selected by the compiler in case the operand requires an
+ // intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.dv_ ) );
+ assign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector
+ // for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand
+ // requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.dv_ ) );
+ addAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // vector for-each expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.dv_ ) );
+ subAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand requires
+ // an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.dv_ ) );
+ multAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense
+ // vector for-each expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ divAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.dv_ ) );
+ divAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected and the underlying numeric data
+ // type of the operand and the target vector are identical
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< And< UseSMPAssign<VT2>
+ , IsSame< UnderlyingNumeric<VT>, UnderlyingNumeric<VT2> > > >
+ smpAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.dv_ );
+ smpAssign( ~lhs, rhs.op_( ~lhs ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected and the underlying numeric data
+ // type of the operand and the target vector differ.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< And< UseSMPAssign<VT2>
+ , Not< IsSame< UnderlyingNumeric<VT>, UnderlyingNumeric<VT2> > > > >
+ smpAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.dv_ );
+ smpAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector for-each expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // for-each expression to a sparse vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.dv_ );
+ smpAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.dv_ );
+ smpAddAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.dv_ );
+ smpSubAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // dense vector for-each expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.dv_ );
+ smpMultAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector for-each expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense
+ // vector for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,TF>& lhs, const DVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.dv_ );
+ smpDivAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluates the given custom operation on each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \param op The custom operation.
+// \return The custom operation applied to each single element of \a dv.
+//
+// The \a forEach() function evaluates the given custom operation on each element of the input
+// vector \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a forEach() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = forEach( a, []( double a ){ return std::sqrt( a ); } );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF // Transpose flag
+ , typename OP > // Type of the custom operation
+inline const DVecForEachExpr<VT,OP,TF> forEach( const DenseVector<VT,TF>& dv, OP op )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,OP,TF>( ~dv, op );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a abs() function to each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The resulting dense vector.
+//
+// This function applies the \a abs() function to each element of the input vector \a dv. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a abs() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = abs( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Abs,TF> abs( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Abs,TF>( ~dv, Abs() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a floor() function to each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The resulting dense vector.
+//
+// This function applies the \a floor() function to each element of the input vector \a dv. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a floor() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = floor( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Floor,TF> floor( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Floor,TF>( ~dv, Floor() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a ceil() function to each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The resulting dense vector.
+//
+// This function applies the \a ceil() function to each element of the input vector \a dv. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a ceil() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = ceil( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Ceil,TF> ceil( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Ceil,TF>( ~dv, Ceil() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a vector containing the complex conjugate of each single element of \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The complex conjugate of each single element of \a dv.
+//
+// The \a conj function calculates the complex conjugate of each element of the input vector
+// \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a conj function:
+
+ \code
+ blaze::DynamicVector< complex<double> > a, b;
+ // ... Resizing and initialization
+ b = conj( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Conj,TF> conj( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Conj,TF>( ~dv, Conj() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the conjugate transpose vector of \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The conjugate transpose of \a dv.
+//
+// The \a ctrans function returns an expression representing the conjugate transpose (also called
+// adjoint matrix, Hermitian conjugate matrix or transjugate matrix) of the given input vector
+// \a dv.\n
+// The following example demonstrates the use of the \a ctrans function:
+
+ \code
+ blaze::DynamicVector< complex<double> > a, b;
+ // ... Resizing and initialization
+ b = ctrans( a );
+ \endcode
+
+// Note that the \a ctrans function has the same effect as manually applying the \a conj and
+// \a trans function in any order:
+
+ \code
+ b = trans( conj( a ) ); // Computing the conjugate transpose vector
+ b = conj( trans( a ) ); // Computing the conjugate transpose vector
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const CTransExprTrait_<VT> ctrans( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return trans( conj( ~dv ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a vector containing the real part of each single element of \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The real part of each single element of \a dv.
+//
+// The \a real function calculates the real part of each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a real function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = real( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Real,TF> real( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Real,TF>( ~dv, Real() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a vector containing the imaginary part of each single element of \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The imaginary part of each single element of \a dv.
+//
+// The \a imag function calculates the imaginary part of each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a imag function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = imag( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Imag,TF> imag( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Imag,TF>( ~dv, Imag() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the square root of each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[0..\infty)\f$.
+// \return The square root of each single element of \a dv.
+//
+// The \a sqrt() function computes the square root of each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sqrt() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = sqrt( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Sqrt,TF> sqrt( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Sqrt,TF>( ~dv, Sqrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse square root of each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$(0..\infty)\f$.
+// \return The inverse square root of each single element of \a dv.
+//
+// The \a invsqrt() function computes the inverse square root of each element of the input vector
+// \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a invsqrt() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = invsqrt( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$(0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,InvSqrt,TF> invsqrt( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,InvSqrt,TF>( ~dv, InvSqrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the cubic root of each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[0..\infty)\f$.
+// \return The cubic root of each single element of \a dv.
+//
+// The \a cbrt() function computes the cubic root of each element of the input vector \a dv. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cbrt() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = cbrt( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Cbrt,TF> cbrt( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Cbrt,TF>( ~dv, Cbrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cubic root of each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$(0..\infty)\f$.
+// \return The inverse cubic root of each single element of \a dv.
+//
+// The \a invcbrt() function computes the inverse cubic root of each element of the input vector
+// \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a invcbrt() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = invcbrt( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$(0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,InvCbrt,TF> invcbrt( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,InvCbrt,TF>( ~dv, InvCbrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the exponential value for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \param exp The exponent.
+// \return The exponential value of each single element of \a dv.
+//
+// The \a pow() function computes the exponential value for each element of the input vector
+// \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a pow() function:
+
+ \code
+ blaze::DynamicVector<double> A, B;
+ // ... Resizing and initialization
+ B = pow( A, 4.2 );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF // Transpose flag
+ , typename ET > // Type of the exponent
+inline const DVecForEachExpr<VT,Pow<ET>,TF> pow( const DenseVector<VT,TF>& dv, ET exp )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET );
+
+ return DVecForEachExpr<VT,Pow<ET>,TF>( ~dv, Pow<ET>( exp ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes \f$ e^x \f$ for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The resulting dense vector.
+//
+// The \a exp() function computes \f$ e^x \f$ for each element of the input vector \a dv. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a exp() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = exp( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Exp,TF> exp( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Exp,TF>( ~dv, Exp() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the natural logarithm for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[0..\infty)\f$.
+// \return The natural logarithm of each single element of \a dv.
+//
+// The \a log() function computes natural logarithm for each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a log() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = log( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Log,TF> log( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Log,TF>( ~dv, Log() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the common logarithm for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[0..\infty)\f$.
+// \return The common logarithm of each single element of \a dv.
+//
+// The \a log10() function computes common logarithm for each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a log10() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = log10( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Log10,TF> log10( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Log10,TF>( ~dv, Log10() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the sine for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The sine of each single element of \a dv.
+//
+// The \a sin() function computes the sine for each element of the input vector \a dv. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sin() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = sin( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Sin,TF> sin( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Sin,TF>( ~dv, Sin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse sine for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[-1..1]\f$.
+// \return The inverse sine of each single element of \a dv.
+//
+// The \a asin() function computes the inverse sine for each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a asin() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = asin( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Asin,TF> asin( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Asin,TF>( ~dv, Asin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic sine for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The hyperbolic sine of each single element of \a dv.
+//
+// The \a sinh() function computes the hyperbolic sine for each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sinh() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = sinh( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Sinh,TF> sinh( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Sinh,TF>( ~dv, Sinh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic sine for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The inverse hyperbolic sine of each single element of \a dv.
+//
+// The \a asinh() function computes the inverse hyperbolic sine for each element of the input
+// vector \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a asinh() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = asinh( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Asinh,TF> asinh( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Asinh,TF>( ~dv, Asinh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the cosine for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The cosine of each single element of \a dv.
+//
+// The \a cos() function computes the cosine for each element of the input vector \a dv. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cos() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = cos( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Cos,TF> cos( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Cos,TF>( ~dv, Cos() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cosine for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[-1..1]\f$.
+// \return The inverse cosine of each single element of \a dv.
+//
+// The \a acos() function computes the inverse cosine for each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a acos() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = acos( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Acos,TF> acos( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Acos,TF>( ~dv, Acos() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic cosine for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The hyperbolic cosine of each single element of \a dv.
+//
+// The \a cosh() function computes the hyperbolic cosine for each element of the input vector
+// \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cosh() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = cosh( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Cosh,TF> cosh( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Cosh,TF>( ~dv, Cosh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic cosine for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[1..\infty)\f$.
+// \return The inverse hyperbolic cosine of each single element of \a dv.
+//
+// The \a acosh() function computes the inverse hyperbolic cosine for each element of the input
+// vector \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a acosh() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = acosh( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[1..\infty)\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Acosh,TF> acosh( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Acosh,TF>( ~dv, Acosh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the tangent for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The tangent of each single element of \a dv.
+//
+// The \a tan() function computes the tangent for each element of the input vector \a dv. The
+// function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a tan() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = tan( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Tan,TF> tan( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Tan,TF>( ~dv, Tan() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse tangent for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The inverse tangent of each single element of \a dv.
+//
+// The \a atan() function computes the inverse tangent for each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a atan() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = atan( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Atan,TF> atan( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Atan,TF>( ~dv, Atan() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic tangent for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[-1..1]\f$.
+// \return The hyperbolic tangent of each single element of \a dv.
+//
+// The \a tanh() function computes the hyperbolic tangent for each element of the input vector
+// \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a tanh() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = tanh( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Tanh,TF> tanh( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Tanh,TF>( ~dv, Tanh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic tangent for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector; all elements must be in the range \f$[-1..1]\f$.
+// \return The inverse hyperbolic tangent of each single element of \a dv.
+//
+// The \a atanh() function computes the inverse hyperbolic tangent for each element of the input
+// vector \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a atanh() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = atanh( a );
+ \endcode
+
+// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are
+// performed to assert this precondition!
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Atanh,TF> atanh( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Atanh,TF>( ~dv, Atanh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the error function for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The error function of each single element of \a dv.
+//
+// The \a erf() function computes the error function for each element of the input vector \a dv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a erf() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = erf( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Erf,TF> erf( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Erf,TF>( ~dv, Erf() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the complementary error function for each single element of the dense vector \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The complementary error function of each single element of \a dv.
+//
+// The \a erfc() function computes the complementary error function for each element of the input
+// vector \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a erfc() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = erfc( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Erfc,TF> erfc( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecForEachExpr<VT,Erfc,TF>( ~dv, Erfc() );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Absolute value function for absolute value dense vector expressions.
+// \ingroup dense_vector
+//
+// \param dv The absolute value dense vector expression.
+// \return The absolute value of each single element of \a dv.
+//
+// This function implements a performance optimized treatment of the absolute value operation
+// on a dense vector absolute value expression.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Abs,TF>& abs( const DVecForEachExpr<VT,Abs,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Applies the \a floor() function to a dense vector \a floor() expressions.
+// \ingroup dense_vector
+//
+// \param dv The dense vector \a floor expression.
+// \return The resulting dense vector.
+//
+// This function implements a performance optimized treatment of the \a floor() operation on
+// a dense vector \a floor() expression.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Floor,TF>& floor( const DVecForEachExpr<VT,Floor,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Applies the \a ceil() function to a dense vector \a ceil() expressions.
+// \ingroup dense_vector
+//
+// \param dv The dense vector \a ceil expression.
+// \return The resulting dense vector.
+//
+// This function implements a performance optimized treatment of the \a ceil() operation on
+// a dense vector \a ceil() expression.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Ceil,TF>& ceil( const DVecForEachExpr<VT,Ceil,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Complex conjugate function for complex conjugate dense vector expressions.
+// \ingroup dense_vector
+//
+// \param dv The complex conjugate dense vector expression.
+// \return The original dense vector.
+//
+// This function implements a performance optimized treatment of the complex conjugate operation
+// on a dense vector complex conjugate expression. It returns an expression representing the
+// original dense vector:
+
+ \code
+ blaze::DynamicVector< complex<double> > a, b;
+ // ... Resizing and initialization
+ b = conj( conj( a ) );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename DVecForEachExpr<VT,Conj,TF>::Operand conj( const DVecForEachExpr<VT,Conj,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dv.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Complex conjugate function for conjugate transpose dense vector expressions.
+// \ingroup dense_vector
+//
+// \param dv The conjugate transpose dense vector expression.
+// \return The transpose dense vector.
+//
+// This function implements a performance optimized treatment of the complex conjugate operation
+// on a dense vector conjugate transpose expression. It returns an expression representing the
+// transpose of the dense vector:
+
+ \code
+ blaze::DynamicVector< complex<double> > a, b;
+ // ... Resizing and initialization
+ b = conj( ctrans( a ) );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecTransExpr<VT,!TF> conj( const DVecTransExpr<DVecForEachExpr<VT,Conj,TF>,!TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecTransExpr<VT,!TF>( dv.operand().operand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Real part function for real part dense vector expressions.
+// \ingroup dense_vector
+//
+// \param dv The real part dense vector expression.
+// \return The real part of each single element of \a dv.
+//
+// This function implements a performance optimized treatment of the real part operation on
+// a dense vector real part expression.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecForEachExpr<VT,Real,TF>& real( const DVecForEachExpr<VT,Real,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename OP, bool TF >
+struct Size< DVecForEachExpr<VT,OP,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename OP, bool TF >
+struct IsAligned< DVecForEachExpr<VT,OP,TF> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename OP, bool TF >
+struct IsPadded< DVecForEachExpr<VT,OP,TF> >
+ : public BoolConstant< IsPadded<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecForEachExprTrait< DVecForEachExpr<VT,Abs,false>, Abs >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecForEachExpr<VT,Abs,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecForEachExprTrait< DVecForEachExpr<VT,Abs,true>, Abs >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecForEachExpr<VT,Abs,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecForEachExprTrait< DVecForEachExpr<VT,Floor,false>, Floor >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecForEachExpr<VT,Floor,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecForEachExprTrait< DVecForEachExpr<VT,Floor,true>, Floor >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecForEachExpr<VT,Floor,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecForEachExprTrait< DVecForEachExpr<VT,Ceil,false>, Ceil >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecForEachExpr<VT,Ceil,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecForEachExprTrait< DVecForEachExpr<VT,Ceil,true>, Ceil >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecForEachExpr<VT,Ceil,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecForEachExprTrait< DVecForEachExpr<VT,Conj,false>, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , Operand_< DVecForEachExpr<VT,Conj,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecForEachExprTrait< DVecForEachExpr<VT,Conj,true>, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , Operand_< DVecForEachExpr<VT,Conj,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecForEachExprTrait< DVecTransExpr< DVecForEachExpr<VT,Conj,true>, false >, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecTransExpr<VT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecForEachExprTrait< DVecTransExpr< DVecForEachExpr<VT,Conj,false>, true >, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecTransExpr<VT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecForEachExprTrait< DVecForEachExpr<VT,Real,false>, Real >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecForEachExpr<VT,Real,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecForEachExprTrait< DVecForEachExpr<VT,Real,true>, Real >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecForEachExpr<VT,Real,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename OP, bool TF, bool AF >
+struct SubvectorExprTrait< DVecForEachExpr<VT,OP,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = ForEachExprTrait_< SubvectorExprTrait_<const VT,AF>, OP >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecSVecAddExpr.h b/src/cpu/blaze/math/expressions/DVecSVecAddExpr.h
new file mode 100644
index 00000000..fb022557
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecSVecAddExpr.h
@@ -0,0 +1,946 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecSVecAddExpr.h
+// \brief Header file for the dense vector/sparse vector addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECSVECADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECSVECADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/VecVecAddExpr.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecVecAddExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECSVECADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-sparse vector additions.
+// \ingroup dense_vector_expression
+//
+// The DVecSVecAddExpr class represents the compile time expression for additions between
+// a dense vector and a sparse vector.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class DVecSVecAddExpr : public DenseVector< DVecSVecAddExpr<VT1,VT2,TF>, TF >
+ , private VecVecAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ typedef TransposeType_<VT1> TT1; //!< Transpose type of the left-hand side dense vector expression.
+ typedef TransposeType_<VT2> TT2; //!< Transpose type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two vector operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT1::smpAssignable || !VT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecSVecAddExpr<VT1,VT2,TF> This; //!< Type of this DVecSVecAddExpr instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecSVecAddExpr class.
+ //
+ // \param lhs The left-hand side dense vector operand of the addition expression.
+ // \param rhs The right-hand side sparse vector operand of the addition expression.
+ */
+ explicit inline DVecSVecAddExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the addition expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] + rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<VT1>::value && lhs_.canAlias( alias ) ) ||
+ ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the addition expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector addition expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector addition to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector addition expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // sparse vector addition expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // sparse vector addition expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-sparse vector addition expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // sparse vector addition expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-sparse
+ // vector addition expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-sparse vector addition to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-sparse
+ // vector addition expression to a sparse vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( SparseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector-sparse vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // sparse vector addition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-sparse vector addition to a dense
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector-sparse vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector-sparse vector addition to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP divison assignment of a dense vector-
+ // sparse vector addition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpDivAssign( DenseVector<VT,TF>& lhs, const DVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECADDEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a dense vector and a sparse vector
+// (\f$ \vec{a}=\vec{b}+\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the vector addition.
+// \param rhs The right-hand side sparse vector for the vector addition.
+// \return The sum of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the addition of a dense vector and a sparse vector:
+
+ \code
+ blaze::DynamicVector<double> a, c;
+ blaze::CompressedVector<double> b;
+ // ... Resizing and initialization
+ c = a + b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const DVecSVecAddExpr<T1,T2,TF>
+ operator+( const DenseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return DVecSVecAddExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a sparse vector and a dense vector
+// (\f$ \vec{a}=\vec{b}+\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector for the vector addition.
+// \param rhs The right-hand side dense vector for the vector addition.
+// \return The sum of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the addition of a sparse vector and a dense vector:
+
+ \code
+ blaze::CompressedVector<double> a;
+ blaze::DynamicVector<double> b, c;
+ // ... Resizing and initialization
+ c = a + b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const DVecSVecAddExpr<T2,T1,TF>
+ operator+( const SparseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return DVecSVecAddExpr<T2,T1,TF>( ~rhs, ~lhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a dense vector-sparse vector addition
+// expression and a dense vector (\f$ \vec{a}=(\vec{b}+\vec{c})+\vec{d} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector-sparse vector addition.
+// \param rhs The right-hand side dense vector.
+// \return The sum of the two vectors.
+//
+// This operator implements a performance optimized treatment of the addition of a dense
+// vector-sparse vector addition expression to a dense vector.
+*/
+template< typename T1 // Type of the dense vector of the left-hand side expression
+ , typename T2 // Type of the sparse vector of the left-hand side expression
+ , bool TF // Transpose flag of the left-hand side expression
+ , typename T3 > // Type of the right-hand side dense vector
+inline const AddExprTrait_< DVecSVecAddExpr<T1,T2,TF>, T3 >
+ operator+( const DVecSVecAddExpr<T1,T2,TF>& lhs, const DenseVector<T3,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() + (~rhs) ) + lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a dense vector-sparse vector addition
+// expression and a dense vector (\f$ \vec{a}=(\vec{b}+\vec{c})-\vec{d} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector-sparse vector addition.
+// \param rhs The right-hand side dense vector.
+// \return The difference of the two vectors.
+//
+// This operator implements a performance optimized treatment of the subtraction of a
+// dense vector-sparse vector addition expression and a dense vector.
+*/
+template< typename T1 // Type of the dense vector of the left-hand side expression
+ , typename T2 // Type of the sparse vector of the left-hand side expression
+ , bool TF // Transpose flag of the left-hand side expression
+ , typename T3 > // Type of the right-hand side dense vector
+inline const SubExprTrait_< DVecSVecAddExpr<T1,T2,TF>, T3 >
+ operator-( const DVecSVecAddExpr<T1,T2,TF>& lhs, const DenseVector<T3,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() - (~rhs) ) + lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecSVecAddExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct DVecDVecAddExprTrait< DVecSVecAddExpr<VT1,VT2,false>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsDenseVector<VT3>, IsColumnVector<VT3> >
+ , DVecSVecAddExprTrait_< DVecDVecAddExprTrait_<VT1,VT3>, VT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct TDVecTDVecAddExprTrait< DVecSVecAddExpr<VT1,VT2,true>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsDenseVector<VT3>, IsRowVector<VT3> >
+ , TDVecTSVecAddExprTrait_< TDVecTDVecAddExprTrait_<VT1,VT3>, VT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct DVecDVecSubExprTrait< DVecSVecAddExpr<VT1,VT2,false>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsDenseVector<VT3>, IsColumnVector<VT3> >
+ , DVecSVecAddExprTrait_< DVecDVecSubExprTrait_<VT1,VT3>, VT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct TDVecTDVecSubExprTrait< DVecSVecAddExpr<VT1,VT2,true>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsDenseVector<VT3>, IsRowVector<VT3> >
+ , TDVecTSVecAddExprTrait_< TDVecTDVecSubExprTrait_<VT1,VT3>, VT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecSVecAddExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecSVecCrossExpr.h b/src/cpu/blaze/math/expressions/DVecSVecCrossExpr.h
new file mode 100644
index 00000000..7882e376
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecSVecCrossExpr.h
@@ -0,0 +1,573 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecSVecCrossExpr.h
+// \brief Header file for the dense vector/sparse vector cross product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECSVECCROSSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECSVECCROSSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/dense/Forward.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/CrossExpr.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECSVECCROSSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-sparse vector cross products.
+// \ingroup dense_vector_expression
+//
+// The DVecSVecCrossExpr class represents the compile time expression for cross products
+// between a dense vector and a sparse vector.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class DVecSVecCrossExpr : public DenseVector< DVecSVecCrossExpr<VT1,VT2,TF>, TF >
+ , private CrossExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side dense vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_< MultExprTrait_<RN1,RN2>, MultExprTrait_<RN1,RN2> > ExprReturnType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecSVecCrossExpr<VT1,VT2,TF> This; //!< Type of this DVecSVecCrossExpr instance.
+ typedef CrossTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsComputation<VT1>, const StaticVector<ET1,3UL,TF>, CT1 > LT;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef const StaticVector<ET2,3UL,TF> RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecSVecCrossExpr class.
+ //
+ // \param lhs The left-hand side operand of the cross product expression.
+ // \param rhs The right-hand side operand of the cross product expression.
+ */
+ explicit inline DVecSVecCrossExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the cross product expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the cross product expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( rhs.size() == 3UL, "Invalid vector size" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..2]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < 3UL, "Invalid vector access index" );
+
+ if( index == 0UL )
+ return lhs_[1UL] * rhs_[2UL] - lhs_[2UL] * rhs_[1UL];
+ else if( index == 1UL )
+ return lhs_[2UL] * rhs_[0UL] - lhs_[0UL] * rhs_[2UL];
+ else
+ return lhs_[0UL] * rhs_[1UL] - lhs_[1UL] * rhs_[0UL];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= 3UL ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline constexpr size_t size() const noexcept {
+ return 3UL;
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the cross product expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the cross product expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT,TF>& lhs, const DVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] = x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] = x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] = x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector cross product to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side cross product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector cross product expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const DVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // sparse vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const DVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] += x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] += x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] += x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // sparse vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const DVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] -= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] -= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] -= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-sparse vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const DVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] *= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] *= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] *= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // sparse vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT,TF>& lhs, const DVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] /= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] /= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] /= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Operator for the cross product of a dense vector and a sparse vector
+// (\f$ \vec{a}=\vec{b} \times \vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the cross product.
+// \param rhs The right-hand side sparse vector for the cross product.
+// \return The cross product of the two vectors.
+// \exception std::invalid_argument Invalid vector size for cross product.
+//
+// This operator represents the cross product of a dense vector and a sparse vector:
+
+ \code
+ blaze::DynamicVector<double> a( 3UL );
+ blaze::CompressedVector<double> b( 3UL );
+ blaze::StaticVector<double,3UL> c;
+ // ... Resizing and initialization
+ c = a % b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the CrossTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const DVecSVecCrossExpr<T1,T2,TF>
+ operator%( const DenseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != 3UL || (~rhs).size() != 3UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" );
+ }
+
+ return DVecSVecCrossExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Cross product of a dense vector and a sparse vector (\f$ \vec{a}=\vec{b} \times \vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the cross product.
+// \param rhs The right-hand side sparse vector for the cross product.
+// \return The cross product of the two vectors.
+// \exception std::invalid_argument Invalid vector size for cross product.
+//
+// This function computes the cross product of a dense vector and a sparse vector:
+
+ \code
+ blaze::DynamicVector<double> a( 3UL );
+ blaze::CompressedVector<double> b( 3UL );
+ blaze::StaticVector<double,3UL> c;
+ // ... Resizing and initialization
+ c = a % b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the CrossTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const DVecSVecCrossExpr<T1,T2,TF>
+ cross( const DenseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ return lhs % rhs;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecSVecCrossExpr<VT1,VT2,TF> > : public SizeT<3UL>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecSVecMultExpr.h b/src/cpu/blaze/math/expressions/DVecSVecMultExpr.h
new file mode 100644
index 00000000..f3c9f5a2
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecSVecMultExpr.h
@@ -0,0 +1,777 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecSVecMultExpr.h
+// \brief Header file for the dense vector/sparse vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecVecMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECSVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-sparse vector multiplications.
+// \ingroup sparse_vector_expression
+//
+// The DVecSVecMultExpr class represents the compile time expression for componentwise
+// multiplications between a dense vector and a sparse vector.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class DVecSVecMultExpr : public SparseVector< DVecSVecMultExpr<VT1,VT2,TF>, TF >
+ , private VecVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ typedef TransposeType_<VT1> TT1; //!< Transpose type of the left-hand side dense vector expression.
+ typedef TransposeType_<VT2> TT2; //!< Transpose type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Evaluation strategy*************************************************************************
+ //! Compilation switch for the evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the multiplication expression. In case either the dense or
+ the sparse vector operand requires an intermediate evaluation, \a useAssign will be set
+ to \a true and the multiplication expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to \a false and the expression will be
+ evaluated via the subscript operator. */
+ enum : bool { useAssign = ( RequiresEvaluation<VT1>::value || RequiresEvaluation<VT2>::value ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecSVecMultExpr<VT1,VT2,TF> This; //!< Type of this DVecSVecMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecSVecMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector-sparse vector multiplication expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse vector expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<RightOperand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( LeftOperand vec, IteratorType it )
+ : vec_( vec ) // Left-hand side dense vector expression
+ , it_ ( it ) // Iterator over the elements of the right-hand side sparse vector expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( vec_[it_->index()] * it_->value(), it_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return vec_[it_->index()] * it_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftOperand vec_; //!< Left-hand side dense vector expression.
+ IteratorType it_; //!< Iterator over the elements of the right-hand side sparse vector expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecSVecMultExpr class.
+ //
+ // \param lhs The left-hand side dense vector operand of the multiplication expression.
+ // \param rhs The right-hand side sparse vector operand of the multiplication expression.
+ */
+ explicit inline DVecSVecMultExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] * rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( lhs_, rhs_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( lhs_, rhs_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific vector element.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT2 );
+ return ConstIterator( lhs_, rhs_.find( index ) );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT2 );
+ return ConstIterator( lhs_, rhs_.lowerBound( index ) );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT2 );
+ return ConstIterator( lhs_, rhs_.upperBound( index ) );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( DenseVector<VT,TF>& lhs, const DVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=y.begin(); element!=y.end(); ++element )
+ (~lhs)[element->index()] = x[element->index()] * element->value();
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector multiplication to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( SparseVector<VT,TF>& lhs, const DVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=y.begin(); element!=y.end(); ++element )
+ (~lhs).append( element->index(), x[element->index()] * element->value() );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // sparse vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ addAssign( DenseVector<VT,TF>& lhs, const DVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=y.begin(); element!=y.end(); ++element )
+ (~lhs)[element->index()] += x[element->index()] * element->value();
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // sparse vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ subAssign( DenseVector<VT,TF>& lhs, const DVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=y.begin(); element!=y.end(); ++element )
+ (~lhs)[element->index()] -= x[element->index()] * element->value();
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ multAssign( DenseVector<VT,TF>& lhs, const DVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const ConstIterator end( y.end() );
+ ConstIterator begin( y.begin() );
+ size_t i( 0UL );
+
+ for( ; begin!=end; ++begin ) {
+ const size_t index( begin->index() );
+ for( ; i<index; ++i )
+ reset( (~lhs)[i] );
+ (~lhs)[index] *= x[index] * begin->value();
+ ++i;
+ }
+
+ for( ; i<(~lhs).size(); ++i )
+ reset( (~lhs)[i] );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECMULTEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the componentwise product of a dense vector and a sparse
+// vector (\f$ \vec{a}=\vec{b}*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side dense vector for the component product.
+// \param rhs The right-hand side sparse vector for the component product.
+// \return The product of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the componentwise multiplication of a dense vector and a sparse
+// vector:
+
+ \code
+ blaze::DynamicVector<double> a;
+ blaze::CompressedVector<double> b, c;
+ // ... Resizing and initialization
+ c = a * b;
+ \endcode
+
+// The operator returns an expression representing a sparse vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const DVecSVecMultExpr<T1,T2,TF>
+ operator*( const DenseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return DVecSVecMultExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecSVecMultExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecSVecMultExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecSVecSubExpr.h b/src/cpu/blaze/math/expressions/DVecSVecSubExpr.h
new file mode 100644
index 00000000..50b65781
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecSVecSubExpr.h
@@ -0,0 +1,904 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecSVecSubExpr.h
+// \brief Header file for the dense vector/sparse vector subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECSVECSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECSVECSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecSubExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecVecSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECSVECSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-sparse vector subtractions.
+// \ingroup dense_vector_expression
+//
+// The DVecSVecSubExpr class represents the compile time expression for subtractions between
+// a dense vector and a sparse vector.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class DVecSVecSubExpr : public DenseVector< DVecSVecSubExpr<VT1,VT2,TF>, TF >
+ , private VecVecSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ typedef TransposeType_<VT1> TT1; //!< Transpose type of the left-hand side dense vector expression.
+ typedef TransposeType_<VT2> TT2; //!< Transpose type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two vector operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT1::smpAssignable || !VT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecSVecSubExpr<VT1,VT2,TF> This; //!< Type of this DVecSVecSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecSVecSubExpr class.
+ //
+ // \param lhs The left-hand side dense vector operand of the subtraction expression.
+ // \param rhs The right-hand side sparse vector operand of the subtraction expression.
+ */
+ explicit inline DVecSVecSubExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] - rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<VT1>::value && lhs_.canAlias( alias ) ) ||
+ ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector subtraction to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector subtraction expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-sparse vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // sparse vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-sparse vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // sparse vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-sparse vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-sparse vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-sparse vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ //sparse vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-sparse vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-sparse
+ // vector subtraction expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( !IsComputation<VT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-sparse vector subtraction to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-sparse
+ // vector subtraction expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( SparseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-sparse vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector-sparse vector subtraction expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-sparse vector subtraction to a dense
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector-sparse vector subtraction expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-sparse vector subtraction to a dense
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // dense vector-sparse vector subtraction expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector-sparse vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense
+ // vector-sparse vector subtraction expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpDivAssign( DenseVector<VT,TF>& lhs, const DVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP divisor assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECSUBEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a dense vector and a sparse vector
+// (\f$ \vec{a}=\vec{b}-\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the vector subtraction.
+// \param rhs The right-hand side sparse vector to be subtracted from the dense vector.
+// \return The difference of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the subtraction of a dense vector and a sparse vector:
+
+ \code
+ blaze::DynamicVector<double> a, c;
+ blaze::CompressedVector<double> b;
+ // ... Resizing and initialization
+ c = a - b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const DVecSVecSubExpr<T1,T2,TF>
+ operator-( const DenseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return DVecSVecSubExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a dense vector-sparse vector subtraction
+// expression and a dense vector (\f$ \vec{a}=(\vec{b}-\vec{c})+\vec{d} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector-sparse vector subtraction.
+// \param rhs The right-hand side dense vector.
+// \return The sum of the two vectors.
+//
+// This operator implements a performance optimized treatment of the addition of a dense
+// vector-sparse vector subtraction expression to a dense vector.
+*/
+template< typename T1 // Type of the dense vector of the left-hand side expression
+ , typename T2 // Type of the sparse vector of the left-hand side expression
+ , bool TF // Transpose flag of the left-hand side expression
+ , typename T3 > // Type of the right-hand side dense vector
+inline const AddExprTrait_< DVecSVecSubExpr<T1,T2,TF>, T3 >
+ operator+( const DVecSVecSubExpr<T1,T2,TF>& lhs, const DenseVector<T3,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() + (~rhs) ) - lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a dense vector-sparse vector subtraction
+// expression and a dense vector (\f$ \vec{a}=(\vec{b}-\vec{c})-\vec{d} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector-sparse vector subtraction.
+// \param rhs The right-hand side dense vector.
+// \return The difference of the two vectors.
+//
+// This operator implements a performance optimized treatment of the subtraction of a
+// dense vector-sparse vector subtraction expression and a dense vector.
+*/
+template< typename T1 // Type of the dense vector of the left-hand side expression
+ , typename T2 // Type of the sparse vector of the left-hand side expression
+ , bool TF // Transpose flag of the left-hand side expression
+ , typename T3 > // Type of the right-hand side dense vector
+inline const SubExprTrait_< DVecSVecSubExpr<T1,T2,TF>, T3 >
+ operator-( const DVecSVecSubExpr<T1,T2,TF>& lhs, const DenseVector<T3,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() - (~rhs) ) - lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< DVecSVecSubExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct DVecDVecAddExprTrait< DVecSVecSubExpr<VT1,VT2,false>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsDenseVector<VT3>, IsColumnVector<VT3> >
+ , DVecSVecSubExprTrait_< DVecDVecAddExprTrait_<VT1,VT3>, VT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct TDVecTDVecAddExprTrait< DVecSVecSubExpr<VT1,VT2,true>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsDenseVector<VT3>, IsRowVector<VT3> >
+ , TDVecTSVecSubExprTrait_< TDVecTDVecAddExprTrait_<VT1,VT3>, VT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct DVecDVecSubExprTrait< DVecSVecSubExpr<VT1,VT2,false>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsDenseVector<VT3>, IsColumnVector<VT3> >
+ , DVecSVecSubExprTrait_< DVecDVecSubExprTrait_<VT1,VT3>, VT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct TDVecTDVecSubExprTrait< DVecSVecSubExpr<VT1,VT2,true>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsDenseVector<VT3>, IsRowVector<VT3> >
+ , TDVecTSVecSubExprTrait_< TDVecTDVecSubExprTrait_<VT1,VT3>, VT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecSVecSubExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecScalarDivExpr.h b/src/cpu/blaze/math/expressions/DVecScalarDivExpr.h
new file mode 100644
index 00000000..06dbbb30
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecScalarDivExpr.h
@@ -0,0 +1,1314 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecScalarDivExpr.h
+// \brief Header file for the dense vector/scalar division expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECSCALARDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecScalarDivExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsMultExpr.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/math/typetraits/UnderlyingElement.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECSCALARDIVEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for divisions of a dense vector by a scalar.
+// \ingroup dense_vector_expression
+//
+// The DVecScalarDivExpr class represents the compile time expression for divisions of dense
+// vectors by scalar values.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST // Type of the right-hand side scalar value
+ , bool TF > // Transpose flag
+class DVecScalarDivExpr : public DenseVector< DVecScalarDivExpr<VT,ST,TF>, TF >
+ , private VecScalarDivExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> RT; //!< Result type of the dense vector expression.
+ typedef ReturnType_<VT> RN; //!< Return type of the dense vector expression.
+ typedef ElementType_<VT> ET; //!< Element type of the dense vector expression.
+ typedef CompositeType_<VT> CT; //!< Composite type of the dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If the vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef DivExprTrait_<RN,ST> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the division expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the division expression. In case the given dense
+ vector expression of type \a VT is a computation expression and requires an intermediate
+ evaluation, \a useAssign will be set to 1 and the division expression will be evaluated
+ via the \a assign function family. Otherwise \a useAssign will be set to 0 and the
+ expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = IsComputation<VT>::value && RequiresEvaluation<VT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target vector or the dense vector operand is not SMP assignable
+ and the vector operand is a computation expression that requires an intermediate evaluation,
+ \a value is set to 1 and the expression specific evaluation strategy is selected. Otherwise
+ \a value is set to 0 and the default strategy is chosen. */
+ template< typename VT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT2::smpAssignable || !VT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecScalarDivExpr<VT,ST,TF> This; //!< Type of this DVecScalarDivExpr instance.
+ typedef DivTrait_<RT,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecScalarDivExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the dense vector expression.
+ typedef ConstIterator_<VT> IteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ // \param scalar Scalar of the division expression.
+ */
+ explicit inline ConstIterator( IteratorType iterator, RightOperand scalar )
+ : iterator_( iterator ) // Iterator to the current element
+ , scalar_ ( scalar ) // Scalar of the division expression
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( iterator_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( iterator_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return *iterator_ / scalar_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return iterator_.load() / set( scalar_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.iterator_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.iterator_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.iterator_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current element.
+ RightOperand scalar_; //!< Scalar of the division expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT::simdEnabled &&
+ IsNumeric<ET>::value &&
+ ( HasSIMDDiv<ET,ST>::value ||
+ HasSIMDDiv<UnderlyingElement_<ET>,ST>::value ) };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecScalarDivExpr class.
+ //
+ // \param vector The left-hand side dense vector of the division expression.
+ // \param scalar The right-hand side scalar of the division expression.
+ */
+ explicit inline DVecScalarDivExpr( const VT& vector, ST scalar ) noexcept
+ : vector_( vector ) // Left-hand side dense vector of the division expression
+ , scalar_( scalar ) // Right-hand side scalar of the division expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
+ return vector_[index] / scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= vector_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t index ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size() , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ return vector_.load( index ) / set( scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the dense vector.
+ //
+ // \return Iterator to the first non-zero element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( vector_.begin(), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
+ //
+ // \return Iterator just past the last non-zero element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( vector_.end(), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return vector_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vector_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return IsComputation<VT>::value && vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return vector_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return vector_.canSMPAssign() || ( size() > SMP_DVECSCALARMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vector_; //!< Left-hand side dense vector of the division expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the division expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-scalar
+ // division expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the vector
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.vector_ );
+ assign( ~lhs, (~lhs) / rhs.scalar_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-scalar division to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-scalar
+ // division expression to a sparse vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the vector
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.vector_ );
+ (~lhs) /= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // scalar division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // scalar division expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the vector operand is
+ // a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-scalar division expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // vector operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // scalar division expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the vector operand
+ // is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ divAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-
+ // scalar division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.vector_ );
+ smpAssign( ~lhs, (~lhs) / rhs.scalar_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-scalar division to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-
+ // scalar division expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.vector_ );
+ (~lhs) /= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector-scalar division expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector-scalar division expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // dense vector-scalar division expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector-scalar division to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense
+ // vector-scalar division expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,TF>& lhs, const DVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ElementType );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division operator for the divison of a dense vector by a scalar value
+// (\f$ \vec{a}=\vec{b}/s \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector for the division.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result vector.
+//
+// This operator represents the division of a dense vector by a scalar value:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = a / 0.24;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order
+// element type of the involved data types \a T1::ElementType and \a T2. Both data types
+// \a T1::ElementType and \a T2 have to be supported by the DivTrait class template.
+// Note that this operator only works for scalar values of built-in data type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side scalar
+ , bool TF > // Transpose flag
+inline const EnableIf_< IsNumeric<T2>, DivExprTrait_<T1,T2> >
+ operator/( const DenseVector<T1,TF>& vec, T2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_USER_ASSERT( scalar != T2(0), "Division by zero detected" );
+
+ typedef DivExprTrait_<T1,T2> ReturnType;
+ typedef RightOperand_<ReturnType> ScalarType;
+
+ if( IsMultExpr<ReturnType>::value ) {
+ return ReturnType( ~vec, ScalarType(1)/ScalarType(scalar) );
+ }
+ else {
+ return ReturnType( ~vec, scalar );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector-scalar division
+// expression and a scalar value (\f$ \vec{a}=(\vec{b}/s1)*s2 \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector-scalar division.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// dense vector-scalar division expression and a scalar value.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the dense vector
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< And< IsNumeric<ST2>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , MultExprTrait_< DVecScalarDivExpr<VT,ST1,TF>, ST2 > >
+ operator*( const DVecScalarDivExpr<VT,ST1,TF>& vec, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( scalar / vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a scalar value and a dense vector-
+// scalar division expression (\f$ \vec{a}=s2*(\vec{b}/s1) \f$).
+// \ingroup dense_vector
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param vec The right-hand side dense vector-scalar division.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// scalar value and a dense vector-scalar division expression.
+*/
+template< typename ST1 // Type of the left-hand side scalar
+ , typename VT // Type of the dense vector of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool TF > // Transpose flag of the dense vector
+inline const EnableIf_< And< IsNumeric<ST1>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , MultExprTrait_< ST1, DVecScalarDivExpr<VT,ST2,TF> > >
+ operator*( ST1 scalar, const DVecScalarDivExpr<VT,ST2,TF>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( scalar / vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division operator for the division of a dense vector-scalar division expression
+// and a scalar value (\f$ \vec{a}=(\vec{b}/s1)/s2 \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector-scalar division.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the division of a dense
+// vector-scalar division expression and a scalar value.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the dense vector
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<ST2>
+ , DivExprTrait_< VT, MultTrait_<ST1,ST2> > >
+ operator/( const DVecScalarDivExpr<VT,ST1,TF>& vec, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" );
+
+ typedef MultTrait_<ST1,ST2> MultType;
+ typedef DivExprTrait_<VT,MultType> ReturnType;
+ typedef RightOperand_<ReturnType> ScalarType;
+
+ if( IsMultExpr<ReturnType>::value ) {
+ return ReturnType( vec.leftOperand(), ScalarType(1)/( vec.rightOperand() * scalar ) );
+ }
+ else {
+ return ReturnType( vec.leftOperand(), vec.rightOperand() * scalar );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF >
+struct Size< DVecScalarDivExpr<VT,ST,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF >
+struct IsAligned< DVecScalarDivExpr<VT,ST,TF> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF >
+struct IsPadded< DVecScalarDivExpr<VT,ST,TF> >
+ : public BoolConstant< IsPadded<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct DVecScalarMultExprTrait< DVecScalarDivExpr<VT,ST1,false>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ typedef DivTrait_<ST2,ST1> ScalarType;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , DVecScalarMultExprTrait_<VT,ScalarType>
+ , DVecScalarMultExpr< DVecScalarDivExpr<VT,ST1,false>, ST2, false > >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct TDVecScalarMultExprTrait< DVecScalarDivExpr<VT,ST1,true>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ typedef DivTrait_<ST2,ST1> ScalarType;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , DVecScalarMultExprTrait_<VT,ScalarType>
+ , DVecScalarMultExpr< DVecScalarDivExpr<VT,ST1,true>, ST2, true > >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTOREXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF, bool AF >
+struct SubvectorExprTrait< DVecScalarDivExpr<VT,ST,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< SubvectorExprTrait_<const VT,AF>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecScalarMultExpr.h b/src/cpu/blaze/math/expressions/DVecScalarMultExpr.h
new file mode 100644
index 00000000..7e918f8c
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecScalarMultExpr.h
@@ -0,0 +1,2678 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecScalarMultExpr.h
+// \brief Header file for the dense vector/scalar multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECSCALARMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecScalarMultExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingElement.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECSCALARMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-scalar multiplications.
+// \ingroup dense_vector_expression
+//
+// The DVecScalarMultExpr class represents the compile time expression for multiplications between
+// a dense vector and a scalar value.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST // Type of the right-hand side scalar value
+ , bool TF > // Transpose flag
+class DVecScalarMultExpr : public DenseVector< DVecScalarMultExpr<VT,ST,TF>, TF >
+ , private VecScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> RT; //!< Result type of the dense vector expression.
+ typedef ReturnType_<VT> RN; //!< Return type of the dense vector expression.
+ typedef ElementType_<VT> ET; //!< Element type of the dense vector expression.
+ typedef CompositeType_<VT> CT; //!< Composite type of the dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If the vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN,ST> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the multiplication expression. In case the given dense
+ vector expression of type \a VT is a computation expression and requires an intermediate
+ evaluation, \a useAssign will be set to 1 and the multiplication expression will be
+ evaluated via the \a assign function family. Otherwise \a useAssign will be set to 0
+ and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = IsComputation<VT>::value && RequiresEvaluation<VT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target vector ir the dense vector operand is not SMP assignable
+ and the vector operand is a computation expression that requires an intermediate evaluation,
+ \a value is set to 1 and the expression specific evaluation strategy is selected. Otherwise
+ \a value is set to 0 and the default strategy is chosen. */
+ template< typename VT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT2::smpAssignable || !VT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecScalarMultExpr<VT,ST,TF> This; //!< Type of this DVecScalarMultExpr instance.
+ typedef MultTrait_<RT,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecScalarMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the dense vector expression.
+ typedef ConstIterator_<VT> IteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ // \param scalar Scalar of the multiplication expression.
+ */
+ explicit inline ConstIterator( IteratorType iterator, RightOperand scalar )
+ : iterator_( iterator ) // Iterator to the current element
+ , scalar_ ( scalar ) // Scalar of the multiplication expression
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( iterator_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( iterator_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return *iterator_ * scalar_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return iterator_.load() * set( scalar_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.iterator_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.iterator_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.iterator_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current element.
+ RightOperand scalar_; //!< Scalar of the multiplication expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT::simdEnabled &&
+ IsNumeric<ET>::value &&
+ ( HasSIMDMult<ET,ST>::value ||
+ HasSIMDMult<UnderlyingElement_<ET>,ST>::value ) };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecScalarMultExpr class.
+ //
+ // \param vector The left-hand side dense vector of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DVecScalarMultExpr( const VT& vector, ST scalar ) noexcept
+ : vector_( vector ) // Left-hand side dense vector of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
+ return vector_[index] * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= vector_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t index ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size() , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
+ return vector_.load( index ) * set( scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the dense vector.
+ //
+ // \return Iterator to the first non-zero element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( vector_.begin(), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
+ //
+ // \return Iterator just past the last non-zero element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( vector_.end(), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return vector_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vector_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return IsComputation<VT>::value && vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return vector_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return vector_.canSMPAssign() || ( size() > SMP_DVECSCALARMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vector_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-scalar
+ // multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.vector_ );
+ assign( ~lhs, (~lhs) * rhs.scalar_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-scalar multiplication to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-scalar
+ // multiplication expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.vector_ );
+ (~lhs) *= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // scalar multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // vector operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // scalar multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector-scalar multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // vector operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector-
+ // scalar multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // vector operand is a computation expression and requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ divAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-scalar
+ // multiplication expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.vector_ );
+ smpAssign( ~lhs, (~lhs) * rhs.scalar_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-scalar multiplication to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-scalar
+ // multiplication expression to a sparse vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.vector_ );
+ (~lhs) *= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector-scalar multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector-scalar multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector-scalar multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector-scalar multiplication to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense vector-
+ // scalar multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL UNARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unary minus operator for the negation of a dense vector (\f$ \vec{a} = -\vec{b} \f$).
+// \ingroup dense_vector
+//
+// \param dv The dense vector to be negated.
+// \return The negation of the vector.
+//
+// This operator represents the negation of a dense vector:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = -a;
+ \endcode
+
+// The operator returns an expression representing the negation of the given dense vector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecScalarMultExpr<VT,UnderlyingBuiltin_<VT>,TF>
+ operator-( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef UnderlyingBuiltin_<VT> ElementType;
+ return DVecScalarMultExpr<VT,ElementType,TF>( ~dv, ElementType(-1) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a dense vector and a scalar value
+// (\f$ \vec{a}=\vec{b}*s \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector for the multiplication.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result vector.
+//
+// This operator represents the multiplication between a dense vector and a scalar value:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = a * 1.25;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element type
+// of the involved data types \a T1::ElementType and \a T2. Both data types \a T1::ElementType and
+// \a T2 have to be supported by the MultTrait class template. Note that this operator only works
+// for scalar values of built-in data type.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side scalar
+ , bool TF > // Transpose flag
+inline const EnableIf_< IsNumeric<T2>, MultExprTrait_<T1,T2> >
+ operator*( const DenseVector<T1,TF>& vec, T2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return MultExprTrait_<T1,T2>( ~vec, scalar );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a scalar value and a dense vector
+// (\f$ \vec{a}=s*\vec{b} \f$).
+// \ingroup dense_vector
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param vec The right-hand side vector for the multiplication.
+// \return The scaled result vector.
+//
+// This operator represents the multiplication between a a scalar value and dense vector:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = 1.25 * a;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the involved data types \a T1::ElementType and \a T2. Both data types \a T1 and
+// \a T2::ElementType have to be supported by the MultTrait class template. Note that this
+// operator only works for scalar values of built-in data type.
+*/
+template< typename T1 // Type of the left-hand side scalar
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const EnableIf_< IsNumeric<T1>, MultExprTrait_<T1,T2> >
+ operator*( T1 scalar, const DenseVector<T2,TF>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return MultExprTrait_<T1,T2>( ~vec, scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Normalization of the dense vector (\f$|\vec{a}|=1\f$).
+//
+// \param vec The given dense vector.
+// \return The normalized result vector.
+//
+// This function represents the normalization of a dense vector:
+
+ \code
+ blaze::DynamicVector<double> a;
+ // ... Resizing and initialization
+ a = normalize( a );
+ \endcode
+
+// The function returns an expression representing the normalized dense vector. Note that
+// this function only works for floating point vectors. The attempt to use this function for
+// an integral vector results in a compile time error.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecScalarMultExpr<VT,ElementType_<VT>,TF>
+ normalize( const DenseVector<VT,TF>& vec )
+{
+ typedef ElementType_<VT> ElementType;
+
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType );
+
+ const ElementType len ( length( ~vec ) );
+ const ElementType ilen( ( len != ElementType(0) )?( ElementType(1) / len ):( 0 ) );
+
+ return DVecScalarMultExpr<VT,ElementType,TF>( ~vec, ilen );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING UNARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unary minus operator for the negation of a dense vector-scalar multiplication
+// (\f$ \vec{a} = -(\vec{b} * s) \f$).
+// \ingroup dense_vector
+//
+// \param dv The dense vector-scalar multiplication to be negated.
+// \return The negation of the dense vector-scalar multiplication.
+//
+// This operator implements a performance optimized treatment of the negation of a dense vector-
+// scalar multiplication expression.
+*/
+template< typename VT // Type of the dense vector
+ , typename ST // Type of the scalar
+ , bool TF > // Transpose flag
+inline const DVecScalarMultExpr<VT,ST,TF>
+ operator-( const DVecScalarMultExpr<VT,ST,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecScalarMultExpr<VT,ST,TF>( dv.leftOperand(), -dv.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector-scalar multiplication
+// expression and a scalar value (\f$ \vec{a}=(\vec{b}*s1)*s2 \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector-scalar multiplication.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// dense vector-scalar multiplication expression and a scalar value.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the dense vector
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<ST2>, MultExprTrait_< DVecScalarMultExpr<VT,ST1,TF>, ST2 > >
+ operator*( const DVecScalarMultExpr<VT,ST1,TF>& vec, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( vec.rightOperand() * scalar );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector-scalar multiplication
+// expression and a scalar value (\f$ \vec{a}=s2*(\vec{b}*s1) \f$).
+// \ingroup dense_vector
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param vec The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// scalar value and a dense vector-scalar multiplication expression.
+*/
+template< typename ST1 // Type of the left-hand side scalar
+ , typename VT // Type of the dense vector of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool TF > // Transpose flag of the dense vector
+inline const EnableIf_< IsNumeric<ST1>, MultExprTrait_< ST1, DVecScalarMultExpr<VT,ST2,TF> > >
+ operator*( ST1 scalar, const DVecScalarMultExpr<VT,ST2,TF>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( scalar * vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division operator for the division of a dense vector-scalar multiplication
+// expression by a scalar value (\f$ \vec{a}=(\vec{b}*s1)/s2 \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector-scalar multiplication.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the division of a
+// dense vector-scalar multiplication expression by a scalar value.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the dense vector
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< And< IsNumeric<ST2>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , DivExprTrait_< DVecScalarMultExpr<VT,ST1,TF>, ST2 > >
+ operator/( const DVecScalarMultExpr<VT,ST1,TF>& vec, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( vec.rightOperand() / scalar );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector-scalar multiplication
+// expression and a dense vector (\f$ \vec{a}=(\vec{b}*s1)*\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector-scalar multiplication.
+// \param rhs The right-hand side dense vector.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense vector-scalar multiplication and a dense vector. It restructures the expression
+// \f$ \vec{a}=(\vec{b}*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*s1 \f$.
+*/
+template< typename VT1 // Type of the dense vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the dense vectors
+ , typename VT2 > // Type of the right-hand side dense vector
+inline const MultExprTrait_< DVecScalarMultExpr<VT1,ST,TF>, VT2 >
+ operator*( const DVecScalarMultExpr<VT1,ST,TF>& lhs, const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector and a dense vector-
+// scalar multiplication expression (\f$ \vec{a}=\vec{b}*(\vec{c}*s1) \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense vector and a dense vector-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=\vec{b}*(\vec{c}*s1) \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*s1 \f$.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF // Transpose flag of the dense vectors
+ , typename VT2 // Type of the dense vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< VT1, DVecScalarMultExpr<VT2,ST,TF> >
+ operator*( const DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr<VT2,ST,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of two dense vector-scalar
+// multiplication expressions (\f$ \vec{a}=(\vec{b}*s1)*(\vec{c}*s2) \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector-scalar multiplication.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of
+// two dense vector-scalar multiplication expressions. It restructures the expression
+// \f$ \vec{a}=(\vec{b}*s1)*(\vec{c}*s2) \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*(s1*s2) \f$.
+*/
+template< typename VT1 // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the dense vectors
+ , typename VT2 // Type of the dense vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< DVecScalarMultExpr<VT1,ST1,TF>, DVecScalarMultExpr<VT2,ST2,TF> >
+ operator*( const DVecScalarMultExpr<VT1,ST1,TF>& lhs, const DVecScalarMultExpr<VT2,ST2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a dense vector-scalar multiplication
+// expression and a dense vector (\f$ A=(\vec{b}*s1)*\vec{c}^T \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense vector-scalar multiplication.
+// \param rhs The right-hand side dense vector.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product of a
+// dense vector-scalar multiplication and a dense vector. It restructures the expression
+// \f$ A=(\vec{b}*s1)*\vec{c}^T \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*s1 \f$.
+*/
+template< typename VT1 // Type of the dense vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , typename VT2 > // Type of the right-hand side dense vector
+inline const MultExprTrait_< DVecScalarMultExpr<VT1,ST,false>, VT2 >
+ operator*( const DVecScalarMultExpr<VT1,ST,false>& lhs, const DenseVector<VT2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a dense vector and a dense vector-
+// scalar multiplication expression (\f$ A=\vec{b}*(\vec{c}^T*s1) \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense vector.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product of a
+// dense vector and a dense vector-scalar multiplication. It restructures the expression
+// \f$ A=\vec{b}*(\vec{c}^T*s1) \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*s1 \f$.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the dense vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< VT1, DVecScalarMultExpr<VT2,ST,true> >
+ operator*( const DenseVector<VT1,false>& lhs, const DVecScalarMultExpr<VT2,ST,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of two a dense vector-scalar
+// multiplication expressions (\f$ A=(\vec{b}*s1)*(\vec{c}^T*s2) \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense vector-scalar multiplication.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product
+// of two dense vector-scalar multiplications. It restructures the expression
+// \f$ A=(\vec{b}*s1)*(\vec{c}^T*s2) \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*(s1*s2) \f$.
+*/
+template< typename VT1 // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , typename VT2 // Type of the dense vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< DVecScalarMultExpr<VT1,ST1,false>, DVecScalarMultExpr<VT2,ST2,true> >
+ operator*( const DVecScalarMultExpr<VT1,ST1,false>& lhs, const DVecScalarMultExpr<VT2,ST2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector-scalar multiplication
+// expression and a sparse vector (\f$ \vec{a}=(\vec{b}*s1)*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side dense vector-scalar multiplication.
+// \param rhs The right-hand side sparse vector.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense vector-scalar multiplication and a sparse vector. It restructures the expression
+// \f$ \vec{a}=(\vec{b}*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*s1 \f$.
+*/
+template< typename VT1 // Type of the dense vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the vectors
+ , typename VT2 > // Type of the right-hand side sparse vector
+inline const MultExprTrait_< DVecScalarMultExpr<VT1,ST,TF>, VT2 >
+ operator*( const DVecScalarMultExpr<VT1,ST,TF>& lhs, const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector and a dense vector-
+// scalar multiplication expression (\f$ \vec{a}=\vec{b}*(\vec{c}*s1) \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse vector and a dense vector-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=\vec{b}*(\vec{c}*s1) \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*s1 \f$.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , bool TF // Transpose flag of the vectors
+ , typename VT2 // Type of the dense vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< VT1, DVecScalarMultExpr<VT2,ST,TF> >
+ operator*( const SparseVector<VT1,TF>& lhs, const DVecScalarMultExpr<VT2,ST,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector-scalar multiplication
+// expression and a sparse vector-scalar multiplication (\f$ \vec{a}=(\vec{b}*s1)*(\vec{c}*s2) \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side dense vector-scalar multiplication.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a dense vector-scalar multiplication and a sparse vector-scalar multiplication.
+// It restructures the expression \f$ \vec{a}=(\vec{b}*s1)*(\vec{c}*s2) \f$ to the
+// expression \f$ \vec{a}=(\vec{b}*\vec{c})*(s1*s2) \f$.
+*/
+template< typename VT1 // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the vectors
+ , typename VT2 // Type of the sparse vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar o the right-hand side expression
+inline const MultExprTrait_< DVecScalarMultExpr<VT1,ST1,TF>, SVecScalarMultExpr<VT2,ST2,TF> >
+ operator*( const DVecScalarMultExpr<VT1,ST1,TF>& lhs, const SVecScalarMultExpr<VT2,ST2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector-scalar multiplication
+// expression and a dense vector-scalar multiplication (\f$ \vec{a}=(\vec{b}*s1)*(\vec{c}*s2) \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector-scalar multiplication.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a sparse vector-scalar multiplication and a dense vector-scalar multiplication.
+// It restructures the expression \f$ \vec{a}=(\vec{b}*s1)*(\vec{c}*s2) \f$ to the
+// expression \f$ \vec{a}=(\vec{b}*\vec{c})*(s1*s2) \f$.
+*/
+template< typename VT1 // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the vectors
+ , typename VT2 // Type of the dense vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar o the right-hand side expression
+inline const MultExprTrait_< SVecScalarMultExpr<VT1,ST1,TF>, DVecScalarMultExpr<VT2,ST2,TF> >
+ operator*( const SVecScalarMultExpr<VT1,ST1,TF>& lhs, const DVecScalarMultExpr<VT2,ST2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a dense vector-scalar multiplication
+// expression and a sparse vector (\f$ A=(\vec{b}*s1)*\vec{c}^T \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side dense vector-scalar multiplication.
+// \param rhs The right-hand side sparse vector.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product of a
+// dense vector-scalar multiplication and a sparse vector. It restructures the expression
+// \f$ A=(\vec{b}*s1)*\vec{c}^T \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*s1 \f$.
+*/
+template< typename VT1 // Type of the dense vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , typename VT2 > // Type of the right-hand side sparse vector
+inline const MultExprTrait_< DVecScalarMultExpr<VT1,ST,false>, VT2 >
+ operator*( const DVecScalarMultExpr<VT1,ST,false>& lhs, const SparseVector<VT2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a sparse vector and a dense vector-
+// scalar multiplication expression (\f$ A=\vec{b}*(\vec{c}^T*s1) \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse vector.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product of a
+// sparse vector and a dense vector-scalar multiplication. It restructures the expression
+// \f$ A=\vec{b}*(\vec{c}^T*s1) \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*s1 \f$.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the dense vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< VT1, DVecScalarMultExpr<VT2,ST,true> >
+ operator*( const SparseVector<VT1,false>& lhs, const DVecScalarMultExpr<VT2,ST,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a dense vector-scalar multiplication
+// expression and a sparse vector-scalar multiplication (\f$ A=(\vec{b}*s1)*(\vec{c}^T*s2) \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side dense vector-scalar multiplication.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product
+// of a dense vector-scalar multiplication and a sparse vector-scalar multiplication.
+// It restructures the expression \f$ A=(\vec{b}*s1)*(\vec{c}^T*s2) \f$ to the
+// expression \f$ A=(\vec{b}*\vec{c}^T)*(s1*s2) \f$.
+*/
+template< typename VT1 // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , typename VT2 // Type of the sparse vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar o the right-hand side expression
+inline const MultExprTrait_< DVecScalarMultExpr<VT1,ST1,false>, SVecScalarMultExpr<VT2,ST2,true> >
+ operator*( const DVecScalarMultExpr<VT1,ST1,false>& lhs, const SVecScalarMultExpr<VT2,ST2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a sparse vector-scalar multiplication
+// expression and a dense vector-scalar multiplication (\f$ A=(\vec{b}*s1)*(\vec{c}^T*s2) \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse vector-scalar multiplication.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a sparse vector-scalar multiplication and a dense vector-scalar multiplication.
+// It restructures the expression \f$ A=(\vec{b}*s1)*(\vec{c}^T*s2) \f$ to the
+// expression \f$ A=(\vec{b}*\vec{c}^T)*(s1*s2) \f$.
+*/
+template< typename VT1 // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , typename VT2 // Type of the dense vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar o the right-hand side expression
+inline const MultExprTrait_< SVecScalarMultExpr<VT1,ST1,false>, DVecScalarMultExpr<VT2,ST2,true> >
+ operator*( const SVecScalarMultExpr<VT1,ST1,false>& lhs, const DVecScalarMultExpr<VT2,ST2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix and a dense
+// vector-scalar multiplication expression (\f$ \vec{a}=B*(\vec{c}*s1) \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense matrix.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense matrix and a dense vector-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=B*(\vec{c}*s1) \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename VT // Type of the dense vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< MT, DVecScalarMultExpr<VT,ST,false> >
+ operator*( const DenseMatrix<MT,SO>& mat, const DVecScalarMultExpr<VT,ST,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~mat) * vec.leftOperand() ) * vec.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector-scalar
+// multiplication expression and a dense matrix (\f$ \vec{a}^T=(\vec{b}^T*s1)*C \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side transpose dense vector-scalar multiplication.
+// \param rhs The right-hand side dense matrix.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// transpose dense vector-scalar multiplication and a dense matrix. It restructures the
+// expression \f$ \vec{a}^T=(\vec{b}^T*s1)*C \f$ to the expression \f$ \vec{a}^T=(\vec{b}^T*C)*s1 \f$.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const MultExprTrait_< DVecScalarMultExpr<VT,ST,true>, MT >
+ operator*( const DVecScalarMultExpr<VT,ST,true>& vec, const DenseMatrix<MT,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( vec.leftOperand() * (~mat) ) * vec.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix and a dense
+// vector-scalar multiplication expression (\f$ \vec{a}=B*(\vec{c}*s1) \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse matrix.
+// \param rhs The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse matrix and a dense vector-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=B*(\vec{c}*s1) \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , bool SO // Storage order of the left-hand side sparse matrix
+ , typename VT // Type of the dense vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< MT, DVecScalarMultExpr<VT,ST,false> >
+ operator*( const SparseMatrix<MT,SO>& mat, const DVecScalarMultExpr<VT,ST,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~mat) * vec.leftOperand() ) * vec.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector-scalar
+// multiplication expression and a sparse matrix (\f$ \vec{a}^T=(\vec{b}^T*s1)*C \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side transpose dense vector-scalar multiplication.
+// \param rhs The right-hand side sparse matrix.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// transpose dense vector-scalar multiplication and a sparse matrix. It restructures the
+// expression \f$ \vec{a}^T=(\vec{b}^T*s1)*C \f$ to the expression \f$ \vec{a}^T=(\vec{b}^T*C)*s1 \f$.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , typename MT // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline const MultExprTrait_< DVecScalarMultExpr<VT,ST,true>, MT >
+ operator*( const DVecScalarMultExpr<VT,ST,true>& vec, const SparseMatrix<MT,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( vec.leftOperand() * (~mat) ) * vec.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF >
+struct Size< DVecScalarMultExpr<VT,ST,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF >
+struct IsAligned< DVecScalarMultExpr<VT,ST,TF> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF >
+struct IsPadded< DVecScalarMultExpr<VT,ST,TF> >
+ : public BoolConstant< IsPadded<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct DVecScalarMultExprTrait< DVecScalarMultExpr<VT,ST1,false>, ST2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DVecScalarMultExprTrait_< VT, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct TDVecScalarMultExprTrait< DVecScalarMultExpr<VT,ST1,true>, ST2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDVecScalarMultExprTrait_< VT, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSCALARDIVEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct DVecScalarDivExprTrait< DVecScalarMultExpr<VT,ST1,false>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ typedef DivTrait_<ST1,ST2> ScalarType;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , DVecScalarMultExprTrait_<VT,ScalarType>
+ , DVecScalarDivExprTrait_<VT,ScalarType> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECSCALARDIVEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct TDVecScalarDivExprTrait< DVecScalarMultExpr<VT,ST1,true>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ typedef DivTrait_<ST1,ST2> ScalarType;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , TDVecScalarMultExprTrait_<VT,ScalarType>
+ , TDVecScalarDivExprTrait_<VT,ScalarType> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct DVecDVecMultExprTrait< DVecScalarMultExpr<VT1,ST,false>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< DVecDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct DVecDVecMultExprTrait< VT1, DVecScalarMultExpr<VT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< DVecDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct DVecDVecMultExprTrait< DVecScalarMultExpr<VT1,ST1,false>, DVecScalarMultExpr<VT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DVecScalarMultExprTrait_< DVecDVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECTDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct DVecTDVecMultExprTrait< DVecScalarMultExpr<VT1,ST,false>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DVecTDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct DVecTDVecMultExprTrait< VT1, DVecScalarMultExpr<VT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DVecTDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct DVecTDVecMultExprTrait< DVecScalarMultExpr<VT1,ST1,false>, DVecScalarMultExpr<VT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DMatScalarMultExprTrait_< DVecTDVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECTDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct TDVecTDVecMultExprTrait< DVecScalarMultExpr<VT1,ST,true>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecTDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct TDVecTDVecMultExprTrait< VT1, DVecScalarMultExpr<VT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecTDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct TDVecTDVecMultExprTrait< DVecScalarMultExpr<VT1,ST1,true>, DVecScalarMultExpr<VT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDVecScalarMultExprTrait_< TDVecTDVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct DVecSVecMultExprTrait< DVecScalarMultExpr<VT1,ST,false>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< DVecSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct DVecSVecMultExprTrait< DVecScalarMultExpr<VT1,ST1,false>, SVecScalarMultExpr<VT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SVecScalarMultExprTrait_< DVecSVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECTSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct DVecTSVecMultExprTrait< DVecScalarMultExpr<VT1,ST,false>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , SMatScalarMultExprTrait_< DVecTSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct DVecTSVecMultExprTrait< DVecScalarMultExpr<VT1,ST1,false>, SVecScalarMultExpr<VT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SMatScalarMultExprTrait_< DVecTSVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECTSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct TDVecTSVecMultExprTrait< DVecScalarMultExpr<VT1,ST,true>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TDVecTSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct TDVecTSVecMultExprTrait< DVecScalarMultExpr<VT1,ST1,true>, SVecScalarMultExpr<VT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSVecScalarMultExprTrait_< TDVecTSVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct SVecDVecMultExprTrait< VT1, DVecScalarMultExpr<VT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< SVecDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct SVecDVecMultExprTrait< SVecScalarMultExpr<VT1,ST1,false>, DVecScalarMultExpr<VT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SVecScalarMultExprTrait_< SVecDVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECTDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct SVecTDVecMultExprTrait< VT1, DVecScalarMultExpr<VT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TSMatScalarMultExprTrait_< SVecTDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct SVecTDVecMultExprTrait< SVecScalarMultExpr<VT1,ST1,false>, DVecScalarMultExpr<VT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSMatScalarMultExprTrait_< SVecTDVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECTDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct TSVecTDVecMultExprTrait< VT1, DVecScalarMultExpr<VT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TSVecTDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct TSVecTDVecMultExprTrait< SVecScalarMultExpr<VT1,ST1,true>, DVecScalarMultExpr<VT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSVecScalarMultExprTrait_< TSVecTDVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, typename ST >
+struct DMatDVecMultExprTrait< MT, DVecScalarMultExpr<VT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< DMatDVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, typename ST >
+struct TDMatDVecMultExprTrait< MT, DVecScalarMultExpr<VT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< TDMatDVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TDVecDMatMultExprTrait< DVecScalarMultExpr<VT,ST,true>, MT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TDVecTDMatMultExprTrait< DVecScalarMultExpr<VT,ST,true>, MT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecTDMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, typename ST >
+struct SMatDVecMultExprTrait< MT, DVecScalarMultExpr<VT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< SMatDVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, typename ST >
+struct TSMatDVecMultExprTrait< MT, DVecScalarMultExpr<VT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< TSMatDVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TDVecSMatMultExprTrait< DVecScalarMultExpr<VT,ST,true>, MT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TDVecTSMatMultExprTrait< DVecScalarMultExpr<VT,ST,true>, MT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTOREXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF, bool AF >
+struct SubvectorExprTrait< DVecScalarMultExpr<VT,ST,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecSerialExpr.h b/src/cpu/blaze/math/expressions/DVecSerialExpr.h
new file mode 100644
index 00000000..2e6cd2ba
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecSerialExpr.h
@@ -0,0 +1,889 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecSerialExpr.h
+// \brief Header file for the dense vector serial evaluation expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECSERIALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecSerialExpr.h>
+#include <blaze/math/traits/DVecSerialExprTrait.h>
+#include <blaze/math/traits/SerialExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/TDVecSerialExprTrait.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECSERIALEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the forced serial evaluation of dense vectors.
+// \ingroup dense_vector_expression
+//
+// The DVecSerialExpr class represents the compile time expression for the forced serial
+// evaluation of a dense vector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+class DVecSerialExpr : public DenseVector< DVecSerialExpr<VT,TF>, TF >
+ , private VecSerialExpr
+ , private Computation
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecSerialExpr<VT,TF> This; //!< Type of this DVecSerialExpr instance.
+ typedef ResultType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecSerialExpr class.
+ //
+ // \param dv The dense vector operand of the serial evaluation expression.
+ */
+ explicit inline DVecSerialExpr( const VT& dv ) noexcept
+ : dv_( dv ) // Dense vector of the serial evaluation expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < dv_.size(), "Invalid vector access index" );
+ return dv_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= dv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return dv_.size();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense vector operand.
+ //
+ // \return The dense vector operand.
+ */
+ inline Operand operand() const noexcept {
+ return dv_;
+ }
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\brief Conversion to the type of the dense vector operand.
+ //
+ // \return The dense vector operand.
+ */
+ inline operator Operand() const noexcept {
+ return dv_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return dv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return dv_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return dv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dv_; //!< Dense vector of the serial evaluation expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector serial evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector serial
+ // evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector serial evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector serial
+ // evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector serial evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector
+ // serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector serial evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaulation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector
+ // serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void addAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector serial evaluation expression to a dense
+ vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector serial evaluation expression to a sparse
+ vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void subAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector serial evaluation expression to a dense
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector serial evaluation expression to a sparse
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void multAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector serial evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector
+ // serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ divAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector serial evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector
+ // serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void divAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ divAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector serial evaluation expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector serial evaluation expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector serial evaluation expression to a dense
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpAddAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector serial evaluation expression to a sparse
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpAddAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector serial evaluation expression to a dense
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpSubAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector serial evaluation expression to a sparse
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpSubAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector serial evaluation expression to a
+ // dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpMultAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector serial evaluation expression to a
+ // sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpMultAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector serial evaluation expression to a dense
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense vector
+ // serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpDivAssign( DenseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ divAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector serial evaluation expression to a sparse
+ // vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense vector
+ // serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpDivAssign( SparseVector<VT2,TF>& lhs, const DVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ divAssign( ~lhs, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Forces the serial evaluation of the given dense vector expression \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input vector.
+// \return The evaluated dense vector.
+//
+// The \a serial function forces the serial evaluation of the given dense vector expression
+// \a dv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a serial function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = serial( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecSerialExpr<VT,TF> serial( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecSerialExpr<VT,TF>( ~dv );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Evaluation of the given dense vector serial evaluation expression \a dv.
+// \ingroup dense_vector
+//
+// \param dv The input serial evaluation expression.
+// \return The evaluated dense vector.
+//
+// This function implements a performance optimized treatment of the serial evaluation of a dense
+// vector serial evaluation expression.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecSerialExpr<VT,TF> serial( const DVecSerialExpr<VT,TF>& dv )
+{
+ return dv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct Size< DVecSerialExpr<VT,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct IsAligned< DVecSerialExpr<VT,TF> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecSerialExprTrait< DVecSerialExpr<VT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecSerialExpr<VT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecSerialExprTrait< DVecSerialExpr<VT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecSerialExpr<VT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF, bool AF >
+struct SubvectorExprTrait< DVecSerialExpr<VT,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SerialExprTrait_< SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecTDVecMultExpr.h b/src/cpu/blaze/math/expressions/DVecTDVecMultExpr.h
new file mode 100644
index 00000000..2447a70c
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecTDVecMultExpr.h
@@ -0,0 +1,1792 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecTDVecMultExpr.h
+// \brief Header file for the dense vector/dense vector outer product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECTDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECTDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/VecTVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecTVecMultExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECTDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for outer products between two dense vectors.
+// \ingroup dense_matrix_expression
+//
+// The DVecTDVecMultExpr class represents the compile time expression for outer products
+// between dense vectors.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 > // Type of the right-hand side dense vector
+class DVecTDVecMultExpr : public DenseMatrix< DVecTDVecMultExpr<VT1,VT2>, false >
+ , private VecTVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense vector expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense vector expression.
+ enum : bool { evaluateLeft = IsComputation<VT1>::value || RequiresEvaluation<VT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense vector expression.
+ enum : bool { evaluateRight = IsComputation<VT2>::value || RequiresEvaluation<VT2>::value };
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the outer product expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the outer product expression. In case either of the
+ two dense vector operands requires an evaluation, \a useAssign will be set to \a true
+ and the outer product expression will be evaluated via the \a assign function family.
+ Otherwise \a useAssign will be set to \a false and the expression will be evaluated
+ via the function call operator. */
+ enum : bool { useAssign = ( evaluateLeft || evaluateRight ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the right-hand side vector operand requires an intermediate evaluation,
+ the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = evaluateRight };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ outer product, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no vectorized computation is possible, the nested \value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseVectorizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecTDVecMultExpr<VT1,VT2> This; //!< Type of this DVecTDVecMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecTDVecMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense vector operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense matrix.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the left-hand side dense matrix expression.
+ typedef ConstIterator_<VT1> LeftIteratorType;
+
+ //! ConstIterator type of the right-hand side dense matrix expression.
+ typedef ConstIterator_<VT2> RightIteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param left Iterator to the initial left-hand side element.
+ // \param right Iterator to the initial right-hand side element.
+ */
+ explicit inline ConstIterator( LeftIteratorType left, RightIteratorType right )
+ : left_ ( left ) // Iterator to the current left-hand side element
+ , right_( right ) // Iterator to the current right-hand side element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ right_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ right_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( left_, right_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --right_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( left_, right_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return (*left_) * (*right_);
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return set( *left_ ) * right_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return right_ == rhs.right_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return right_ != rhs.right_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return right_ < rhs.right_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return right_ > rhs.right_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return right_ <= rhs.right_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return right_ >= rhs.right_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return right_ - rhs.right_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.left_, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.left_, it.right_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.left_, it.right_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftIteratorType left_; //!< Iterator to the current left-hand side element.
+ RightIteratorType right_; //!< Iterator to the current right-hand side element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT1::simdEnabled && VT2::simdEnabled &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT1::smpAssignable && !evaluateRight };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecTDVecMultExpr class.
+ //
+ // \param lhs The left-hand side dense vector operand of the multiplication expression.
+ // \param rhs The right-hand side dense vector operand of the multiplication expression.
+ */
+ explicit inline DVecTDVecMultExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense vector of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.size(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.size(), "Invalid column access index" );
+
+ return lhs_[i] * rhs_[j];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the matrix.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t i, size_t j ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.size() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.size() , "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+ return set( lhs_[i] ) * rhs_.load( j );
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.size(), "Invalid row access index" );
+ return ConstIterator( lhs_.begin()+i, rhs_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.size(), "Invalid row access index" );
+ return ConstIterator( lhs_.begin()+i, rhs_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_DVECTDVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to row-major dense matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector outer product to a row-major dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector outer product expression to a row-major dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,false>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTDVecMultExpr::selectAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense vector-dense vector outer product to a row-major dense
+ // matrix (\f$ A=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the dense vector-dense vector
+ // outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const size_t jpos( N & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( N - ( N % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ (~A)(i,j ) = x[i] * y[j ];
+ (~A)(i,j+1UL) = x[i] * y[j+1];
+ }
+ if( jpos < N ) {
+ (~A)(i,jpos) = x[i] * y[jpos];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized assignment to row-major dense matrices*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized assignment of a dense vector-dense vector outer product to a row-major
+ // dense matrix (\f$ A=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized assignment kernel for the dense vector-dense vector
+ // outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT4>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const SIMDType x1( set( x[i] ) );
+
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ (~A).store( i, j, x1 * y.load(j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ (~A)(i,j) = x[i] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector outer product to a column-major dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,true>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTDVecMultExpr::selectAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense vector-dense vector outer product to a column-major
+ // dense matrix (\f$ A=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the dense vector-dense vector
+ // outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const size_t ipos( M & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( M - ( M % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ (~A)(i ,j) = x[i ] * y[j];
+ (~A)(i+1UL,j) = x[i+1] * y[j];
+ }
+ if( ipos < M ) {
+ (~A)(ipos,j) = x[ipos] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized assignment to column-major dense matrices****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized assignment of a dense vector-dense vector outer product to a column-major
+ // dense matrix (\f$ A=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized assignment kernel for the dense vector-dense vector
+ // outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT3>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const SIMDType y1( set( y[j] ) );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ (~A).store( i, j, x.load(i) * y1 );
+ }
+ for( ; remainder && i<M; ++i ) {
+ (~A)(i,j) = x[i] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-dense vector outer product to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-dense
+ // vector outer product expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to row-major dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-dense vector outer product to a row-major
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // dense vector outer product expression to a row-major dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,false>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTDVecMultExpr::selectAddAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a dense vector-dense vector outer product to a
+ // row-major dense matrix (\f$ A+=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the dense vector-dense
+ // vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectAddAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const size_t jpos( N & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( N - ( N % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ (~A)(i,j ) += x[i] * y[j ];
+ (~A)(i,j+1UL) += x[i] * y[j+1UL];
+ }
+ if( jpos < N ) {
+ (~A)(i,jpos) += x[i] * y[jpos];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized addition assignment to row-major dense matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized addition assignment of a dense vector-dense vector outer product to a
+ // row-major dense matrix (\f$ A+=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized addition assignment kernel for the dense vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectAddAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT4>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const SIMDType x1( set( x[i] ) );
+
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ (~A).store( i, j, (~A).load(i,j) + x1 * y.load(j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ (~A)(i,j) += x[i] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to column-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-dense vector outer product to a column-major
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // dense vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,true>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTDVecMultExpr::selectAddAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to column dense matrices****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a dense vector-dense vector outer product to a
+ // column-major dense matrix (\f$ A+=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the dense vector-dense
+ // vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectAddAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const size_t ipos( M & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( M - ( M % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ (~A)(i ,j) += x[i ] * y[j];
+ (~A)(i+1UL,j) += x[i+1UL] * y[j];
+ }
+ if( ipos < M ) {
+ (~A)(ipos,j) += x[ipos] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized addition assignment to column-major dense matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized addition assignment of a dense vector-dense vector outer product to a
+ // column-major dense matrix (\f$ A+=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized addition assignment kernel for the dense vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectAddAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT3>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const SIMDType y1( set( y[j] ) );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ (~A).store( i, j, (~A).load(i,j) + x.load(i) * y1 );
+ }
+ for( ; remainder && i<M; ++i ) {
+ (~A)(i,j) += x[i] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to row-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-dense vector outer product to a row-major
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // dense vector outer product expression to a row-major dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands requires an intermediate evaluation.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,false>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTDVecMultExpr::selectSubAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a dense vector-dense vector outer product to a
+ // row-major dense matrix (\f$ A-=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the dense vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectSubAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const size_t jpos( N & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( N - ( N % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ (~A)(i,j ) -= x[i] * y[j ];
+ (~A)(i,j+1UL) -= x[i] * y[j+1UL];
+ }
+ if( jpos < N ) {
+ (~A)(i,jpos) -= x[i] * y[jpos];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized subtraction assignment to row-major dense matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized subtraction assignment of a dense vector-dense vector outer product to a
+ // row-major dense matrix (\f$ A-=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized subtraction assignment kernel for the dense vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectSubAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT4>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const SIMDType x1( set( x[i] ) );
+
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ (~A).store( i, j, (~A).load(i,j) - x1 * y.load(j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ (~A)(i,j) -= x[i] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to column-major dense matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-dense vector outer product to a column-major
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // dense vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,true>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTDVecMultExpr::selectSubAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column dense matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a dense vector-dense vector outer product to a
+ // column-major dense matrix (\f$ A-=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the dense vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectSubAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const size_t ipos( M & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( M - ( M % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ (~A)(i ,j) -= x[i ] * y[j];
+ (~A)(i+1UL,j) -= x[i+1UL] * y[j];
+ }
+ if( ipos < M ) {
+ (~A)(ipos,j) -= x[ipos] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized subtraction assignment to column-major dense matrices****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized subtraction assignment of a dense vector-dense vector outer product to a
+ // column-major dense matrix (\f$ A-=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_matrix
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized subtraction assignment kernel for the dense vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectSubAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ const size_t M( (~A).rows() );
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT3>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const SIMDType y1( set( y[j] ) );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ (~A).store( i, j, (~A).load(i,j) - x.load(i) * y1 );
+ }
+ for( ; remainder && i<M; ++i ) {
+ (~A)(i,j) -= x[i] * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector outer product to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector outer product expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( rhs.lhs_ ); // Evaluation of the left-hand side dense vector operand
+ RT y( rhs.rhs_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ smpAssign( ~lhs, x * y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector-dense vector outer product to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector-dense
+ // vector outer product expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector-dense vector outer product to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector-dense vector outer product expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,false>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( rhs.lhs_ ); // Evaluation of the left-hand side dense vector operand
+ RT y( rhs.rhs_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ smpAddAssign( ~lhs, x * y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector-dense vector outer product to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector-dense vector outer product expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,false>& lhs, const DVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( rhs.lhs_ ); // Evaluation of the left-hand side dense vector operand
+ RT y( rhs.rhs_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ smpSubAssign( ~lhs, x * y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECTVECMULTEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the outer product of two dense vectors
+// (\f$ A=\vec{b}*\vec{c}^T \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense vector for the outer product.
+// \param rhs The right-hand side transpose dense vector for the outer product.
+// \return The resulting dense matrix.
+//
+// This operator represents the outer product between a dense vector and a transpose dense
+// vector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowMajor;
+
+ blaze::DynamicVector<double,columnVector> a, b;
+ blaze::DynamicMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ A = a * trans(b);
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both
+// dense vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType
+// and \a T2::ElementType have to be supported by the MultTrait class template.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side dense vector
+inline const DVecTDVecMultExpr<T1,T2>
+ operator*( const DenseVector<T1,false>& lhs, const DenseVector<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecTDVecMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct Rows< DVecTDVecMultExpr<VT1,VT2> > : public Size<VT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct Columns< DVecTDVecMultExpr<VT1,VT2> > : public Size<VT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct IsAligned< DVecTDVecMultExpr<VT1,VT2> >
+ : public BoolConstant< And< IsAligned<VT1>, IsAligned<VT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct IsPadded< DVecTDVecMultExpr<VT1,VT2> >
+ : public BoolConstant< IsPadded<VT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool AF >
+struct SubmatrixExprTrait< DVecTDVecMultExpr<VT1,VT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct RowExprTrait< DVecTDVecMultExpr<VT1,VT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< ReturnType_<VT1>, VT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct ColumnExprTrait< DVecTDVecMultExpr<VT1,VT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< VT1, ReturnType_<VT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecTSVecMultExpr.h b/src/cpu/blaze/math/expressions/DVecTSVecMultExpr.h
new file mode 100644
index 00000000..dcda22c6
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecTSVecMultExpr.h
@@ -0,0 +1,1326 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecTSVecMultExpr.h
+// \brief Header file for the dense vector/sparse vector outer product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECTSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECTSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/VecTVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/VecTVecMultExpr.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECTSVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector-sparse vector outer products.
+// \ingroup sparse_matrix_expression
+//
+// The DVecTSVecMultExpr class represents the compile time expression for dense vector-sparse
+// vector outer products
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 > // Type of the right-hand side sparse vector
+class DVecTSVecMultExpr : public SparseMatrix< DVecTSVecMultExpr<VT1,VT2>, false >
+ , private VecTVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side dense vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side dense vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Evaluation strategy*************************************************************************
+ //! Compilation switch for the evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the multiplication expression. In case either the dense
+ or the sparse vector operand is a computational expression or if any of two involved
+ element types is not a numeric data type, \a useAssign will be set to \a true and the
+ multiplication expression will be evaluated via the \a assign function family. Otherwise
+ \a useAssign will be set to \a false and the expression will be evaluated via the
+ subscript operator. */
+ enum : bool { useAssign = ( IsComputation<VT1>::value || !IsNumeric<ET1>::value ||
+ IsComputation<VT2>::value || !IsNumeric<ET2>::value ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ outer product, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ T1::simdEnabled && T2::simdEnabled &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T1>, ElementType_<T1> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no vectorized computation is possible, the nested \value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseVectorizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecTSVecMultExpr<VT1,VT2> This; //!< Type of this DVecTSVecMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecTSVecMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense vector operand.
+ typedef If_< IsComputation<VT1>, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef If_< IsComputation<VT2>, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector-sparse vector outer product expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse matrix expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Element type of the dense vector expression
+ typedef ET1 LeftElement;
+
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<RightOperand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( LeftElement v, IteratorType it )
+ : v_ ( v ) // Element of the left-hand side dense vector expression.
+ , it_( it ) // Iterator over the elements of the right-hand side sparse vector expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( v_ * it_->value(), it_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return Reference to the sparse matrix element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return v_ * it_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ LeftElement v_; //!< Element of the left-hand side dense vector expression.
+ IteratorType it_; //!< Iterator over the elements of the right-hand side sparse vector expression
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecTSVecMultExpr class.
+ //
+ // \param lhs The left-hand side dense vector operand of the multiplication expression.
+ // \param rhs The right-hand side sparse vector operand of the multiplication expression.
+ */
+ explicit inline DVecTSVecMultExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense vector of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.size(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.size(), "Invalid column access index" );
+
+ return lhs_[i] * rhs_[j];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( lhs_[i], rhs_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( lhs_[i], rhs_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.size() * rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ UNUSED_PARAMETER( i );
+ return rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific matrix element.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT2 );
+ return ConstIterator( lhs_[i], rhs_.find( j ) );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT2 );
+ return ConstIterator( lhs_[i], rhs_.lowerBound( j ) );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT2 );
+ return ConstIterator( lhs_[i], rhs_.upperBound( j ) );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to row-major dense matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector outer product to a row-major dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector outer product expression to a row-major dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands is an expression or any of the two involved element types is non-numeric
+ // data type.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,false>& lhs, const DVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ (~lhs)(i,element->index()) = x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,true>& lhs, const DVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTSVecMultExpr::selectAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a dense vector-sparse vector outer product to a column-major
+ // dense matrix (\f$ A=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the dense vector-sparse vector
+ // outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ for( size_t i=0UL; i<(~A).rows(); ++i ) {
+ (~A)(i,element->index()) = x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized assignment to column-major dense matrices****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized assignment of a dense vector-sparse vector outer product to a column-major
+ // dense matrix (\f$ A=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the vectorized assignment kernel for the dense vector-sparse vector
+ // outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ const size_t M( (~A).rows() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT3>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element )
+ {
+ const SIMDTrait_<ElementType> y1( set( element->value() ) );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ (~A).store( i, element->index(), x.load(i) * y1 );
+ }
+ for( ; remainder && i<M; ++i ) {
+ (~A)(i,element->index()) = x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector outer product to a row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector outer product expression to a row-major sparse matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands is an expression or any of the two involved element
+ // types is non-numeric data type.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( SparseMatrix<MT,false>& lhs, const DVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).capacity() >= rhs.nonZeros(), "Insufficient capacity" );
+
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ if( begin == end )
+ return;
+
+ for( size_t i=0UL; i<x.size(); ++i ) {
+ if( !isDefault( x[i] ) ) {
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ (~lhs).append( i, element->index(), x[i] * element->value() );
+ }
+ }
+ (~lhs).finalize( i );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector-sparse vector outer product to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector-sparse
+ // vector outer product expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,true>& lhs, const DVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns() , "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ if( begin == end )
+ return;
+
+ (~lhs).reserve( begin->index(), rhs.nonZeros() );
+
+ size_t index( 0UL );
+
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ if( !isDefault( element->value() ) ) {
+ for( ; index < element->index(); ++index ) {
+ (~lhs).finalize( index );
+ }
+ for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
+ (~lhs).append( i, element->index(), x[i] * element->value() );
+ }
+ (~lhs).finalize( index++ );
+ }
+ }
+
+ for( ; index < y.size(); ++index ) {
+ (~lhs).finalize( index );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to row-major dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-sparse vector outer product to a row-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // sparse vector outer product expression to a row-major dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands is an expression or any of the two involved element
+ // types is non-numeric data type.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,false>& lhs, const DVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ (~lhs)(i,element->index()) += x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to column-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector-sparse vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense vector-
+ // sparse vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,true>& lhs, const DVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTSVecMultExpr::selectAddAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to column dense matrices****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a dense vector-sparse vector outer product to a
+ // column-major dense matrix (\f$ A+=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the dense vector-sparse
+ // vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectAddAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ for( size_t i=0UL; i<(~A).rows(); ++i ) {
+ (~A)(i,element->index()) += x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized addition assignment to column-major dense matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized addition assignment of a dense vector-sparse vector outer product to a
+ // column-major dense matrix (\f$ A+=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the vectorized addition assignment kernel for the dense vector-
+ // sparse vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectAddAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ const size_t M( (~A).rows() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT3>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element )
+ {
+ const SIMDTrait_<ElementType> y1( set( element->value() ) );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ (~A).store( i, element->index(), (~A).load(i,element->index()) + x.load(i) * y1 );
+ }
+ for( ; remainder && i<M; ++i ) {
+ (~A)(i,element->index()) += x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to row-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-sparse vector outer product to a row-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // sparse vector outer product expression to a row-major dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands is an expression or any of the two involved element
+ // types is non-numeric data type.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,false>& lhs, const DVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ (~lhs)(i,element->index()) -= x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to column-major dense matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector-sparse vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense vector-
+ // sparse vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,true>& lhs, const DVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ DVecTSVecMultExpr::selectSubAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column dense matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a dense vector-sparse vector outer product to a
+ // column-major dense matrix (\f$ A-=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the dense vector-
+ // sparse vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectSubAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ for( size_t i=0UL; i<(~A).rows(); ++i ) {
+ (~A)(i,element->index()) -= x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized subtraction assignment to column-major dense matrices****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized subtraction assignment of a dense vector-sparse vector outer product to a
+ // column-major dense matrix (\f$ A-=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side dense vector operand.
+ // \param y The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the vectorized subtraction assignment kernel for the dense vector-
+ // sparse vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectSubAssignKernel( DenseMatrix<MT,true>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ const size_t M( (~A).rows() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT3>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const ConstIterator begin( y.begin() );
+ const ConstIterator end ( y.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element )
+ {
+ const SIMDTrait_<ElementType> y1( set( element->value() ) );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ (~A).store( i, element->index(), (~A).load(i,element->index()) - x.load(i) * y1 );
+ }
+ for( ; remainder && i<M; ++i ) {
+ (~A)(i,element->index()) -= x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECTVECMULTEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the dense vector-sparse vector outer product
+// (\f$ A=\vec{b}*\vec{c}^T \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side dense vector for the outer product.
+// \param rhs The right-hand side transpose sparse vector for the outer product.
+// \return The resulting sparse matrix.
+//
+// This operator represents the outer product between a dense vector and a transpose sparse
+// vector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+ using blaze::rowMajor;
+
+ blaze::DynamicVector<double,columnVector> a;
+ blaze::CompressedVector<double,rowVector> b;
+ blaze::CompressedMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ A = a * b;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both
+// vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const DVecTSVecMultExpr<T1,T2>
+ operator*( const DenseVector<T1,false>& lhs, const SparseVector<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecTSVecMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct Rows< DVecTSVecMultExpr<VT1,VT2> > : public Size<VT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct Columns< DVecTSVecMultExpr<VT1,VT2> > : public Size<VT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool AF >
+struct SubmatrixExprTrait< DVecTSVecMultExpr<VT1,VT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct RowExprTrait< DVecTSVecMultExpr<VT1,VT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< ReturnType_<VT1>, VT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct ColumnExprTrait< DVecTSVecMultExpr<VT1,VT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< VT1, ReturnType_<VT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecTransExpr.h b/src/cpu/blaze/math/expressions/DVecTransExpr.h
new file mode 100644
index 00000000..7db40abb
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecTransExpr.h
@@ -0,0 +1,1120 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecTransExpr.h
+// \brief Header file for the dense vector transpose expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECTRANSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/DVecTransposer.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SVecTransposer.h>
+#include <blaze/math/expressions/VecTransExpr.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/DVecTransExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/TDVecTransExprTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EmptyType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECTRANSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense vector transpositions.
+// \ingroup dense_vector_expression
+//
+// The DVecTransExpr class represents the compile time expression for transpositions of
+// dense vectors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+class DVecTransExpr : public DenseVector< DVecTransExpr<VT,TF>, TF >
+ , private VecTransExpr
+ , private If< IsComputation<VT>, Computation, EmptyType >::Type
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef CompositeType_<VT> CT; //!< Composite type of the dense vector expression.
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the transposition expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the transposition expression. In case the given dense
+ vector expression of type \a VT requires an intermediate evaluation, \a useAssign will
+ be set to 1 and the transposition expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to 0 and the expression will be evaluated via
+ the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<VT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target vector is SMP assignable and the dense vector operand requires
+ an intermediate evaluation, \a value is set to 1 and the expression specific evaluation
+ strategy is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename VT2 >
+ struct UseSMPAssign {
+ enum : bool { value = VT2::smpAssignable && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecTransExpr<VT,TF> This; //!< Type of this DVecTransExpr instance.
+ typedef TransposeType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef ResultType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const DVecTransExpr& > CompositeType;
+
+ //! Composite data type of the dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > Operand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the dense vector.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying elements.
+ typedef ElementType* PointerType; //!< Pointer return type.
+ typedef ElementType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+
+ //! ConstIterator type of the dense vector expression.
+ typedef ConstIterator_<VT> IteratorType;
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ */
+ explicit inline ConstIterator( IteratorType iterator )
+ : iterator_( iterator ) // Iterator to the current element
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ConstIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ConstIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator++( int ) {
+ return ConstIterator( iterator_++ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ConstIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ConstIterator operator--( int ) {
+ return ConstIterator( iterator_-- );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReturnType operator*() const {
+ return *iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \return The resulting SIMD element.
+ */
+ inline auto load() const noexcept {
+ return iterator_.load();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const ConstIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const ConstIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const ConstIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const ConstIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
+ return ConstIterator( it.iterator_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ConstIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
+ return ConstIterator( it.iterator_ + inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ConstIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
+ return ConstIterator( it.iterator_ - dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current element.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecTransExpr class.
+ //
+ // \param dv The dense vector operand of the transposition expression.
+ */
+ explicit inline DVecTransExpr( const VT& dv ) noexcept
+ : dv_( dv ) // Dense vector of the transposition expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < dv_.size(), "Invalid vector access index" );
+ return dv_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= dv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Access to the SIMD elements of the vector.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed values.
+ */
+ BLAZE_ALWAYS_INLINE auto load( size_t index ) const noexcept {
+ BLAZE_INTERNAL_ASSERT( index < dv_.size() , "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid vector access index" );
+ return dv_.load( index );
+ }
+ //**********************************************************************************************
+
+ //**Low-level data access***********************************************************************
+ /*!\brief Low-level data access to the vector elements.
+ //
+ // \return Pointer to the internal element storage.
+ */
+ inline const ElementType* data() const noexcept {
+ return dv_.data();
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the dense vector.
+ //
+ // \return Iterator to the first non-zero element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( dv_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
+ //
+ // \return Iterator just past the last non-zero element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( dv_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return dv_.size();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the dense vector operand.
+ //
+ // \return The dense vector operand.
+ */
+ inline Operand operand() const noexcept {
+ return dv_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return dv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return dv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return dv_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return dv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand dv_; //!< Dense vector of the transposition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector
+ // transposition expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ assign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a dense vector transposition expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a dense vector
+ // transposition expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ SVecTransposer<VT2,!TF> tmp( ~lhs );
+ assign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a dense
+ // vector transposition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ addAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a dense
+ // vector transposition expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ subAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a dense
+ // vector transposition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the operand
+ // requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ multAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a dense vector
+ // transposition expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand requires
+ // an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ divAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ divAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // transposition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a dense vector transposition expression to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a dense vector
+ // transposition expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ SVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a dense
+ // vector transposition expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpAddAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a dense
+ // vector transposition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpSubAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a dense
+ // vector transposition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpMultAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a dense vector transposition expression to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a dense
+ // vector transposition expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,TF>& lhs, const DVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpDivAssign( tmp, rhs.dv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, !TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Calculation of the transpose of the given dense vector.
+// \ingroup dense_vector
+//
+// \param dv The dense vector to be transposed.
+// \return The transpose of the dense vector.
+//
+// This function returns an expression representing the transpose of the given dense vector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ blaze::DynamicVector<double,columnVector> a;
+ blaze::DynamicVector<double,rowVector> b;
+ // ... Resizing and initialization
+ b = trans( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const DVecTransExpr<VT,!TF> trans( const DenseVector<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return DVecTransExpr<VT,!TF>( ~dv );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating the transpose of a transpose dense vector.
+// \ingroup dense_vector
+//
+// \param dv The dense vector to be (re-)transposed.
+// \return The transpose of the transpose vector.
+//
+// This function implements a performance optimized treatment of the transpose operation on a
+// dense vector transpose expression. It returns an expression representing the transpose of a
+// transpose dense vector:
+
+ \code
+ using blaze::columnVector;
+
+ blaze::DynamicVector<double,columnVector> a, b;
+ // ... Resizing and initialization
+ b = trans( trans( a ) );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename DVecTransExpr<VT,TF>::Operand trans( const DVecTransExpr<VT,TF>& dv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return dv.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct Size< DVecTransExpr<VT,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct IsAligned< DVecTransExpr<VT,TF> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct IsPadded< DVecTransExpr<VT,TF> >
+ : public BoolConstant< IsPadded<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct DVecTransExprTrait< DVecTransExpr<VT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , Operand_< DVecTransExpr<VT,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TDVecTransExprTrait< DVecTransExpr<VT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , Operand_< DVecTransExpr<VT,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF, bool AF >
+struct SubvectorExprTrait< DVecTransExpr<VT,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = TransExprTrait_< SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DVecTransposer.h b/src/cpu/blaze/math/expressions/DVecTransposer.h
new file mode 100644
index 00000000..fbfa6ac7
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DVecTransposer.h
@@ -0,0 +1,833 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DVecTransposer.h
+// \brief Header file for the dense vector transposer
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DVECTRANSPOSER_H_
+#define _BLAZE_MATH_EXPRESSIONS_DVECTRANSPOSER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/simd/SIMDTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DVECTRANSPOSER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the transposition of a dense vector.
+// \ingroup dense_vector_expression
+//
+// The DVecTransposer class is a wrapper object for the temporary transposition of a dense vector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+class DVecTransposer : public DenseVector< DVecTransposer<VT,TF>, TF >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecTransposer<VT,TF> This; //!< Type of this DVecTransposer instance.
+ typedef TransposeType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef ResultType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Type of the vector elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the vector elements.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<VT> Reference; //!< Reference to a non-constant vector value.
+ typedef ConstReference_<VT> ConstReference; //!< Reference to a constant vector value.
+ typedef Pointer_<VT> Pointer; //!< Pointer to a non-constant vector value.
+ typedef ConstPointer_<VT> ConstPointer; //!< Pointer to a constant vector value.
+ typedef Iterator_<VT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<VT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
+ in can be optimized via SIMD operations. In case the dense vector operand is vectorizable,
+ the \a simdEnabled compilation flag is set to \a true, otherwise it is set to \a false. */
+ enum : bool { simdEnabled = VT::simdEnabled };
+
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecTransposer class.
+ //
+ // \param dv The dense vector operand.
+ */
+ explicit inline DVecTransposer( VT& dv ) noexcept
+ : dv_( dv ) // The dense vector operand
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline Reference operator[]( size_t index ) {
+ BLAZE_USER_ASSERT( index < dv_.size(), "Invalid vector access index" );
+ return dv_[index];
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline ConstReference operator[]( size_t index ) const {
+ BLAZE_USER_ASSERT( index < dv_.size(), "Invalid vector access index" );
+ return dv_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline Reference at( size_t index ) {
+ if( index >= dv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ConstReference at( size_t index ) const {
+ if( index >= dv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Low-level data access***********************************************************************
+ /*!\brief Low-level data access to the vector elements.
+ //
+ // \return Pointer to the internal element storage.
+ */
+ inline Pointer data() noexcept {
+ return dv_.data();
+ }
+ //**********************************************************************************************
+
+ //**Low-level data access***********************************************************************
+ /*!\brief Low-level data access to the vector elements.
+ //
+ // \return Pointer to the internal element storage.
+ */
+ inline ConstPointer data() const noexcept {
+ return dv_.data();
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first element of the dense vector.
+ //
+ // \return Iterator to the first element of the dense vector.
+ */
+ inline Iterator begin() {
+ return dv_.begin();
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first element of the dense vector.
+ //
+ // \return Iterator to the first element of the dense vector.
+ */
+ inline ConstIterator begin() const {
+ return dv_.cbegin();
+ }
+ //**********************************************************************************************
+
+ //**Cbegin function*****************************************************************************
+ /*!\brief Returns an iterator to the first element of the dense vector.
+ //
+ // \return Iterator to the first element of the dense vector.
+ */
+ inline ConstIterator cbegin() const {
+ return dv_.cbegin();
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last element of the dense vector.
+ //
+ // \return Iterator just past the last element of the dense vector.
+ */
+ inline Iterator end() {
+ return dv_.end();
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last element of the dense vector.
+ //
+ // \return Iterator just past the last element of the dense vector.
+ */
+ inline ConstIterator end() const {
+ return dv_.cend();
+ }
+ //**********************************************************************************************
+
+ //**Cend function*******************************************************************************
+ /*!\brief Returns an iterator just past the last element of the dense vector.
+ //
+ // \return Iterator just past the last element of the dense vector.
+ */
+ inline ConstIterator cend() const {
+ return dv_.cend();
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment operator**********************************************************
+ /*!\brief Multiplication assignment operator for the multiplication between a vector and
+ // a scalar value (\f$ \vec{a}*=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the multiplication.
+ // \return Reference to this DVecTransposer.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, DVecTransposer >& operator*=( Other rhs )
+ {
+ (~dv_) *= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Division assignment operator****************************************************************
+ /*!\brief Division assignment operator for the division of a vector by a scalar value
+ // (\f$ \vec{a}/=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the division.
+ // \return Reference to this DVecTransposer.
+ //
+ // \note A division by zero is only checked by an user assert.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, DVecTransposer >& operator/=( Other rhs )
+ {
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ (~dv_) /= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return dv_.size();
+ }
+ //**********************************************************************************************
+
+ //**Reset function******************************************************************************
+ /*!\brief Resets the vector elements.
+ //
+ // \return void
+ */
+ inline void reset() {
+ return dv_.reset();
+ }
+ //**********************************************************************************************
+
+ //**CanAliased function*************************************************************************
+ /*!\brief Returns whether the vector can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this vector, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool canAlias( const Other* alias ) const noexcept
+ {
+ return dv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**IsAliased function**************************************************************************
+ /*!\brief Returns whether the vector is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this vector, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool isAliased( const Other* alias ) const noexcept
+ {
+ return dv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**IsAligned function**************************************************************************
+ /*!\brief Returns whether the vector is properly aligned in memory.
+ //
+ // \return \a true in case the vector is aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept
+ {
+ return dv_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**CanSMPAssign function***********************************************************************
+ /*!\brief Returns whether the vector can be used in SMP assignments.
+ //
+ // \return \a true in case the vector can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept
+ {
+ return dv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ //**Load function*******************************************************************************
+ /*!\brief Load of a SIMD element of the vector.
+ //
+ // \param index Access index. The index must be smaller than the number of vector elements.
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType load( size_t index ) const noexcept
+ {
+ return dv_.load( index );
+ }
+ //**********************************************************************************************
+
+ //**Loada function******************************************************************************
+ /*!\brief Aligned load of a SIMD element of the vector.
+ //
+ // \param index Access index. The index must be smaller than the number of vector elements.
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept
+ {
+ return dv_.loada( index );
+ }
+ //**********************************************************************************************
+
+ //**Loadu function******************************************************************************
+ /*!\brief Unaligned load of a SIMD element of the vector.
+ //
+ // \param index Access index. The index must be smaller than the number of vector elements.
+ // \return The loaded SIMD element.
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept
+ {
+ return dv_.loadu( index );
+ }
+ //**********************************************************************************************
+
+ //**Store function******************************************************************************
+ /*!\brief Store of a SIMD element of the vector.
+ //
+ // \param index Access index. The index must be smaller than the number of vector elements.
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void store( size_t index, const SIMDType& value ) noexcept
+ {
+ dv_.store( index, value );
+ }
+ //**********************************************************************************************
+
+ //**Storea function******************************************************************************
+ /*!\brief Aligned store of a SIMD element of the vector.
+ //
+ // \param index Access index. The index must be smaller than the number of vector elements.
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept
+ {
+ dv_.storea( index, value );
+ }
+ //**********************************************************************************************
+
+ //**Storeu function*****************************************************************************
+ /*!\brief Unaligned store of a SIMD element of the vector.
+ //
+ // \param index Access index. The index must be smaller than the number of vector elements.
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept
+ {
+ dv_.storeu( index, value );
+ }
+ //**********************************************************************************************
+
+ //**Stream function*****************************************************************************
+ /*!\brief Aligned, non-temporal store of a SIMD element of the vector.
+ //
+ // \param index Access index. The index must be smaller than the number of vector elements.
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors.
+ */
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept
+ {
+ dv_.stream( index, value );
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of dense vectors*******************************************************
+ /*!\brief Implementation of the transpose assignment of a dense vector.
+ //
+ // \param rhs The right-hand side dense vector to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side dense vector
+ inline void assign( const DenseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t n( size() );
+
+ const size_t ipos( n & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n - ( n % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ dv_[i ] = (~rhs)[i ];
+ dv_[i+1UL] = (~rhs)[i+1UL];
+ }
+ if( ipos < n )
+ dv_[ipos] = (~rhs)[ipos];
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of sparse vectors******************************************************
+ /*!\brief Implementation of the transpose assignment of a sparse vector.
+ //
+ // \param rhs The right-hand side sparse vector to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side sparse vector
+ inline void assign( const SparseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_<VT2> RhsConstIterator;
+
+ for( RhsConstIterator element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ dv_[element->index()] = element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of dense vectors**********************************************
+ /*!\brief Implementation of the transpose addition assignment of a dense vector.
+ //
+ // \param rhs The right-hand side dense vector to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side dense vector
+ inline void addAssign( const DenseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t n( size() );
+
+ const size_t ipos( n & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n - ( n % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ dv_[i ] += (~rhs)[i ];
+ dv_[i+1UL] += (~rhs)[i+1UL];
+ }
+ if( ipos < n )
+ dv_[ipos] += (~rhs)[ipos];
+ }
+ //**********************************************************************************************
+
+ //**Transpose addition assignment of sparse vectors*********************************************
+ /*!\brief Implementation of the transpose addition assignment of a sparse vector.
+ //
+ // \param rhs The right-hand side sparse vector to be added.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side sparse vector
+ inline void addAssign( const SparseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_<VT2> RhsConstIterator;
+
+ for( RhsConstIterator element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ dv_[element->index()] += element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of dense vectors*******************************************
+ /*!\brief Implementation of the transpose subtraction assignment of a dense vector.
+ //
+ // \param rhs The right-hand side dense vector to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side dense vector
+ inline void subAssign( const DenseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t n( size() );
+
+ const size_t ipos( n & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n - ( n % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ dv_[i ] -= (~rhs)[i ];
+ dv_[i+1UL] -= (~rhs)[i+1UL];
+ }
+ if( ipos < n )
+ dv_[ipos] -= (~rhs)[ipos];
+ }
+ //**********************************************************************************************
+
+ //**Transpose subtraction assignment of sparse vectors******************************************
+ /*!\brief Implementation of the transpose subtraction assignment of a sparse vector.
+ //
+ // \param rhs The right-hand side sparse vector to be subtracted.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side sparse vector
+ inline void subAssign( const SparseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_<VT2> RhsConstIterator;
+
+ for( RhsConstIterator element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ dv_[element->index()] -= element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose multiplication assignment of dense vectors****************************************
+ /*!\brief Implementation of the transpose multiplication assignment of a dense vector.
+ //
+ // \param rhs The right-hand side dense vector to be multiplied.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side dense vector
+ inline void multAssign( const DenseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t n( size() );
+
+ const size_t ipos( n & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n - ( n % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ dv_[i ] *= (~rhs)[i ];
+ dv_[i+1UL] *= (~rhs)[i+1UL];
+ }
+ if( ipos < n )
+ dv_[ipos] *= (~rhs)[ipos];
+ }
+ //**********************************************************************************************
+
+ //**Transpose multiplication assignment of sparse vectors***************************************
+ /*!\brief Implementation of the transpose multiplication assignment of a sparse vector.
+ //
+ // \param rhs The right-hand side sparse vector to be multiplied.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side dense vector
+ inline void multAssign( const SparseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_<VT2> RhsConstIterator;
+
+ const VT tmp( dv_ );
+ dv_.reset();
+
+ for( RhsConstIterator element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ dv_[element->index()] = tmp[element->index()] * element->value();
+ }
+ //**********************************************************************************************
+
+ //**Transpose division assignment of dense vectors**********************************************
+ /*!\brief Implementation of the transpose division assignment of a dense vector.
+ //
+ // \param rhs The right-hand side dense vector divisor.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side dense vector
+ inline void divAssign( const DenseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t n( size() );
+
+ const size_t ipos( n & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n - ( n % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ dv_[i ] /= (~rhs)[i ];
+ dv_[i+1UL] /= (~rhs)[i+1UL];
+ }
+ if( ipos < n )
+ dv_[ipos] /= (~rhs)[ipos];
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ VT& dv_; //!< The dense vector operand.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, !TF );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resetting the dense vector contained in a DVecTransposer.
+// \ingroup dense_vector_expression
+//
+// \param v The dense vector to be resetted.
+// \return void
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline void reset( DVecTransposer<VT,TF>& v )
+{
+ v.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct IsAligned< DVecTransposer<VT,TF> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct IsPadded< DVecTransposer<VT,TF> >
+ : public BoolConstant< IsPadded<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct SubvectorTrait< DVecTransposer<VT,TF> >
+{
+ using Type = SubvectorTrait_< ResultType_< DVecTransposer<VT,TF> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DenseMatrix.h b/src/cpu/blaze/math/expressions/DenseMatrix.h
new file mode 100644
index 00000000..90ad1877
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DenseMatrix.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DenseMatrix.h
+// \brief Header file for the DenseMatrix base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DENSEMATRIX_H_
+#define _BLAZE_MATH_EXPRESSIONS_DENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Matrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup dense_matrix Dense Matrices
+// \ingroup matrix
+*/
+/*!\defgroup dense_matrix_expression Expressions
+// \ingroup dense_matrix
+*/
+/*!\brief Base class for dense matrices.
+// \ingroup dense_matrix
+//
+// The DenseMatrix class is a base class for all dense matrix classes. It provides an
+// abstraction from the actual type of the dense matrix, but enables a conversion back
+// to this type via the Matrix base class.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+struct DenseMatrix : public Matrix<MT,SO>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DenseVector.h b/src/cpu/blaze/math/expressions/DenseVector.h
new file mode 100644
index 00000000..1f8a5550
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DenseVector.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DenseVector.h
+// \brief Header file for the DenseVector base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DENSEVECTOR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Vector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup dense_vector Dense Vectors
+// \ingroup vector
+*/
+/*!\defgroup dense_vector_expression Expressions
+// \ingroup dense_vector
+*/
+/*!\brief Base class for N-dimensional dense vectors.
+// \ingroup dense_vector
+//
+// The DenseVector class is a base class for all arbitrarily sized (N-dimensional) dense
+// vectors. It provides an abstraction from the actual type of the dense vector, but enables
+// a conversion back to this type via the Vector base class.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+struct DenseVector : public Vector<VT,TF>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/DivExpr.h b/src/cpu/blaze/math/expressions/DivExpr.h
new file mode 100644
index 00000000..54cdec56
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/DivExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/DivExpr.h
+// \brief Header file for the DivExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_DIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_DIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all division expression templates.
+// \ingroup math
+//
+// The DivExpr class serves as a tag for all expression templates that implement mathematical
+// divisions. All classes, that represent a mathematical division (vector/scalar divisions and
+// matrix/scalar division) and that are used within the expression template environment of the
+// Blaze library have to derive from this class in order to qualify as division expression
+// template. Only in case a class is derived from the DivExpr base class, the IsDivExpr type
+// trait recognizes the class as valid division expression template.
+*/
+struct DivExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/EvalExpr.h b/src/cpu/blaze/math/expressions/EvalExpr.h
new file mode 100644
index 00000000..daf56edc
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/EvalExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/EvalExpr.h
+// \brief Header file for the EvalExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_EVALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_EVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all evaluation expression templates.
+// \ingroup math
+//
+// The EvalExpr class serves as a tag for all expression templates that implement an evaluation
+// operation. All classes, that represent an evaluation operation and that are used within the
+// expression template environment of the Blaze library have to derive from this class in order
+// to qualify as evaluation expression template. Only in case a class is derived from the EvalExpr
+// base class, the IsEvalExpr type trait recognizes the class as valid evaluation expression
+// template.
+*/
+struct EvalExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/Expression.h b/src/cpu/blaze/math/expressions/Expression.h
new file mode 100644
index 00000000..a058d6a3
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/Expression.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/Expression.h
+// \brief Header file for the Expression base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_EXPRESSION_H_
+#define _BLAZE_MATH_EXPRESSIONS_EXPRESSION_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all expression templates.
+// \ingroup math
+//
+// The Expression class is the base class for all expression templates. All classes, that
+// represent a mathematical operation and that are used within the expression template
+// environment of the Blaze library have to derive from this class in order to qualify
+// as expression template. Only in case a class is derived from the Expression base class,
+// the IsExpression type trait recognizes the class as valid expression template.
+*/
+struct Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/ForEachExpr.h b/src/cpu/blaze/math/expressions/ForEachExpr.h
new file mode 100644
index 00000000..e8e51430
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/ForEachExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/ForEachExpr.h
+// \brief Header file for the ForEachExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_FOREACHEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_FOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all for-each expression templates.
+// \ingroup math
+//
+// The ForEachExpr class serves as a tag for all expression templates that represent a unary,
+// custom operation. All classes, that represent a custom operation and that are used within
+// the expression template environment of the Blaze library have to derive from this class in
+// order to qualify as for-each expression template. Only in case a class is derived from the
+// ForEachExpr base class, the IsForEachExpr type trait recognizes the class as valid for-each
+// expression template.
+*/
+struct ForEachExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/Forward.h b/src/cpu/blaze/math/expressions/Forward.h
new file mode 100644
index 00000000..12fe60ff
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/Forward.h
@@ -0,0 +1,194 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/Forward.h
+// \brief Header file for all forward declarations for expression class templates
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_FORWARD_H_
+#define _BLAZE_MATH_EXPRESSIONS_FORWARD_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+template< typename, bool > struct DenseMatrix;
+template< typename, bool > struct DenseVector;
+template< typename, typename, bool > class DMatDMatAddExpr;
+template< typename, typename > class DMatDMatMultExpr;
+template< typename, typename, bool > class DMatDMatSubExpr;
+template< typename, typename > class DMatDVecMultExpr;
+template< typename, bool > class DMatEvalExpr;
+template< typename, typename, bool > class DMatForEachExpr;
+template< typename, bool > class DMatInvExpr;
+template< typename, typename, bool > class DMatScalarDivExpr;
+template< typename, typename, bool > class DMatScalarMultExpr;
+template< typename, bool > class DMatSerialExpr;
+template< typename, typename, bool > class DMatSMatAddExpr;
+template< typename, typename > class DMatSMatMultExpr;
+template< typename, typename, bool > class DMatSMatSubExpr;
+template< typename, typename > class DMatSVecMultExpr;
+template< typename, typename > class DMatTDMatAddExpr;
+template< typename, typename > class DMatTDMatMultExpr;
+template< typename, typename > class DMatTDMatSubExpr;
+template< typename, bool > class DMatTransExpr;
+template< typename, bool > class DMatTransposer;
+template< typename, typename > class DMatTSMatAddExpr;
+template< typename, typename > class DMatTSMatMultExpr;
+template< typename, typename > class DMatTSMatSubExpr;
+template< typename, typename, bool > class DVecDVecAddExpr;
+template< typename, typename, bool > class DVecDVecCrossExpr;
+template< typename, typename, bool > class DVecDVecDivExpr;
+template< typename, typename, bool > class DVecDVecMultExpr;
+template< typename, typename, bool > class DVecDVecSubExpr;
+template< typename, bool > class DVecEvalExpr;
+template< typename, typename, bool > class DVecForEachExpr;
+template< typename, typename, bool > class DVecScalarDivExpr;
+template< typename, typename, bool > class DVecScalarMultExpr;
+template< typename, bool > class DVecSerialExpr;
+template< typename, typename, bool > class DVecSVecAddExpr;
+template< typename, typename, bool > class DVecSVecCrossExpr;
+template< typename, typename, bool > class DVecSVecMultExpr;
+template< typename, typename, bool > class DVecSVecSubExpr;
+template< typename, typename > class DVecTDVecMultExpr;
+template< typename, bool > class DVecTransExpr;
+template< typename, bool > class DVecTransposer;
+template< typename, typename > class DVecTSVecMultExpr;
+template< typename, bool > struct Matrix;
+template< typename, typename > class SMatDMatMultExpr;
+template< typename, typename, bool > class SMatDMatSubExpr;
+template< typename, typename > class SMatDVecMultExpr;
+template< typename, bool > class SMatEvalExpr;
+template< typename, typename, bool > class SMatForEachExpr;
+template< typename, typename, bool > class SMatScalarDivExpr;
+template< typename, typename, bool > class SMatScalarMultExpr;
+template< typename, bool > class SMatSerialExpr;
+template< typename, typename > class SMatSMatAddExpr;
+template< typename, typename > class SMatSMatMultExpr;
+template< typename, typename > class SMatSMatSubExpr;
+template< typename, typename > class SMatSVecMultExpr;
+template< typename, typename > class SMatTDMatMultExpr;
+template< typename, typename > class SMatTDMatSubExpr;
+template< typename, bool > class SMatTransExpr;
+template< typename, bool > class SMatTransposer;
+template< typename, typename > class SMatTSMatAddExpr;
+template< typename, typename > class SMatTSMatMultExpr;
+template< typename, typename > class SMatTSMatSubExpr;
+template< typename, bool > struct SparseMatrix;
+template< typename, bool > struct SparseVector;
+template< typename, typename, bool > class SVecDVecCrossExpr;
+template< typename, typename, bool > class SVecDVecDivExpr;
+template< typename, typename, bool > class SVecDVecMultExpr;
+template< typename, typename, bool > class SVecDVecSubExpr;
+template< typename, bool > class SVecEvalExpr;
+template< typename, typename, bool > class SVecForEachExpr;
+template< typename, typename, bool > class SVecScalarDivExpr;
+template< typename, typename, bool > class SVecScalarMultExpr;
+template< typename, bool > class SVecSerialExpr;
+template< typename, typename, bool > class SVecSVecAddExpr;
+template< typename, typename, bool > class SVecSVecCrossExpr;
+template< typename, typename, bool > class SVecSVecMultExpr;
+template< typename, typename, bool > class SVecSVecSubExpr;
+template< typename, typename > class SVecTDVecMultExpr;
+template< typename, bool > class SVecTransExpr;
+template< typename, bool > class SVecTransposer;
+template< typename, typename > class SVecTSVecMultExpr;
+template< typename, typename > class TDMatDMatMultExpr;
+template< typename, typename > class TDMatDVecMultExpr;
+template< typename, typename > class TDMatSMatAddExpr;
+template< typename, typename > class TDMatSMatMultExpr;
+template< typename, typename > class TDMatSMatSubExpr;
+template< typename, typename > class TDMatSVecMultExpr;
+template< typename, typename > class TDMatTDMatMultExpr;
+template< typename, typename > class TDMatTSMatMultExpr;
+template< typename, typename > class TDVecDMatMultExpr;
+template< typename, typename > class TDVecSMatMultExpr;
+template< typename, typename > class TDVecTDMatMultExpr;
+template< typename, typename > class TDVecTSMatMultExpr;
+template< typename, typename > class TSMatDMatMultExpr;
+template< typename, typename > class TSMatDMatSubExpr;
+template< typename, typename > class TSMatDVecMultExpr;
+template< typename, typename > class TSMatSMatMultExpr;
+template< typename, typename > class TSMatSMatSubExpr;
+template< typename, typename > class TSMatSVecMultExpr;
+template< typename, typename > class TSMatTDMatMultExpr;
+template< typename, typename > class TSMatTSMatAddExpr;
+template< typename, typename > class TSMatTSMatMultExpr;
+template< typename, typename > class TSMatTSMatSubExpr;
+template< typename, typename > class TSVecDMatMultExpr;
+template< typename, typename > class TSVecSMatMultExpr;
+template< typename, typename > class TSVecTDMatMultExpr;
+template< typename, typename > class TSVecTSMatMultExpr;
+template< typename, bool > struct Vector;
+
+template< typename VT, bool TF >
+inline const DVecTransExpr<VT,!TF> trans( const DenseVector<VT,TF>& );
+
+template< typename VT, bool TF >
+inline const SVecTransExpr<VT,!TF> trans( const SparseVector<VT,TF>& );
+
+template< typename MT, bool SO >
+inline const DMatTransExpr<MT,!SO> trans( const DenseMatrix<MT,SO>& );
+
+template< typename MT, bool SO >
+inline const SMatTransExpr<MT,!SO> trans( const SparseMatrix<MT,SO>& );
+
+template< typename VT, bool TF >
+inline const DVecSerialExpr<VT,TF> serial( const DenseVector<VT,TF>& );
+
+template< typename VT, bool TF >
+inline const SVecSerialExpr<VT,TF> serial( const SparseVector<VT,TF>& );
+
+template< typename MT, bool SO >
+inline const DMatSerialExpr<MT,SO> serial( const DenseMatrix<MT,SO>& );
+
+template< typename MT, bool SO >
+inline const SMatSerialExpr<MT,SO> serial( const SparseMatrix<MT,SO>& );
+
+template< typename VT, bool TF, typename OP >
+inline const DVecForEachExpr<VT,OP,TF> forEach( const DenseVector<VT,TF>&, OP );
+
+template< typename VT, bool TF, typename OP >
+inline const SVecForEachExpr<VT,OP,TF> forEach( const SparseVector<VT,TF>&, OP );
+
+template< typename MT, bool SO, typename OP >
+inline const DMatForEachExpr<MT,OP,SO> forEach( const DenseMatrix<MT,SO>&, OP );
+
+template< typename MT, bool SO, typename OP >
+inline const SMatForEachExpr<MT,OP,SO> forEach( const SparseMatrix<MT,SO>&, OP );
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatEvalExpr.h b/src/cpu/blaze/math/expressions/MatEvalExpr.h
new file mode 100644
index 00000000..745d7780
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatEvalExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatEvalExpr.h
+// \brief Header file for the MatEvalExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATEVALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/EvalExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix evaluation expression templates.
+// \ingroup math
+//
+// The MatEvalExpr class serves as a tag for all expression templates that implement a matrix
+// evaluation operation. All classes, that represent a matrix evaluation operation and that
+// are used within the expression template environment of the Blaze library have to derive
+// from this class in order to qualify as matrix evaluation expression template. Only in case
+// a class is derived from the MatEvalExpr base class, the IsMatEvalExpr type trait recognizes
+// the class as valid matrix evaluation expression template.
+*/
+struct MatEvalExpr : private EvalExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatForEachExpr.h b/src/cpu/blaze/math/expressions/MatForEachExpr.h
new file mode 100644
index 00000000..97f0ada3
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatForEachExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatForEachExpr.h
+// \brief Header file for the MatForEachExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATFOREACHEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/ForEachExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix for-each expression templates.
+// \ingroup math
+//
+// The MatForEachExpr class serves as a tag for all expression templates that represent a unary,
+// custom operation on a matrix. All classes, that represent a matrix custom operation and that
+// are used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as matrix for-each expression template. Only in case a class
+// is derived from the MatForEachExpr base class, the IsMatForEachExpr type trait recognizes the
+// class as valid matrix for-each expression template.
+*/
+struct MatForEachExpr : private ForEachExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatInvExpr.h b/src/cpu/blaze/math/expressions/MatInvExpr.h
new file mode 100644
index 00000000..f567ae39
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatInvExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatInvExpr.h
+// \brief Header file for the MatInvExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATINVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATINVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix inversion expression templates.
+// \ingroup math
+//
+// The MatInvExpr class serves as a tag for all expression templates that implement a matrix
+// inversion operation. All classes, that represent a matrix inversion operation and that are
+// used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as matrix inversion expression template. Only in case a
+// class is derived from the MatInvExpr base class, the IsMatInvExpr type trait recognizes
+// the class as valid matrix inversion expression template.
+*/
+struct MatInvExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatMatAddExpr.h b/src/cpu/blaze/math/expressions/MatMatAddExpr.h
new file mode 100644
index 00000000..3d7c9d41
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatMatAddExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatMatAddExpr.h
+// \brief Header file for the MatMatAddExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/AddExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix/matrix addition expression templates.
+// \ingroup math
+//
+// The MatMatAddExpr class serves as a tag for all expression templates that implement a
+// matrix/matrix addition. All classes, that represent a matrix addition and that are used
+// within the expression template environment of the Blaze library have to derive from this
+// class in order to qualify as matrix addition expression template. Only in case a class is
+// derived from the MatMatAddExpr base class, the IsMatMatAddExpr type trait recognizes the
+// class as valid matrix addition expression template.
+*/
+struct MatMatAddExpr : private AddExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatMatMultExpr.h b/src/cpu/blaze/math/expressions/MatMatMultExpr.h
new file mode 100644
index 00000000..4b9f2add
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatMatMultExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatMatMultExpr.h
+// \brief Header file for the MatMatMultExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix/matrix multiplication expression templates.
+// \ingroup math
+//
+// The MatMatMultExpr class serves as a tag for all expression templates that implement a
+// matrix/matrix multiplication. All classes, that represent a matrix multiplication and
+// that are used within the expression template environment of the Blaze library have to
+// derive from this class in order to qualify as matrix multiplication expression template.
+// Only in case a class is derived from the MatMatMultExpr base class, the IsMatMatMultExpr
+// type trait recognizes the class as valid matrix multiplication expression template.
+*/
+struct MatMatMultExpr : private MultExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatMatSubExpr.h b/src/cpu/blaze/math/expressions/MatMatSubExpr.h
new file mode 100644
index 00000000..57e1cb11
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatMatSubExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatMatSubExpr.h
+// \brief Header file for the MatMatSubExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SubExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix/matrix subtraction expression templates.
+// \ingroup math
+//
+// The MatMatSubExpr class serves as a tag for all expression templates that implement a
+// matrix/matrix subtraction. All classes, that represent a matrix subtraction and that are
+// used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as matrix subtraction expression template. Only in case a
+// class is derived from the MatMatSubExpr base class, the IsMatMatSubExpr type trait
+// recognizes the class as valid matrix subtraction expression template.
+*/
+struct MatMatSubExpr : private SubExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatScalarDivExpr.h b/src/cpu/blaze/math/expressions/MatScalarDivExpr.h
new file mode 100644
index 00000000..a61dc645
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatScalarDivExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatScalarDivExpr.h
+// \brief Header file for the MatScalarDivExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATSCALARDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DivExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix/scalar divsion expression templates.
+// \ingroup math
+//
+// The MatScalarDivExpr class serves as a tag for all expression templates that implement a
+// matrix/scalar divsion. All classes, that represent a matrix/scalar divsion and that are
+// used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as matrix/scalar divsion expression template. Only in case
+// a class is derived from the MatScalarDivExpr base class, the IsMatScalarDivExpr type trait
+// recognizes the class as valid matrix/scalar divsion expression template.
+*/
+struct MatScalarDivExpr : private DivExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatScalarMultExpr.h b/src/cpu/blaze/math/expressions/MatScalarMultExpr.h
new file mode 100644
index 00000000..d7745ea2
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatScalarMultExpr.h
@@ -0,0 +1,72 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatScalarMultExpr.h
+// \brief Header file for the MatScalarMultExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATSCALARMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix/scalar multiplication expression templates.
+// \ingroup math
+//
+// The MatScalarMultExpr class serves as a tag for all expression templates that implement a
+// matrix/scalar multiplication. All classes, that represent a matrix/scalar multiplication
+// and that are used within the expression template environment of the Blaze library have
+// to derive from this class in order to qualify as matrix/scalar multiplication expression
+// template. Only in case a class is derived from the MatScalarMultExpr base class, the
+// IsMatScalarMultExpr type trait recognizes the class as valid matrix/scalar multiplication
+// expression template.
+*/
+struct MatScalarMultExpr : private MultExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatSerialExpr.h b/src/cpu/blaze/math/expressions/MatSerialExpr.h
new file mode 100644
index 00000000..23a0dee4
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatSerialExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatSerialExpr.h
+// \brief Header file for the MatSerialExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATSERIALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SerialExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix serial evaluation expression templates.
+// \ingroup math
+//
+// The MatSerialExpr class serves as a tag for all expression templates that enforce a serial
+// evaluation of a matrix. All classes, that represent a matrix serialization operation and that
+// are used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as matrix serial evaluation expression template. Only in case
+// a class is derived from the MatSerialExpr base class, the IsMatSerialExpr type trait recognizes
+// the class as valid matrix serial evaluation expression template.
+*/
+struct MatSerialExpr : private SerialExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatTransExpr.h b/src/cpu/blaze/math/expressions/MatTransExpr.h
new file mode 100644
index 00000000..f569e1dd
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatTransExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatTransExpr.h
+// \brief Header file for the MatTransExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATTRANSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/TransExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix transposition expression templates.
+// \ingroup math
+//
+// The MatTransExpr class serves as a tag for all expression templates that implement a matrix
+// transposition operation. All classes, that represent a matrix transposition operation and
+// that are used within the expression template environment of the Blaze library have to derive
+// from this class in order to qualify as matrix transposition expression template. Only in case
+// a class is derived from the MatTransExpr base class, the IsMatTransExpr type trait recognizes
+// the class as valid matrix transposition expression template.
+*/
+struct MatTransExpr : private TransExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MatVecMultExpr.h b/src/cpu/blaze/math/expressions/MatVecMultExpr.h
new file mode 100644
index 00000000..36ae8e56
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MatVecMultExpr.h
@@ -0,0 +1,72 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MatVecMultExpr.h
+// \brief Header file for the MatVecMultExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all matrix/vector multiplication expression templates.
+// \ingroup math
+//
+// The MatVecMultExpr class serves as a tag for all expression templates that implement a
+// matrix/vector multiplication. All classes, that represent a matrix/vector multiplication
+// and that are used within the expression template environment of the Blaze library have
+// to derive from this class in order to qualify as matrix/vector multiplication expression
+// template. Only in case a class is derived from the MatVecMultExpr base class, the
+// IsMatVecMultExpr type trait recognizes the class as valid matrix/vector multiplication
+// expression template.
+*/
+struct MatVecMultExpr : private MultExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/Matrix.h b/src/cpu/blaze/math/expressions/Matrix.h
new file mode 100644
index 00000000..02e3b440
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/Matrix.h
@@ -0,0 +1,1331 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/Matrix.h
+// \brief Header file for the Matrix base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MATRIX_H_
+#define _BLAZE_MATH_EXPRESSIONS_MATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup matrix Matrices
+// \ingroup math
+*/
+/*!\brief Base class for matrices.
+// \ingroup matrix
+//
+// The Matrix class is a base class for all dense and sparse matrix classes within the Blaze
+// library. It provides an abstraction from the actual type of the matrix, but enables a
+// conversion back to this type via the 'Curiously Recurring Template Pattern' (CRTP).
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+struct Matrix
+{
+ //**Type definitions****************************************************************************
+ typedef MT MatrixType; //!< Type of the matrix.
+ //**********************************************************************************************
+
+ //**Non-const conversion operator***************************************************************
+ /*!\brief Conversion operator for non-constant matrices.
+ //
+ // \return Reference of the actual type of the matrix.
+ */
+ BLAZE_ALWAYS_INLINE MatrixType& operator~() noexcept {
+ return *static_cast<MatrixType*>( this );
+ }
+ //**********************************************************************************************
+
+ //**Const conversion operator*******************************************************************
+ /*!\brief Conversion operator for constant matrices.
+ //
+ // \return Constant reference of the actual type of the matrix.
+ */
+ BLAZE_ALWAYS_INLINE const MatrixType& operator~() const noexcept {
+ return *static_cast<const MatrixType*>( this );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Matrix global functions */
+//@{
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE typename MT::Iterator begin( Matrix<MT,SO>& matrix, size_t i );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE typename MT::ConstIterator begin( const Matrix<MT,SO>& matrix, size_t i );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE typename MT::ConstIterator cbegin( const Matrix<MT,SO>& matrix, size_t i );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE typename MT::Iterator end( Matrix<MT,SO>& matrix, size_t i );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE typename MT::ConstIterator end( const Matrix<MT,SO>& matrix, size_t i );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE typename MT::ConstIterator cend( const Matrix<MT,SO>& matrix, size_t i );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE size_t rows( const Matrix<MT,SO>& matrix ) noexcept;
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE size_t columns( const Matrix<MT,SO>& matrix ) noexcept;
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE size_t capacity( const Matrix<MT,SO>& matrix ) noexcept;
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE size_t capacity( const Matrix<MT,SO>& matrix, size_t i ) noexcept;
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const Matrix<MT,SO>& matrix );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const Matrix<MT,SO>& matrix, size_t i );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE void resize( Matrix<MT,SO>& matrix, size_t rows, size_t columns, bool preserve=true );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE void transpose( Matrix<MT,SO>& matrix );
+
+template< typename MT, bool SO >
+BLAZE_ALWAYS_INLINE bool isSquare( const Matrix<MT,SO>& matrix ) noexcept;
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+BLAZE_ALWAYS_INLINE bool isSame( const Matrix<MT1,SO1>& a, const Matrix<MT2,SO2>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+// \ingroup matrix
+//
+// \param matrix The given dense or sparse matrix.
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the given matrix is a row-major matrix the function returns an iterator to the first element
+// of row \a i, in case it is a column-major matrix the function returns an iterator to the first
+// element of column \a i.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE typename MT::Iterator begin( Matrix<MT,SO>& matrix, size_t i )
+{
+ return (~matrix).begin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+// \ingroup matrix
+//
+// \param matrix The given dense or sparse matrix.
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the given matrix is a row-major matrix the function returns an iterator to the first element
+// of row \a i, in case it is a column-major matrix the function returns an iterator to the first
+// element of column \a i.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE typename MT::ConstIterator begin( const Matrix<MT,SO>& matrix, size_t i )
+{
+ return (~matrix).begin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i.
+// \ingroup matrix
+//
+// \param matrix The given dense or sparse matrix.
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the given matrix is a row-major matrix the function returns an iterator to the first element
+// of row \a i, in case it is a column-major matrix the function returns an iterator to the first
+// element of column \a i.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE typename MT::ConstIterator cbegin( const Matrix<MT,SO>& matrix, size_t i )
+{
+ return (~matrix).cbegin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+// \ingroup matrix
+//
+// \param matrix The given dense or sparse matrix.
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the given matrix is a row-major matrix the function returns an iterator just past
+// the last element of row \a i, in case it is a column-major matrix the function returns an
+// iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE typename MT::Iterator end( Matrix<MT,SO>& matrix, size_t i )
+{
+ return (~matrix).end(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+// \ingroup matrix
+//
+// \param matrix The given dense or sparse matrix.
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the given matrix is a row-major matrix the function returns an iterator just past
+// the last element of row \a i, in case it is a column-major matrix the function returns an
+// iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE typename MT::ConstIterator end( const Matrix<MT,SO>& matrix, size_t i )
+{
+ return (~matrix).end(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i.
+// \ingroup matrix
+//
+// \param matrix The given dense or sparse matrix.
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the given matrix is a row-major matrix the function returns an iterator just past
+// the last element of row \a i, in case it is a column-major matrix the function returns an
+// iterator just past the last element of column \a i.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE typename MT::ConstIterator cend( const Matrix<MT,SO>& matrix, size_t i )
+{
+ return (~matrix).cend(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the matrix.
+// \ingroup matrix
+//
+// \param matrix The given matrix.
+// \return The number of rows of the matrix.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE size_t rows( const Matrix<MT,SO>& matrix ) noexcept
+{
+ return (~matrix).rows();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the matrix.
+// \ingroup matrix
+//
+// \param matrix The given matrix.
+// \return The number of columns of the matrix.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE size_t columns( const Matrix<MT,SO>& matrix ) noexcept
+{
+ return (~matrix).columns();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the matrix.
+// \ingroup matrix
+//
+// \param matrix The given matrix.
+// \return The capacity of the matrix.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE size_t capacity( const Matrix<MT,SO>& matrix ) noexcept
+{
+ return (~matrix).capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column.
+// \ingroup matrix
+//
+// \param matrix The given matrix.
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE size_t capacity( const Matrix<MT,SO>& matrix, size_t i ) noexcept
+{
+ return (~matrix).capacity( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the total number of non-zero elements in the matrix
+// \ingroup matrix
+//
+// \param matrix The given matrix.
+// \return The number of non-zero elements in the dense matrix.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE size_t nonZeros( const Matrix<MT,SO>& matrix )
+{
+ return (~matrix).nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+// \ingroup matrix
+//
+// \param matrix The given matrix.
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE size_t nonZeros( const Matrix<MT,SO>& matrix, size_t i )
+{
+ return (~matrix).nonZeros( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for non-resizable matrices.
+// \ingroup matrix
+//
+// \param matrix The given matrix to be resized.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Matrix cannot be resized.
+//
+// This function tries to change the number of rows and columns of a non-resizable matrix. Since
+// the matrix cannot be resized, in case the specified number of rows and columns is not identical
+// to the current number of rows and columns of the matrix, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE DisableIf_< IsResizable<MT> >
+ resize_backend( Matrix<MT,SO>& matrix, size_t m, size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+
+ if( (~matrix).rows() != m || (~matrix).columns() != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix cannot be resized" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for resizable, non-square matrices.
+// \ingroup matrix
+//
+// \param matrix The given matrix to be resized.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function changes the number of rows and columns of the given resizable, non-square matrix.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsResizable<MT>, Not< IsSquare<MT> > > >
+ resize_backend( Matrix<MT,SO>& matrix, size_t m, size_t n, bool preserve )
+{
+ (~matrix).resize( m, n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for resizable, square matrices.
+// \ingroup matrix
+//
+// \param matrix The given matrix to be resized.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid resize arguments for square matrix.
+//
+// This function changes the number of rows and columns of the given resizable, square matrix.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsResizable<MT>, IsSquare<MT> > >
+ resize_backend( Matrix<MT,SO>& matrix, size_t m, size_t n, bool preserve )
+{
+ if( m != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid resize arguments for square matrix" );
+ }
+
+ (~matrix).resize( m, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the matrix.
+// \ingroup matrix
+//
+// \param matrix The given matrix to be resized.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid resize arguments for square matrix.
+// \exception std::invalid_argument Matrix cannot be resized.
+//
+// This function provides a unified interface to resize dense and sparse matrices. In contrast
+// to the \c resize() member function, which is only available on resizable matrix types, this
+// function can be used on both resizable and non-resizable matrices. In case the given matrix
+// of type \a MT is resizable (i.e. provides a \c resize function) the type-specific \c resize()
+// member function is called. Depending on the type \a MT, this may result in the allocation of
+// new dynamic memory and the invalidation of existing views (submatrices, rows, columns, ...).
+// Note that in case the matrix is a compile time square matrix (as for instance the
+// blaze::SymmetricMatrix adaptor, ...) the specified number of rows must be identical to the
+// number of columns. Otherwise a \a std::invalid_argument exception is thrown. If the matrix
+// type \a MT is non-resizable (i.e. does not provide a \c resize() function) and if the specified
+// number of rows and columns is not identical to the current number of rows and columns of the
+// matrix, a \a std::invalid_argument exception is thrown.
+
+ \code
+ blaze::DynamicMatrix<int> A( 3UL, 3UL );
+ resize( A, 5UL, 2UL ); // OK: regular resize operation
+
+ blaze::SymmetricMatrix< DynamicMatrix<int> > B( 3UL );
+ resize( B, 4UL, 4UL ); // OK: Number of rows and columns is identical
+ resize( B, 3UL, 5UL ); // Error: Invalid arguments for square matrix!
+
+ blaze::StaticMatrix<int,3UL,3UL> C;
+ resize( C, 3UL, 3UL ); // OK: No resize necessary
+ resize( C, 5UL, 2UL ); // Error: Matrix cannot be resized!
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE void resize( Matrix<MT,SO>& matrix, size_t m, size_t n, bool preserve )
+{
+ resize_backend( matrix, m, n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the given matrix.
+// \ingroup matrix
+//
+// \param matrix The given matrix to be transposed.
+// \return void
+// \exception std::logic_error Matrix cannot be transposed.
+//
+// This function transposes the given matrix in-place. The function fails if ...
+//
+// - ... the given matrix has a fixed size and is non-square;
+// - ... the given matrix is a triangular matrix;
+// - ... the given submatrix affects the restricted parts of a triangular matrix;
+// - ... the given submatrix would cause non-deterministic results in a symmetric/Hermitian matrix.
+//
+// In all failure cases a \a std::logic_error exception is thrown.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE void transpose( Matrix<MT,SO>& matrix )
+{
+ (~matrix).transpose();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the given matrix.
+// \ingroup matrix
+//
+// \param matrix The given matrix to be transposed.
+// \return void
+// \exception std::logic_error Matrix cannot be transposed.
+//
+// This function transposes the given matrix in-place. The function fails if ...
+//
+// - ... the given matrix has a fixed size and is non-square;
+// - ... the given matrix is a triangular matrix;
+// - ... the given submatrix affects the restricted parts of a triangular matrix;
+// - ... the given submatrix would cause non-deterministic results in a symmetric/Hermitian matrix.
+//
+// In all failure cases a \a std::logic_error exception is thrown.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order of the matrix
+BLAZE_ALWAYS_INLINE void ctranspose( Matrix<MT,SO>& matrix )
+{
+ (~matrix).ctranspose();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given matrix is a square matrix.
+// \ingroup matrix
+//
+// \param matrix The matrix to be checked.
+// \return \a true if the matrix is a square matrix, \a false if not.
+//
+// This function checks if the number of rows and columns of the given matrix are equal. If
+// they are, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE bool isSquare( const Matrix<MT,SO>& matrix ) noexcept
+{
+ return ( IsSquare<MT>::value || (~matrix).rows() == (~matrix).columns() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the two given matrices represent the same observable state.
+// \ingroup matrix
+//
+// \param a The first matrix to be tested for its state.
+// \param b The second matrix to be tested for its state.
+// \return \a true in case the two matrices share a state, \a false otherwise.
+//
+// The isSame function provides an abstract interface for testing if the two given matrices
+// represent the same observable state. This happens for instance in case \c a and \c b refer
+// to the same matrix or in case \c a and \c b are aliases for the same matrix. In case both
+// matrices represent the same observable state, the function returns \a true, other it returns
+// \a false.
+
+ \code
+ typedef blaze::DynamicMatrix<int> MatrixType;
+ typedef blaze::Submatrix<MatrixType> SubmatrixType;
+
+ MatrixType mat1( 4UL, 5UL ); // Setup of a 4x5 dynamic matrix
+ MatrixType mat2( 4UL, 5UL ); // Setup of a second 4x5 dynamic matrix
+
+ SubmatrixType sub1 = submatrix( mat1, 0UL, 0UL, 4UL, 5UL ); // Submatrix fully covering mat1
+ SubmatrixType sub2 = submatrix( mat1, 1UL, 1UL, 2UL, 3UL ); // Submatrix partially covering mat1
+ SubmatrixType sub3 = submatrix( mat1, 1UL, 1UL, 2UL, 3UL ); // Submatrix partially covering mat1
+
+ isSame( mat1, mat1 ); // returns true since both objects refer to the same matrix
+ isSame( mat1, mat2 ); // returns false since mat1 and mat2 are two different matrices
+ isSame( mat1, sub1 ); // returns true since sub1 represents the same observable state as mat1
+ isSame( mat1, sub3 ); // returns false since sub3 only covers part of mat1
+ isSame( sub2, sub3 ); // returns true since sub1 and sub2 refer to exactly the same part of mat1
+ isSame( sub1, sub3 ); // returns false since sub1 and sub3 refer to different parts of mat1
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+BLAZE_ALWAYS_INLINE bool isSame( const Matrix<MT1,SO1>& a, const Matrix<MT2,SO2>& b ) noexcept
+{
+ return ( IsSame<MT1,MT2>::value &&
+ reinterpret_cast<const void*>( &a ) == reinterpret_cast<const void*>( &b ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the assignment of two matrices with the same storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of both matrices
+BLAZE_ALWAYS_INLINE void assign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ (~lhs).assign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the assignment of two matrices with different storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename MT2 > // Type of the right-hand side matrix
+BLAZE_ALWAYS_INLINE DisableIf_< IsSymmetric<MT2> >
+ assign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,!SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT1 );
+
+ (~lhs).assign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the assignment of a symmetric matrix to a matrix with
+// different storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename MT2 > // Type of the right-hand side matrix
+BLAZE_ALWAYS_INLINE EnableIf_< IsSymmetric<MT2> >
+ assign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,!SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT1 );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( ~rhs ), "Non-square symmetric matrix detected" );
+
+ (~lhs).assign( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a matrix to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \return void
+//
+// This function implements the default assignment of a matrix to a matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+BLAZE_ALWAYS_INLINE void assign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ assign_backend( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the addition assignment of two matrices with the same
+// storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be added.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of both matrices
+BLAZE_ALWAYS_INLINE void addAssign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ (~lhs).addAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the addition assignment of two matrices with different
+// storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be added.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename MT2 > // Type of the right-hand side matrix
+BLAZE_ALWAYS_INLINE DisableIf_< IsSymmetric<MT2> >
+ addAssign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,!SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT1 );
+
+ (~lhs).addAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the addition assignment of a symmetric matrix to a matrix
+// with different storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be added.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename MT2 > // Type of the right-hand side matrix
+BLAZE_ALWAYS_INLINE EnableIf_< IsSymmetric<MT2> >
+ addAssign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,!SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT1 );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( ~rhs ), "Non-square symmetric matrix detected" );
+
+ (~lhs).addAssign( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a matrix to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be added.
+// \return void
+//
+// This function implements the default addition assignment of a matrix to a matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+BLAZE_ALWAYS_INLINE void addAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ addAssign_backend( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the subtraction assignment of two matrices with the same
+// storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of both matrices
+BLAZE_ALWAYS_INLINE void subAssign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ (~lhs).subAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the subtraction assignment of two matrices with different
+// storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename MT2 > // Type of the right-hand side matrix
+BLAZE_ALWAYS_INLINE DisableIf_< IsSymmetric<MT2> >
+ subAssign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,!SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT1 );
+
+ (~lhs).subAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the subtraction assignment of a symmetric matrix to a matrix
+// with different storage order.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename MT2 > // Type of the right-hand side matrix
+BLAZE_ALWAYS_INLINE EnableIf_< IsSymmetric<MT2> >
+ subAssign_backend( Matrix<MT1,SO>& lhs, const Matrix<MT2,!SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT1 );
+
+ BLAZE_INTERNAL_ASSERT( isSquare( ~rhs ), "Non-square symmetric matrix detected" );
+
+ (~lhs).subAssign( trans( ~rhs ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a matrix to matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+//
+// This function implements the default subtraction assignment of a matrix to a matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+BLAZE_ALWAYS_INLINE void subAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ subAssign_backend( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a matrix to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be multiplied.
+// \return void
+//
+// This function implements the default multiplication assignment of a matrix to a matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+BLAZE_ALWAYS_INLINE void multAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
+
+ (~lhs).multAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a vector to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool tryAssign( const Matrix<MT,SO>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= (~lhs).rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= (~lhs).columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= (~lhs).rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= (~lhs).columns() - column ), "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs, rhs, row, column );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a matrix to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+BLAZE_ALWAYS_INLINE bool tryAssign( const Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= (~lhs).rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= (~lhs).columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= (~lhs).rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= (~lhs).columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs, rhs, row, column );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool tryAddAssign( const Matrix<MT,SO>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= (~lhs).rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= (~lhs).columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= (~lhs).rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= (~lhs).columns() - column ), "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs, rhs, row, column );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+BLAZE_ALWAYS_INLINE bool tryAddAssign( const Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= (~lhs).rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= (~lhs).columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= (~lhs).rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= (~lhs).columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs, rhs, row, column );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool trySubAssign( const Matrix<MT,SO>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= (~lhs).rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= (~lhs).columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= (~lhs).rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= (~lhs).columns() - column ), "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs, rhs, row, column );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+BLAZE_ALWAYS_INLINE bool trySubAssign( const Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= (~lhs).rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= (~lhs).columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= (~lhs).rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= (~lhs).columns() - column, "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs, rhs, row, column );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side vector to be multiplied.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool tryMultAssign( const Matrix<MT,SO>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= (~lhs).rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= (~lhs).columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= (~lhs).rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= (~lhs).columns() - column ), "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs, rhs, row, column );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the division assignment of a vector to a matrix.
+// \ingroup matrix
+//
+// \param lhs The target left-hand side matrix.
+// \param rhs The right-hand side vector divisor.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the left-hand side matrix
+ , bool SO // Storage order of the left-hand side matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool tryDivAssign( const Matrix<MT,SO>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= (~lhs).rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= (~lhs).columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= (~lhs).rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= (~lhs).columns() - column ), "Invalid number of columns" );
+
+ UNUSED_PARAMETER( lhs, rhs, row, column );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removal of all restrictions on the data access to the given matrix.
+// \ingroup matrix
+//
+// \param matrix The matrix to be derestricted.
+// \return Reference to the matrix without access restrictions.
+//
+// This function removes all restrictions on the data access to the given matrix. It returns a
+// reference to the matrix that does provide the same interface but does not have any restrictions
+// on the data access.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+BLAZE_ALWAYS_INLINE MT& derestrict( Matrix<MT,SO>& matrix )
+{
+ return ~matrix;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/MultExpr.h b/src/cpu/blaze/math/expressions/MultExpr.h
new file mode 100644
index 00000000..5806b6d5
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/MultExpr.h
@@ -0,0 +1,72 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/MultExpr.h
+// \brief Header file for the MultExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_MULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_MULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all multiplication expression templates.
+// \ingroup math
+//
+// The MultExpr class serves as a tag for all expression templates that implement mathematical
+// multiplications. All classes, that represent a mathematical multiplication (element-wise
+// vector multiplications, matrix/vector multiplications, vector/matrix multiplications and
+// matrix/matrix multiplications) and that are used within the expression template environment
+// of the Blaze library have to derive from this class in order to qualify as multiplication
+// expression template. Only in case a class is derived from the MultExpr base class, the
+// IsMultExpr type trait recognizes the class as valid multiplication expression template.
+*/
+struct MultExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatDMatMultExpr.h b/src/cpu/blaze/math/expressions/SMatDMatMultExpr.h
new file mode 100644
index 00000000..51a129d4
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatDMatMultExpr.h
@@ -0,0 +1,2024 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatDMatMultExpr.h
+// \brief Header file for the sparse matrix/dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecSMatMultExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The SMatDMatMultExpr class represents the compile time expression for multiplications between
+// a row-major sparse matrix and a row-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class SMatDMatMultExpr : public DenseMatrix< SMatDMatMultExpr<MT1,MT2>, false >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side sparse matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T3::simdEnabled &&
+ IsRowMajorMatrix<T1>::value &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case a vectorized computation of the matrix multiplication is not possible, but a
+ loop-unrolled computation is feasible, the nested \value will be set to 1, otherwise
+ it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !UseVectorizedKernel<T1,T2,T3>::value &&
+ !IsDiagonal<T3>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !IsResizable<ET1>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case neither a vectorized nor optimized computation is possible, the nested \value will
+ be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseVectorizedKernel<T1,T2,T3>::value &&
+ !UseOptimizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatDMatMultExpr<MT1,MT2> This; //!< Type of this SMatDMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT2>::value &&
+ MT2::simdEnabled &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatDMatMultExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the multiplication expression.
+ // \param rhs The right-hand side dense matrix operand of the multiplication expression.
+ */
+ explicit inline SMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_SMATDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-dense matrix multiplication to a dense matrix
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-dense
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a sparse matrix-dense matrix multiplication to dense matrices
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the sparse matrix-dense matrix
+ // multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( Or< IsRowMajorMatrix<MT3>, IsDiagonal<MT5> >::value ? B.columns() : 64UL );
+
+ reset( C );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jtmp( min( jj+block, B.columns() ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ ConstIterator element( A.begin(i) );
+ const ConstIterator end( A.end(i) );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+
+ if( IsDiagonal<MT5>::value )
+ {
+ C(i,i1) = element->value() * B(i1,i1);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i1 : i1+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ if( isDefault( C(i,j) ) )
+ C(i,j) = element->value() * B(i1,j);
+ else
+ C(i,j) += element->value() * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a sparse matrix-dense matrix multiplication to dense matrices
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the optimized assignment kernel for the sparse matrix-dense matrix
+ // multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 64UL );
+
+ reset( C );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jtmp( min( jj+block, B.columns() ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i4 : i4+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( jbegin + jnum - ( jnum % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=jbegin; j<jpos; j+=4UL ) {
+ C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
+ C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
+ }
+ for( size_t j=jpos; j<jend; ++j ) {
+ C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i1 : i1+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( jbegin + jnum - ( jnum % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=jbegin; j<jpos; j+=4UL ) {
+ C(i,j ) += v1 * B(i1,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL);
+ C(i,j+2UL) += v1 * B(i1,j+2UL);
+ C(i,j+3UL) += v1 * B(i1,j+3UL);
+ }
+ for( size_t j=jpos; j<jend; ++j ) {
+ C(i,j) += v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized assignment to dense matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized assignment of a sparse matrix-dense matrix multiplication to dense matrices
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized assignment kernel for the sparse matrix-dense matrix
+ // multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i4 : i4+1UL )
+ :( B.columns() ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) + xmm1 * B.load(i1,j) + xmm2 * B.load(i2,j) + xmm3 * B.load(i3,j) + xmm4 * B.load(i4,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i1 : i1+1UL )
+ :( B.columns() ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) + xmm1 * B.load(i1,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ C(i,j) += v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-dense matrix multiplication to a sparse matrix
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-dense
+ // matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-dense matrix multiplication to a dense matrix
+ // (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a sparse matrix-dense matrix multiplication to
+ // dense matrices (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the sparse matrix-dense
+ // matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( Or< IsRowMajorMatrix<MT3>, IsDiagonal<MT5> >::value ? B.columns() : 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jtmp( min( jj+block, B.columns() ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+
+ if( IsDiagonal<MT5>::value )
+ {
+ C(i,i1) += element->value() * B(i1,i1);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i1 : i1+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( jbegin + jnum - ( jnum % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=jbegin; j<jpos; j+=4UL ) {
+ C(i,j ) += element->value() * B(i1,j );
+ C(i,j+1UL) += element->value() * B(i1,j+1UL);
+ C(i,j+2UL) += element->value() * B(i1,j+2UL);
+ C(i,j+3UL) += element->value() * B(i1,j+3UL);
+ }
+ for( size_t j=jpos; j<jend; ++j ) {
+ C(i,j) += element->value() * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a sparse matrix-dense matrix multiplication to
+ // dense matrices (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the optimized addition assignment kernel for the sparse matrix-
+ // dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jtmp( min( jj+block, B.columns() ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i4 : i4+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( jbegin + jnum - ( jnum % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=jbegin; j<jpos; j+=4UL ) {
+ C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
+ C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
+ }
+ for( size_t j=jpos; j<jend; ++j ) {
+ C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i1 : i1+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( jbegin + jnum - ( jnum % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=jbegin; j<jpos; j+=4UL ) {
+ C(i,j ) += v1 * B(i1,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL);
+ C(i,j+2UL) += v1 * B(i1,j+2UL);
+ C(i,j+3UL) += v1 * B(i1,j+3UL);
+ }
+ for( size_t j=jpos; j<jend; ++j ) {
+ C(i,j) += v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized addition assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized addition assignment of a sparse matrix-dense matrix multiplication to
+ // dense matrices (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized addition assignment kernel for the sparse matrix-
+ // dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i4 : i4+1UL )
+ :( B.columns() ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) + xmm1 * B.load(i1,j) + xmm2 * B.load(i2,j) + xmm3 * B.load(i3,j) + xmm4 * B.load(i4,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i1 : i1+1UL )
+ :( B.columns() ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) + xmm1 * B.load(i1,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ C(i,j) += v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-dense matrix multiplication to a dense
+ // matrix (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a sparse matrix-dense matrix multiplication
+ // (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the sparse matrix-
+ // dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( Or< IsRowMajorMatrix<MT3>, IsDiagonal<MT5> >::value ? B.columns() : 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jtmp( min( jj+block, B.columns() ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+
+ if( IsDiagonal<MT5>::value )
+ {
+ C(i,i1) -= element->value() * B(i1,i1);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i1 : i1+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( jbegin + jnum - ( jnum % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=jbegin; j<jpos; j+=4UL ) {
+ C(i,j ) -= element->value() * B(i1,j );
+ C(i,j+1UL) -= element->value() * B(i1,j+1UL);
+ C(i,j+2UL) -= element->value() * B(i1,j+2UL);
+ C(i,j+3UL) -= element->value() * B(i1,j+3UL);
+ }
+ for( size_t j=jpos; j<jend; ++j ) {
+ C(i,j) -= element->value() * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a sparse matrix-dense matrix multiplication
+ // (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the optimized subtraction assignment kernel for the sparse matrix-
+ // dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jtmp( min( jj+block, B.columns() ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i4 : i4+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( jbegin + jnum - ( jnum % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=jbegin; j<jpos; j+=4UL ) {
+ C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ C(i,j+2UL) -= v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
+ C(i,j+3UL) -= v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
+ }
+ for( size_t j=jpos; j<jend; ++j ) {
+ C(i,j) -= v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT5>::value ? i1 : i1+1UL ) ) )
+ :( jtmp ) );
+
+ if( IsTriangular<MT5>::value && jbegin >= jend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( jbegin + jnum - ( jnum % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=jbegin; j<jpos; j+=4UL ) {
+ C(i,j ) -= v1 * B(i1,j );
+ C(i,j+1UL) -= v1 * B(i1,j+1UL);
+ C(i,j+2UL) -= v1 * B(i1,j+2UL);
+ C(i,j+3UL) -= v1 * B(i1,j+3UL);
+ }
+ for( size_t j=jpos; j<jend; ++j ) {
+ C(i,j) -= v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized subtraction assignment to dense matrices*****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized subtraction assignment of a sparse matrix-dense matrix multiplication
+ // (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized subtraction assignment kernel for the sparse matrix-
+ // dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i4 : i4+1UL )
+ :( B.columns() ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) - xmm1 * B.load(i1,j) - xmm2 * B.load(i2,j) - xmm3 * B.load(i3,j) - xmm4 * B.load(i4,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ C(i,j) -= v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( ( IsStrictlyUpper<MT5>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i1 : i1+1UL )
+ :( B.columns() ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) - xmm1 * B.load(i1,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ C(i,j) -= v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-dense matrix multiplication to a dense matrix
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-dense
+ // matrix multiplication expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-dense matrix multiplication to a sparse matrix
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-dense
+ // matrix multiplication expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-dense matrix multiplication to a dense
+ // matrix (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-dense matrix multiplication to a dense
+ // matrix (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major sparse matrix and a
+// row-major dense matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the multiplication.
+// \param rhs The right-hand side dense matrix for the multiplication.
+// \return The resulting matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the multiplication of a row-major sparse matrix and a row-major
+// dense matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A;
+ blaze::DynamicMatrix<double,rowMajor> B, C;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const SMatDMatMultExpr<T1,T2>
+ operator*( const SparseMatrix<T1,false>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatDMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatDMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< SMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsAligned<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatDVecMultExprTrait< SMatDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , SMatDVecMultExprTrait_< MT1, DMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatSVecMultExprTrait< SMatDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , SMatDVecMultExprTrait_< MT1, DMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecDMatMultExprTrait< VT, SMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecDMatMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecDMatMultExprTrait< VT, SMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TSVecDMatMultExprTrait_< TSVecSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatDMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatDMatSubExpr.h b/src/cpu/blaze/math/expressions/SMatDMatSubExpr.h
new file mode 100644
index 00000000..69f2e93e
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatDMatSubExpr.h
@@ -0,0 +1,1097 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatDMatSubExpr.h
+// \brief Header file for the sparse matrix/dense matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATDMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATDMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATDMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-dense matrix subtractions.
+// \ingroup dense_matrix_expression
+//
+// The SMatDMatSubExpr class represents the compile time expression for subtractions between
+// a sparse matrix and a dense matrix with identical storage order.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+class SMatDMatSubExpr : public DenseMatrix< SMatDMatSubExpr<MT1,MT2,SO>, SO >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatDMatSubExpr<MT1,MT2,SO> This; //!< Type of this SMatDMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatDMatSubExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the addition expression.
+ // \param rhs The right-hand side dense matrix operand of the addition expression.
+ */
+ explicit inline SMatDMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) ) ||
+ ( IsExpression<MT2>::value && rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return lhs_.isAliased( alias ) || rhs_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-dense
+ // matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const SMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign ( ~lhs, -rhs.rhs_ );
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-dense
+ // matrix subtraction expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const SMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // dense matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const SMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.rhs_ );
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // dense matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const SMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.rhs_ );
+ subAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-dense
+ // matrix subtraction expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const SMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign ( ~lhs, -rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-dense
+ // matrix subtraction expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const SMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO == SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( ResultType, SO );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OppositeType, !SO );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse matrix-
+ // dense matrix subtraction expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const SMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-dense matrix subtraction expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const SMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT2 );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT1, MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a sparse matrix and a dense matrix with
+// identical storage order (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the sparse matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the subtraction of a sparse matrix and a dense matrix with identical
+// storage order:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A;
+ blaze::DynamicMatrix<double,rowMajor> B, C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order
+inline const SMatDMatSubExpr<T1,T2,SO>
+ operator-( const SparseMatrix<T1,SO>& lhs, const DenseMatrix<T2,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatDMatSubExpr<T1,T2,SO>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a sparse matrix-dense matrix subtraction
+// expression and a dense matrix (\f$ A=(B-C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix-dense matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a sparse
+// matrix-dense matrix subtraction expression to a dense matrix.
+*/
+template< typename T1 // Type of the sparse matrix of the left-hand side expression
+ , typename T2 // Type of the dense matrix of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< SMatDMatSubExpr<T1,T2,SO1>, T3 >
+ operator+( const SMatDMatSubExpr<T1,T2,SO1>& lhs, const DenseMatrix<T3,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~rhs) - lhs.rightOperand() ) + lhs.leftOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a sparse matrix-dense matrix subtraction
+// expression and a dense matrix (\f$ A=(B-C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix-dense matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a sparse
+// matrix-dense matrix subtraction expression and a dense matrix.
+*/
+template< typename T1 // Type of the sparse matrix of the left-hand side expression
+ , typename T2 // Type of the dense matrix of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< SMatDMatSubExpr<T1,T2,SO1>, T3 >
+ operator-( const SMatDMatSubExpr<T1,T2,SO1>& lhs, const DenseMatrix<T3,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return lhs.leftOperand() - ( lhs.rightOperand() + (~rhs) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Rows< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct Columns< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsSymmetric< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsHermitian< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsLower< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniLower< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyLower< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUpper< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsUniUpper< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct IsStrictlyUpper< SMatDMatSubExpr<MT1,MT2,SO> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< SMatDMatSubExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< DMatDMatSubExprTrait_<MT3,MT2>, MT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< SMatDMatSubExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< TDMatDMatSubExprTrait_<MT3,MT2>, MT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatDMatAddExprTrait< SMatDMatSubExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< DMatTDMatSubExprTrait_<MT3,MT2>, MT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatTDMatAddExprTrait< SMatDMatSubExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatTSMatAddExprTrait_< TDMatTDMatSubExprTrait_<MT3,MT2>, MT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< SMatDMatSubExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , SMatDMatSubExprTrait_< MT1, DMatDMatAddExprTrait_<MT2,MT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< SMatDMatSubExpr<MT1,MT2,false>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , SMatDMatSubExprTrait_< MT1, DMatTDMatAddExprTrait_<MT2,MT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatDMatSubExprTrait< SMatDMatSubExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , TSMatDMatSubExprTrait_< MT1, TDMatDMatAddExprTrait_<MT2,MT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct TDMatTDMatSubExprTrait< SMatDMatSubExpr<MT1,MT2,true>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TSMatTDMatSubExprTrait_< MT1, TDMatTDMatAddExprTrait_<MT2,MT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO, bool AF >
+struct SubmatrixExprTrait< SMatDMatSubExpr<MT1,MT2,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct RowExprTrait< SMatDMatSubExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool SO >
+struct ColumnExprTrait< SMatDMatSubExpr<MT1,MT2,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatDVecMultExpr.h b/src/cpu/blaze/math/expressions/SMatDVecMultExpr.h
new file mode 100644
index 00000000..81eae0ef
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatDVecMultExpr.h
@@ -0,0 +1,949 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatDVecMultExpr.h
+// \brief Header file for the sparse matrix/dense vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-dense vector multiplications.
+// \ingroup dense_vector_expression
+//
+// The SMatDVecMultExpr class represents the compile time expression for multiplications
+// between row-major sparse matrices and dense vectors.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename VT > // Type of the right-hand side dense vector
+class SMatDVecMultExpr : public DenseVector< SMatDVecMultExpr<MT,VT>, false >
+ , private MatVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the multiplication expression. In case either the matrix or
+ the vector operand requires an intermediate evaluation or the dense vector expression
+ is a compound expression, \a useAssign will be set to \a true and the multiplication
+ expression will be evaluated via the \a assign function family. Otherwise \a useAssign
+ will be set to \a false and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = evaluateMatrix || evaluateVector };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatDVecMultExpr<MT,VT> This; //!< Type of this SMatDVecMultExpr instance.
+ typedef MultTrait_<MRT,VRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SMatDVecMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatDVecMultExpr class.
+ //
+ // \param mat The left-hand side sparse matrix operand of the multiplication expression.
+ // \param vec The right-hand side dense vector operand of the multiplication expression.
+ */
+ explicit inline SMatDVecMultExpr( const MT& mat, const VT& vec ) noexcept
+ : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
+ , vec_( vec ) // Right-hand side dense vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
+ return row( mat_, index ) * vec_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return vec_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_SMATDVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand mat_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand vec_; //!< Right-hand side dense vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-dense
+ // vector multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ assign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ assign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-dense vector multiplication to a sparse vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-dense
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ assign( SparseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-dense vector multiplication to a dense vector.
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ addAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ addAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ subAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ subAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either the left-hand side matrix operand requires an intermediate evaluation or
+ // the right-hand side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ multAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a sparse matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a sparse matrix-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // the left-hand side matrix operand requires an intermediate evaluation or the right-hand
+ // side vector operand is a compound expression.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT1> >
+ divAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-dense
+ // vector multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-dense vector multiplication to a sparse vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-dense
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of
+ // a sparse matrix-dense vector multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a sparse
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR( MT, VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major sparse matrix and a
+// dense vector (\f$ \vec{y}=A*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side row-major sparse matrix for the multiplication.
+// \param vec The right-hand side dense vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator represents the multiplication between a row-major sparse matrix and a dense
+// vector:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ blaze::CompressedMatrix<double,rowMajor> A;
+ blaze::DynamicVector<double,columnVector> x, y;
+ // ... Resizing and initialization
+ y = A * x;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both the
+// sparse matrix type \a T1 and the dense vector type \a T2 as well as the two element types
+// \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of columns
+// of the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense vector
+inline const DisableIf_< IsMatMatMultExpr<T1>, SMatDVecMultExpr<T1,T2> >
+ operator*( const SparseMatrix<T1,false>& mat, const DenseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return SMatDVecMultExpr<T1,T2>( ~mat, ~vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-matrix
+// multiplication expression and a dense vector (\f$ \vec{y}=(A*B)*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side sparse matrix-matrix multiplication.
+// \param vec The right-hand side dense vector for the multiplication.
+// \return The resulting vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a sparse
+// matrix-matrix multiplication expression and a dense vector. It restructures the expression
+// \f$ \vec{y}=(A*B)*\vec{x} \f$ to the expression \f$ \vec{y}=A*(B*\vec{x}) \f$.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , bool SO // Storage order of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense vector
+inline const EnableIf_< IsMatMatMultExpr<T1>, MultExprTrait_<T1,T2> >
+ operator*( const SparseMatrix<T1,SO>& mat, const DenseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( T1 );
+
+ return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct Size< SMatDVecMultExpr<MT,VT> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct IsAligned< SMatDVecMultExpr<MT,VT> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, bool AF >
+struct SubvectorExprTrait< SMatDVecMultExpr<MT,VT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>
+ , SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatEvalExpr.h b/src/cpu/blaze/math/expressions/SMatEvalExpr.h
new file mode 100644
index 00000000..a07f4421
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatEvalExpr.h
@@ -0,0 +1,1011 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatEvalExpr.h
+// \brief Header file for the sparse matrix evaluation expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATEVALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatEvalExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/EvalExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatEvalExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TSMatEvalExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATEVALEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the forced evaluation of sparse matrices.
+// \ingroup sparse_matrix_expression
+//
+// The SMatEvalExpr class represents the compile time expression for the forced evaluation
+// of a sparse matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+class SMatEvalExpr : public SparseMatrix< SMatEvalExpr<MT,SO>, SO >
+ , private MatEvalExpr
+ , private Computation
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatEvalExpr<MT,SO> This; //!< Type of this SMatEvalExpr instance.
+ typedef ResultType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatEvalExpr class.
+ //
+ // \param sm The sparse matrix operand of the evaluation expression.
+ */
+ explicit inline SMatEvalExpr( const MT& sm ) noexcept
+ : sm_( sm ) // Sparse matrix of the evaluation expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < sm_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < sm_.columns(), "Invalid column access index" );
+ return sm_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= sm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= sm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return sm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return sm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return sm_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return sm_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the sparse matrix operand.
+ //
+ // \return The sparse matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return sm_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return sm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return sm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return sm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand sm_; //!< Sparse matrix of the evaluation expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix evaluation
+ // expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluatin expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix evaluation
+ // expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix
+ // evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void addAssign( SparseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void subAssign( SparseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse matrix evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // matrix evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void multAssign( DenseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse matrix evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void multAssign( SparseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAssign( DenseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluatin expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix
+ // evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpAssign( SparseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpAddAssign( SparseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpSubAssign( SparseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse matrix evaluation expression to a dense
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // matrix evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpMultAssign( DenseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpMultAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse matrix evaluation expression to a sparse
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // matrix evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpMultAssign( SparseMatrix<MT2,SO2>& lhs, const SMatEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpMultAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Forces the evaluation of the given sparse matrix expression \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The evaluated sparse matrix.
+//
+// The \a eval function forces the evaluation of the given sparse matrix expression \a sm.
+// The function returns an expression representing the operation.\n
+// The following example demonstrates the use of the \a eval function
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = eval( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatEvalExpr<MT,SO> eval( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatEvalExpr<MT,SO>( ~sm );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Evaluation of the given sparse matrix evaluation expression \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input evaluation expression.
+// \return The evaluated sparse matrix.
+//
+// This function implements a performance optimized treatment of the evaluation of a sparse matrix
+// evaluation expression.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatEvalExpr<MT,SO> eval( const SMatEvalExpr<MT,SO>& sm )
+{
+ return sm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Rows< SMatEvalExpr<MT,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Columns< SMatEvalExpr<MT,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< SMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< SMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsLower< SMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniLower< SMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyLower< SMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUpper< SMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniUpper< SMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyUpper< SMatEvalExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct SMatEvalExprTrait< SMatEvalExpr<MT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatEvalExpr<MT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TSMatEvalExprTrait< SMatEvalExpr<MT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatEvalExpr<MT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool AF >
+struct SubmatrixExprTrait< SMatEvalExpr<MT,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = EvalExprTrait_< SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct RowExprTrait< SMatEvalExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = EvalExprTrait_< RowExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct ColumnExprTrait< SMatEvalExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = EvalExprTrait_< ColumnExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatForEachExpr.h b/src/cpu/blaze/math/expressions/SMatForEachExpr.h
new file mode 100644
index 00000000..e60da6b0
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatForEachExpr.h
@@ -0,0 +1,2591 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatForEachExpr.h
+// \brief Header file for the sparse matrix for-each expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATFOREACHEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatForEachExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functors.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/ForEachExprTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATFOREACHEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the sparse matrix forEach() function.
+// \ingroup sparse_matrix_expression
+//
+// The SMatForEachExpr class represents the compile time expression for the evaluation of a
+// custom operation on each element of a sparse matrix via the forEach() function.
+*/
+template< typename MT // Type of the sparse matrix
+ , typename OP // Type of the custom operation
+ , bool SO > // Storage order
+class SMatForEachExpr : public SparseMatrix< SMatForEachExpr<MT,OP,SO>, SO >
+ , private MatForEachExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the sparse matrix expression.
+ typedef OppositeType_<MT> OT; //!< Opposite type of the sparse matrix expression.
+ typedef ReturnType_<MT> RN; //!< Return type of the sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the for-each expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the for-each expression. In case the given sparse
+ matrix expression of type \a MT requires an intermediate evaluation, \a useAssign will
+ be set to 1 and the for-each expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to 0 and the expression will be evaluated
+ via the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target matrix or the sparse matrix operand is not SMP
+ assignable or the matrix operand requires an intermediate evaluation, \a value is set to
+ 1 and the expression specific evaluation strategy is selected. Otherwise \a value is set
+ to 0 and the default strategy is chosen. */
+ template< typename MT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatForEachExpr<MT,OP,SO> This; //!< Type of this SMatForEachExpr instance.
+ typedef ForEachTrait_<MT,OP> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef decltype( std::declval<OP>()( std::declval<RN>() ) ) ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SMatForEachExpr& > CompositeType;
+
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+
+ //! Data type of the custom unary operation.
+ typedef OP Operation;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse matrix for-each expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse matrix expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse matrix expression.
+ typedef ConstIterator_< RemoveReference_<Operand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param it Iterator to the initial matrix element.
+ // \param op The custom unary operation.
+ */
+ inline ConstIterator( IteratorType it, OP op )
+ : it_( it ) // Iterator over the elements of the sparse matrix expression
+ , op_( op ) // The custom unary operation
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( op_( it_->value() ), it_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return Reference to the sparse matrix element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return op_( it_->value() );
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator over the elements of the sparse matrix expression.
+ OP op_; //!< The custom unary operation.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatForEachExpr class.
+ //
+ // \param sm The sparse matrix operand of the for-each expression.
+ // \param op The custom unary operation.
+ */
+ explicit inline SMatForEachExpr( const MT& sm, OP op ) noexcept
+ : sm_( sm ) // Sparse matrix of the for-each expression
+ , op_( op ) // The custom unary operation
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < sm_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < sm_.columns(), "Invalid column access index" );
+ return op_( sm_(i,j) );
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= sm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= sm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( sm_.begin(i), op_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( sm_.end(i), op_ );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return sm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return sm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return sm_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return sm_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific matrix element.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( sm_.find( i, j ), op_ );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( sm_.lowerBound( i, j ), op_ );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( sm_.upperBound( i, j ), op_ );
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the sparse matrix operand.
+ //
+ // \return The sparse matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return sm_;
+ }
+ //**********************************************************************************************
+
+ //**Operation access****************************************************************************
+ /*!\brief Returns a copy of the custom operation.
+ //
+ // \return A copy of the custom operation.
+ */
+ inline Operation operation() const {
+ return op_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return sm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return sm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return sm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand sm_; //!< Sparse matrix of the absolute value expression.
+ Operation op_; //!< The custom unary operation.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix for-each expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix for-each
+ // expression to a dense matrix. Due to the explicit application of the SFINAE principle, this
+ // function can only be selected by the compiler in case the operand requires an intermediate
+ // evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( DenseMatrix<MT2,SO2>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( serial( rhs.sm_ ) );
+ assign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix for-each expression to a row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix for-each
+ // expression to a row-major sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand requires
+ // an intermediate evaluation and the underlying numeric data type of the operand and the
+ // target matrix are identical.
+ */
+ template< typename MT2 > // Type of the target sparse matrix
+ friend inline EnableIf_< And< UseAssign<MT2>
+ , IsSame< UnderlyingNumeric<MT>, UnderlyingNumeric<MT2> > > >
+ assign( SparseMatrix<MT2,false>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef Iterator_<MT2> Iterator;
+
+ assign( ~lhs, rhs.sm_ );
+
+ const size_t m( rhs.rows() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ const Iterator end( (~lhs).end(i) );
+ for( Iterator element=(~lhs).begin(i); element!=end; ++element ) {
+ element->value() = rhs.op_( element->value() );
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix for-each expression to a column-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix for-each
+ // expression to a column-major sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand requires
+ // an intermediate evaluation and the underlying numeric data type of the operand and the
+ // target matrix are identical.
+ */
+ template< typename MT2 > // Type of the target sparse matrix
+ friend inline EnableIf_< And< UseAssign<MT2>
+ , IsSame< UnderlyingNumeric<MT>, UnderlyingNumeric<MT2> > > >
+ assign( SparseMatrix<MT2,true>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef Iterator_<MT2> Iterator;
+
+ assign( ~lhs, rhs.sm_ );
+
+ const size_t n( rhs.columns() );
+
+ for( size_t j=0UL; j<n; ++j ) {
+ const Iterator end( (~lhs).end(j) );
+ for( Iterator element=(~lhs).begin(j); element!=end; ++element ) {
+ element->value() = rhs.op_( element->value() );
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix for-each expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix for-each
+ // expression to a sparse matrix. Due to the explicit application of the SFINAE principle, this
+ // function can only be selected by the compiler in case the operand requires an intermediate
+ // evaluation and the underlying numeric data type of the operand and the target vector differ.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< And< UseAssign<MT2>
+ , Not< IsSame< UnderlyingNumeric<MT>, UnderlyingNumeric<MT2> > > > >
+ assign( SparseMatrix<MT2,SO2>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( serial( rhs.sm_ ) );
+ (~lhs).reserve( tmp.nonZeros() );
+ assign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix for-each expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse
+ // matrix for-each expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ addAssign( DenseMatrix<MT2,SO2>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( serial( rhs.sm_ ) );
+ addAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix for-each expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // matrix for-each expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ subAssign( DenseMatrix<MT2,SO2>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( serial( rhs.sm_ ) );
+ subAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix for-each expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix
+ // for-each expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( DenseMatrix<MT2,SO2>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( rhs.sm_ );
+ smpAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix for-each expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix for-each expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( rhs.sm_ );
+ smpAddAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix for-each expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side for-each expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix for-each expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const SMatForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( RT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const RT tmp( rhs.sm_ );
+ smpSubAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluates the given custom operation on each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \param op The custom operation.
+// \return The custom operation applied to each single element of \a sm.
+//
+// The \a forEach() function evaluates the given custom operation on each non-zero element of the
+// input matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a forEach() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = forEach( A, []( double a ){ return std::sqrt( a ); } );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , typename OP > // Type of the custom operation
+inline const SMatForEachExpr<MT,OP,SO> forEach( const SparseMatrix<MT,SO>& sm, OP op )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,OP,SO>( ~sm, op );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a abs() function to each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The resulting sparse matrix.
+//
+// This function applies the abs() function to each non-zero element of the input matrix \a sm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a abs() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = abs( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Abs,SO> abs( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Abs,SO>( ~sm, Abs() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a floor() function to each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The resulting sparse matrix.
+//
+// This function applies the floor() function to each non-zero element of the input matrix \a sm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a floor() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = floor( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Floor,SO> floor( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Floor,SO>( ~sm, Floor() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a ceil() function to each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The resulting sparse matrix.
+//
+// This function applies the ceil() function to each non-zero element of the input matrix \a sm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a ceil() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = ceil( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Ceil,SO> ceil( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Ceil,SO>( ~sm, Ceil() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a matrix containing the complex conjugate of each single element of \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The complex conjugate of each single element of \a sm.
+//
+// The \a conj function calculates the complex conjugate of each element of the input matrix
+// \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a conj function:
+
+ \code
+ blaze::CompressedMatrix< complex<double> > A, B;
+ // ... Resizing and initialization
+ B = conj( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Conj,SO> conj( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Conj,SO>( ~sm, Conj() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the conjugate transpose matrix of \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The conjugate transpose of \a sm.
+//
+// The \a ctrans function returns an expression representing the conjugate transpose (also called
+// adjoint matrix, Hermitian conjugate matrix or transjugate matrix) of the given input matrix
+// \a sm.\n
+// The following example demonstrates the use of the \a ctrans function:
+
+ \code
+ blaze::CompressedMatrix< complex<double> > A, B;
+ // ... Resizing and initialization
+ B = ctrans( A );
+ \endcode
+
+// Note that the \a ctrans function has the same effect as manually applying the \a conj and
+// \a trans function in any order:
+
+ \code
+ B = trans( conj( A ) ); // Computing the conjugate transpose matrix
+ B = conj( trans( A ) ); // Computing the conjugate transpose matrix
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const CTransExprTrait_<MT> ctrans( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return trans( conj( ~sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a matrix containing the real parts of each single element of \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The real part of each single element of \a sm.
+//
+// The \a real function calculates the real part of each element of the input matrix \a sm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a real function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = real( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Real,SO> real( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Real,SO>( ~sm, Real() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a matrix containing the imaginary parts of each single element of \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The imaginary part of each single element of \a sm.
+//
+// The \a imag function calculates the imaginary part of each element of the input matrix \a sm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a imag function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = imag( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Imag,SO> imag( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Imag,SO>( ~sm, Imag() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the square root of each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[0..\infty)\f$.
+// \return The square root of each single element of \a sm.
+//
+// The \a sqrt() function computes the square root of each non-zero element of the input matrix
+// \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sqrt() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = sqrt( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Sqrt,SO> sqrt( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Sqrt,SO>( ~sm, Sqrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse square root of each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$(0..\infty)\f$.
+// \return The inverse square root of each single element of \a sm.
+//
+// The \a invsqrt() function computes the inverse square root of each non-zero element of the
+// input matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a invsqrt() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = invsqrt( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$(0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,InvSqrt,SO> invsqrt( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,InvSqrt,SO>( ~sm, InvSqrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the cubic root of each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[0..\infty)\f$.
+// \return The cubic root of each single element of \a sm.
+//
+// The \a cbrt() function computes the cubic root of each non-zero element of the input matrix
+// \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cbrt() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = cbrt( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Cbrt,SO> cbrt( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Cbrt,SO>( ~sm, Cbrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cubic root of each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$(0..\infty)\f$.
+// \return The inverse cubic root of each single element of \a sm.
+//
+// The \a invcbrt() function computes the inverse cubic root of each non-zero element of the
+// input matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a invcbrt() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = invcbrt( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$(0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,InvCbrt,SO> invcbrt( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,InvCbrt,SO>( ~sm, InvCbrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the exponential value for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \param exp The exponent.
+// \return The exponential value of each non-zero element of \a sm.
+//
+// The \a pow() function computes the exponential value for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a pow() function:
+
+ \code
+ blaze::DynamicMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = pow( A, 4.2 );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , typename ET > // Type of the exponent
+inline const SMatForEachExpr<MT,Pow<ET>,SO> pow( const SparseMatrix<MT,SO>& sm, ET exp )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET );
+
+ return SMatForEachExpr<MT,Pow<ET>,SO>( ~sm, Pow<ET>( exp ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes \f$ e^x \f$ for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The resulting sparse matrix.
+//
+// The \a exp() function computes \f$ e^x \f$ for each non-zero element of the input matrix \a sm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a exp() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = exp( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Exp,SO> exp( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Exp,SO>( ~sm, Exp() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the natural logarithm for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[0..\infty)\f$.
+// \return The natural logarithm of each non-zero element of \a sm.
+//
+// The \a log() function computes the natural logarithm for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a log() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = log( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Log,SO> log( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Log,SO>( ~sm, Log() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the common logarithm for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[0..\infty)\f$.
+// \return The common logarithm of each non-zero element of \a sm.
+//
+// The \a log10() function computes the common logarithm for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a log10() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = log10( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Log10,SO> log10( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Log10,SO>( ~sm, Log10() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the sine for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The sine of each non-zero element of \a sm.
+//
+// The \a sin() function computes the sine for each non-zero element of the input matrix \a sm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sin() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = sin( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Sin,SO> sin( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Sin,SO>( ~sm, Sin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse sine for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[-1..1]\f$.
+// \return The inverse sine of each non-zero element of \a sm.
+//
+// The \a asin() function computes the inverse sine for each non-zero element of the input matrix
+// \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a asin() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = asin( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[-1..1]\f$. No runtime checks
+// are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Asin,SO> asin( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Asin,SO>( ~sm, Asin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic sine for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The hyperbolic sine of each non-zero element of \a sm.
+//
+// The \a sinh() function computes the hyperbolic sine for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sinh() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = sinh( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Sinh,SO> sinh( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Sinh,SO>( ~sm, Sinh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic sine for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The inverse hyperbolic sine of each non-zero element of \a sm.
+//
+// The \a asinh() function computes the inverse hyperbolic sine for each non-zero element of
+// the input matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a asinh() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = asinh( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Asinh,SO> asinh( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Asinh,SO>( ~sm, Asinh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the cosine for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The cosine of each non-zero element of \a sm.
+//
+// The \a cos() function computes the cosine for each non-zero element of the input matrix
+// \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cos() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = cos( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Cos,SO> cos( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Cos,SO>( ~sm, Cos() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cosine for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[-1..1]\f$.
+// \return The inverse cosine of each non-zero element of \a sm.
+//
+// The \a acos() function computes the inverse cosine for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a acos() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = acos( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[-1..1]\f$. No runtime checks
+// are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Acos,SO> acos( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Acos,SO>( ~sm, Acos() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic cosine for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The hyperbolic cosine of each non-zero element of \a sm.
+//
+// The \a cosh() function computes the hyperbolic cosine for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cosh() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = cosh( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Cosh,SO> cosh( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Cosh,SO>( ~sm, Cosh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic cosine for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[1..\infty)\f$.
+// \return The inverse hyperbolic cosine of each non-zero element of \a sm.
+//
+// The \a acosh() function computes the inverse hyperbolic cosine for each non-zero element of
+// the input matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a acosh() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = acosh( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[1..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Acosh,SO> acosh( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Acosh,SO>( ~sm, Acosh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the tangent for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The tangent of each non-zero element of \a sm.
+//
+// The \a tan() function computes the tangent for each non-zero element of the input matrix \a sm.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a tan() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = tan( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Tan,SO> tan( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Tan,SO>( ~sm, Tan() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse tangent for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The inverse tangent of each non-zero element of \a sm.
+//
+// The \a atan() function computes the inverse tangent for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a atan() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = atan( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Atan,SO> atan( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Atan,SO>( ~sm, Atan() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic tangent for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[-1..1]\f$.
+// \return The hyperbolic tangent of each non-zero element of \a sm.
+//
+// The \a tanh() function computes the hyperbolic tangent for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a tanh() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = tanh( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[-1..1]\f$. No runtime checks
+// are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Tanh,SO> tanh( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Tanh,SO>( ~sm, Tanh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic tangent for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix; all non-zero elements must be in the range \f$[-1..1]\f$.
+// \return The inverse hyperbolic tangent of each non-zero element of \a sm.
+//
+// The \a atanh() function computes the inverse hyperbolic tangent for each non-zero element of
+// the input matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a atanh() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = atanh( A );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[-1..1]\f$. No runtime checks
+// are performed to assert this precondition!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Atanh,SO> atanh( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Atanh,SO>( ~sm, Atanh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the error function for each non-zero element of the sparse matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The error function of each non-zero element of \a sm.
+//
+// The \a erf() function computes the error function for each non-zero element of the input
+// matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a erf() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = erf( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Erf,SO> erf( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Erf,SO>( ~sm, Erf() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the complementary error function for each non-zero element of the sparse
+// matrix \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The complementary error function of each non-zero element of \a sm.
+//
+// The \a erfc() function computes the complementary error function for each non-zero element of
+// the input matrix \a sm. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a erfc() function:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = erfc( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Erfc,SO> erfc( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatForEachExpr<MT,Erfc,SO>( ~sm, Erfc() );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Absolute value function for absolute value sparse matrix expressions.
+// \ingroup sparse_matrix
+//
+// \param sm The absolute value sparse matrix expression.
+// \return The absolute value of each single element of \a sm.
+//
+// This function implements a performance optimized treatment of the absolute value operation
+// on a sparse matrix absolute value expression.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Abs,SO>& abs( const SMatForEachExpr<MT,Abs,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Applies the \a floor() function to a sparse matrix \a floor() expressions.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix \a floor() expression.
+// \return The resulting sparse matrix.
+//
+// This function implements a performance optimized treatment of the \a floor() operation on
+// a sparse matrix \a floor() expression.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Floor,SO>& floor( const SMatForEachExpr<MT,Floor,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Applies the \a ceil() function to a sparse matrix \a ceil() expressions.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix \a ceil() expression.
+// \return The resulting sparse matrix.
+//
+// This function implements a performance optimized treatment of the \a ceil() operation on
+// a sparse matrix \a ceil() expression.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Ceil,SO>& ceil( const SMatForEachExpr<MT,Ceil,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Complex conjugate function for complex conjugate sparse matrix expressions.
+// \ingroup sparse_matrix
+//
+// \param sm The complex conjugate sparse matrix expression.
+// \return The original sparse matrix.
+//
+// This function implements a performance optimized treatment of the complex conjugate operation
+// on a sparse matrix complex conjugate expression. It returns an expression representing the
+// original sparse matrix:
+
+ \code
+ blaze::CompressedMatrix< complex<double> > A, B;
+ // ... Resizing and initialization
+ B = conj( conj( A ) );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool TF > // Transpose flag
+inline typename SMatForEachExpr<MT,Conj,TF>::Operand conj( const SMatForEachExpr<MT,Conj,TF>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sm.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Complex conjugate function for conjugate transpose sparse matrix expressions.
+// \ingroup sparse_matrix
+//
+// \param dm The conjugate transpose sparse matrix expression.
+// \return The transpose sparse matrix.
+//
+// This function implements a performance optimized treatment of the complex conjugate operation
+// on a sparse matrix conjugate transpose expression. It returns an expression representing the
+// transpose of the sparse matrix:
+
+ \code
+ blaze::CompressedMatrix< complex<double> > A, B;
+ // ... Resizing and initialization
+ B = conj( ctrans( A ) );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatTransExpr<MT,!SO> conj( const SMatTransExpr<SMatForEachExpr<MT,Conj,SO>,!SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatTransExpr<MT,!SO>( sm.operand().operand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Real part function for real part sparse matrix expressions.
+// \ingroup sparse_matrix
+//
+// \param sm The real part sparse matrix expression.
+// \return The real part of each single element of \a sm.
+//
+// This function implements a performance optimized treatment of the real part operation on
+// a sparse matrix real part expression.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Real,SO>& real( const SMatForEachExpr<MT,Real,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Imaginary part function for imaginary part sparse matrix expressions.
+// \ingroup sparse_matrix
+//
+// \param sm The imaginary part sparse matrix expression.
+// \return The imaginary part of each single element of \a sm.
+//
+// This function implements a performance optimized treatment of the imaginary part operation
+// on a sparse matrix imaginary part expression.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatForEachExpr<MT,Imag,SO>& imag( const SMatForEachExpr<MT,Imag,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct Rows< SMatForEachExpr<MT,OP,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct Columns< SMatForEachExpr<MT,OP,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Abs,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Floor,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Ceil,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Conj,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Real,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Imag,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Sqrt,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,InvSqrt,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Cbrt,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,InvCbrt,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, typename ET, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Pow<ET>,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Exp,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Log,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Log10,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Sin,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Asin,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Sinh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Asinh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Cos,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Acos,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Cosh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Acosh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Tan,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Atan,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Tanh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Atanh,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Erf,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsSymmetric< SMatForEachExpr<MT,Erfc,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Abs,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Floor,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Ceil,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Conj,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Real,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Imag,SO> >
+ : public BoolConstant< IsBuiltin< ElementType_<MT> >::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Sqrt,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,InvSqrt,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Cbrt,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,InvCbrt,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, typename ET, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Pow<ET>,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Exp,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Log,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Log10,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Sin,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Asin,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Sinh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Asinh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Cos,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Acos,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Cosh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Acosh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Tan,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Atan,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Tanh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Atanh,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Erf,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+
+template< typename MT, bool SO >
+struct IsHermitian< SMatForEachExpr<MT,Erfc,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct IsLower< SMatForEachExpr<MT,OP,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ET, bool SO >
+struct IsUniLower< SMatForEachExpr<MT,Pow<ET>,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct IsStrictlyLower< SMatForEachExpr<MT,OP,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct IsUpper< SMatForEachExpr<MT,OP,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ET, bool SO >
+struct IsUniUpper< SMatForEachExpr<MT,Pow<ET>,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct IsStrictlyUpper< SMatForEachExpr<MT,OP,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct SMatForEachExprTrait< SMatForEachExpr<MT,Abs,false>, Abs >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatForEachExpr<MT,Abs,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TSMatForEachExprTrait< SMatForEachExpr<MT,Abs,true>, Abs >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatForEachExpr<MT,Abs,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct SMatForEachExprTrait< SMatForEachExpr<MT,Conj,false>, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , Operand_< SMatForEachExpr<MT,Conj,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TSMatForEachExprTrait< SMatForEachExpr<MT,Conj,true>, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , Operand_< SMatForEachExpr<MT,Conj,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct SMatForEachExprTrait< SMatTransExpr< SMatForEachExpr<MT,Conj,true>, false >, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatTransExpr<MT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TSMatForEachExprTrait< SMatTransExpr< SMatForEachExpr<MT,Conj,false>, true >, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatTransExpr<MT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct SMatForEachExprTrait< SMatForEachExpr<MT,Real,false>, Real >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatForEachExpr<MT,Real,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TSMatForEachExprTrait< SMatForEachExpr<MT,Real,true>, Real >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatForEachExpr<MT,Real,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO, bool AF >
+struct SubmatrixExprTrait< SMatForEachExpr<MT,OP,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = ForEachExprTrait_< SubmatrixExprTrait_<const MT,AF>, OP >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct RowExprTrait< SMatForEachExpr<MT,OP,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = ForEachExprTrait_< RowExprTrait_<const MT>, OP >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename OP, bool SO >
+struct ColumnExprTrait< SMatForEachExpr<MT,OP,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = ForEachExprTrait_< ColumnExprTrait_<const MT>, OP >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatSMatAddExpr.h b/src/cpu/blaze/math/expressions/SMatSMatAddExpr.h
new file mode 100644
index 00000000..d28a7ff9
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatSMatAddExpr.h
@@ -0,0 +1,1058 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatSMatAddExpr.h
+// \brief Header file for the sparse matrix/sparse matrix addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATSMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATSMATADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-sparse matrix additions.
+// \ingroup sparse_matrix_expression
+//
+// The SMatSMatAddExpr class represents the compile time expression for additions between
+// two row-major sparse matrices.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class SMatSMatAddExpr : public SparseMatrix< SMatSMatAddExpr<MT1,MT2>, false >
+ , private MatMatAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSymmetricKernel struct is a helper struct for the selection of the serial
+ evaluation strategy. In case the target matrix is column-major and both matrix
+ operands are symmetric, \a value is set to 1 and an optimized evaluation strategy
+ is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseSymmetricKernel {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( T1 );
+ enum : bool { value = IsSymmetric<T2>::value && IsSymmetric<T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = MT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatSMatAddExpr<MT1,MT2> This; //!< Type of this SMatSMatAddExpr instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatSMatAddExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the addition expression.
+ // \param rhs The right-hand side sparse matrix operand of the addition expression.
+ */
+ explicit inline SMatSMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the addition expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) + rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() + rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return lhs_.nonZeros(i) + rhs_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the addition expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix addition to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ assign( ~lhs, rhs.lhs_ );
+
+ if( !IsResizable< ElementType_<MT> >::value ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else
+ {
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
+ const RightIterator end( B.end(i) );
+ for( RightIterator element=B.begin(i); element!=end; ++element ) {
+ if( isDefault( (~lhs)(i,element->index()) ) )
+ (~lhs)(i,element->index()) = element->value();
+ else
+ (~lhs)(i,element->index()) += element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix addition to a row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix addition expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix addition
+ for( size_t i=0UL; i<(~lhs).rows(); ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( i, r->index(), r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( i, l->index(), l->value()+r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( i, r->index(), r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( i );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix addition to a column-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a sparse matrix-sparse matrix addition
+ // expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ const size_t m( A.rows() );
+ const size_t n( A.columns() );
+
+ // Counting the number of elements per column
+ std::vector<size_t> nonzeros( n, 0UL );
+ for( size_t i=0UL; i<m; ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ ++nonzeros[l->index()];
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ ++nonzeros[r->index()];
+ ++r;
+ }
+ else {
+ ++nonzeros[l->index()];
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ ++nonzeros[l->index()];
+ ++l;
+ }
+
+ while( r != rend ) {
+ ++nonzeros[r->index()];
+ ++r;
+ }
+ }
+
+ // Resizing the left-hand side sparse matrix
+ for( size_t j=0UL; j<n; ++j ) {
+ (~lhs).reserve( j, nonzeros[j] );
+ }
+
+ // Performing the matrix addition
+ for( size_t i=0UL; i<m; ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( i, r->index(), r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( i, l->index(), l->value()+r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( i, r->index(), r->value() );
+ ++r;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix addition to a column-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix addition expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) + trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-sparse matrix addition to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-sparse matrix addition to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-sparse matrix addition to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-sparse matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-sparse matrix addition to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-sparse matrix addition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of two row-major sparse matrices (\f$ A=B+C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix addition.
+// \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the addition of two row-major sparse matrices:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const SMatSMatAddExpr<T1,T2>
+ operator+( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatSMatAddExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatSMatAddExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatSMatAddExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< SMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< SMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >
+ , And< IsUniLower<MT2>, IsStrictlyLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >
+ , And< IsUniUpper<MT2>, IsStrictlyUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatSMatAddExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatSMatMultExpr.h b/src/cpu/blaze/math/expressions/SMatSMatMultExpr.h
new file mode 100644
index 00000000..23a69ae9
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatSMatMultExpr.h
@@ -0,0 +1,1433 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatSMatMultExpr.h
+// \brief Header file for the sparse matrix/sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/Infinity.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SMatSVecMultExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecSMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-sparse matrix multiplications.
+// \ingroup sparse_matrix_expression
+//
+// The SMatSMatMultExpr class represents the compile time expression for multiplications between
+// row-major sparse matrices.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class SMatSMatMultExpr : public SparseMatrix< SMatSMatMultExpr<MT1,MT2>, false >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateLeft = RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateRight = RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the target matrix is column-major and both matrix
+ operands are symmetric, \a value is set to 1 and an optimized evaluation strategy
+ is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsColumnMajorMatrix<T1>::value &&
+ IsSymmetric<T2>::value && IsSymmetric<T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation and in case no symmetry can be exploited, the nested \value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatSMatMultExpr<MT1,MT2> This; //!< Type of this SMatSMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatSMatMultExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the multiplication expression.
+ // \param rhs The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline SMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline constexpr size_t nonZeros() const noexcept {
+ return 0UL;
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const noexcept {
+ UNUSED_PARAMETER( i );
+ return 0UL;
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_SMATSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a sparse matrix-sparse matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the sparse matrix-sparse matrix
+ // multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t i=0UL; i<C.rows(); ++i ) {
+ const LeftIterator lend( A.end(i) );
+ for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
+ const RightIterator rend( B.end( lelem->index() ) );
+ for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
+ {
+ if( IsResizable< ElementType_<MT3> >::value &&
+ isDefault( C(i,relem->index()) ) ) {
+ C(i,relem->index()) = lelem->value() * relem->value();
+ }
+ else {
+ C(i,relem->index()) += lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix multiplication to a row-major sparse
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix multiplication expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // (Over-)Estimating the number of non-zero entries in the resulting matrix
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
+ const LeftIterator lend( A.end(i) );
+ for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
+ nonzeros += B.nonZeros( lelem->index() );
+ }
+ }
+
+ if( nonzeros > (~lhs).rows() * (~lhs).columns() ) {
+ nonzeros = (~lhs).rows() * (~lhs).columns();
+ }
+
+ (~lhs).reserve( nonzeros );
+ nonzeros = 0UL;
+
+ // Performing the matrix-matrix multiplication
+ std::vector<ElementType> values ( (~lhs).columns(), ElementType() );
+ std::vector<byte_t> valid ( (~lhs).columns(), 0 );
+ std::vector<size_t> indices( (~lhs).columns(), 0UL );
+ size_t minIndex( inf ), maxIndex( 0UL );
+
+ for( size_t i=0UL; i<(~lhs).rows(); ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem )
+ {
+ const RightIterator rend( B.end( lelem->index() ) );
+ for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
+ {
+ if( !valid[relem->index()] ) {
+ values[relem->index()] = lelem->value() * relem->value();
+ valid [relem->index()] = 1;
+ indices[nonzeros] = relem->index();
+ ++nonzeros;
+ if( relem->index() < minIndex ) minIndex = relem->index();
+ if( relem->index() > maxIndex ) maxIndex = relem->index();
+ }
+ else {
+ values[relem->index()] += lelem->value() * relem->value();
+ }
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( nonzeros <= (~lhs).columns(), "Invalid number of non-zero elements" );
+
+ if( nonzeros > 0UL )
+ {
+ BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
+
+ if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
+ {
+ std::sort( indices.begin(), indices.begin() + nonzeros );
+
+ for( size_t j=0UL; j<nonzeros; ++j )
+ {
+ const size_t index( indices[j] );
+ if( !isDefault( values[index] ) ) {
+ (~lhs).append( i, index, values[index] );
+ reset( values[index] );
+ }
+
+ reset( valid [index] );
+ }
+ }
+ else {
+ for( size_t j=minIndex; j<=maxIndex; ++j )
+ {
+ if( !isDefault( values[j] ) ) {
+ (~lhs).append( i, j, values[j] );
+ reset( values[j] );
+ }
+
+ reset( valid [j] );
+ }
+ }
+
+ nonzeros = 0UL;
+ minIndex = inf;
+ maxIndex = 0UL;
+ }
+
+ (~lhs).finalize( i );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix multiplication to a column-major sparse
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix multiplication expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+
+ const ResultType tmp( serial( rhs ) );
+ (~lhs).reserve( tmp.nonZeros() );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to column-major matrices*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a sparse matrix-sparse matrix multiplication to a
+ // column-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a sparse matrix-
+ // sparse matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-sparse matrix multiplication to a dense matrix
+ // (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matarix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a sparse matrix-sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the sparse matrix-sparse
+ // matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t i=0UL; i<C.rows(); ++i ) {
+ const LeftIterator lend( A.end(i) );
+ for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
+ const RightIterator rend( B.end( lelem->index() ) );
+ for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
+ C(i,relem->index()) += lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to column-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a sparse matrix-sparse matrix multiplication to
+ // a column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a sparse
+ // matrix-sparse matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-sparse matrix multiplication to a
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a sparse matrix-sparse matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the sparse matrix-
+ // sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t i=0UL; i<C.rows(); ++i ) {
+ const LeftIterator lend( A.end(i) );
+ for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
+ const RightIterator rend( B.end( lelem->index() ) );
+ for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
+ C(i,relem->index()) -= lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to column-major matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a sparse matrix-sparse matrix multiplication
+ // to a column-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a sparse
+ // matrix-sparse matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to matrices******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-sparse matrix multiplication to a matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-sparse
+ // matrix multiplication expression to a matrix. Due to the explicit application of the SFINAE
+ // principle this function can only be selected by the compiler in case either of the two
+ // matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to column-major matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a sparse matrix-sparse matrix multiplication to a
+ // column-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a sparse matrix-
+ // sparse matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-sparse matrix multiplication to a dense
+ // matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-sparse matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matarix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to column-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a sparse matrix-sparse matrix multiplication
+ // to a column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // sparse matrix-sparse matrix multiplication expression to a column-major matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-sparse matrix multiplication to a
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-sparse matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to column-major matrices***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a sparse matrix-sparse matrix
+ // multiplication to a column-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // sparse matrix-sparse matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of two row-major sparse matrices
+// (\f$ A=B*C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix multiplication.
+// \param rhs The right-hand side sparse matrix for the matrix multiplication.
+// \return The product of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the multiplication of two row-major sparse matrices:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const SMatSMatMultExpr<T1,T2>
+ operator*( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatSMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatSMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct SMatDVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , SMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct SMatSVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , SMatSVecMultExprTrait_< MT1, SMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecSMatMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TSVecSMatMultExprTrait_< TSVecSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatSMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatSMatSubExpr.h b/src/cpu/blaze/math/expressions/SMatSMatSubExpr.h
new file mode 100644
index 00000000..5e2dd7fa
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatSMatSubExpr.h
@@ -0,0 +1,1056 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatSMatSubExpr.h
+// \brief Header file for the sparse matrix/sparse matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATSMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATSMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-sparse matrix subtractions.
+// \ingroup sparse_matrix_expression
+//
+// The SMatSMatSubExpr class represents the compile time expression for subtractions between
+// sparse matrices.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class SMatSMatSubExpr : public SparseMatrix< SMatSMatSubExpr<MT1,MT2>, false >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< ReturnType type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< ReturnType type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSymmetricKernel struct is a helper struct for the selection of the serial
+ evaluation strategy. In case the target matrix is column-major and both matrix
+ operands are symmetric, \a value is set to 1 and an optimized evaluation strategy
+ is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseSymmetricKernel {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( T1 );
+ enum : bool { value = IsSymmetric<T2>::value && IsSymmetric<T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = MT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatSMatSubExpr<MT1,MT2> This; //!< Type of this SMatSMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatSMatSubExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the subtraction expression.
+ // \param rhs The right-hand side sparse matrix operand of the subtraction expression.
+ */
+ explicit inline SMatSMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() + rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return lhs_.nonZeros(i) + rhs_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ assign( ~lhs, rhs.lhs_ );
+
+ if( !IsResizable< ElementType_<MT> >::value ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else
+ {
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
+ const RightIterator end( B.end(i) );
+ for( RightIterator element=B.begin(i); element!=end; ++element ) {
+ if( isDefault( (~lhs)(i,element->index()) ) )
+ (~lhs)(i,element->index()) = -element->value();
+ else
+ (~lhs)(i,element->index()) -= element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix subtraction to a row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix subtraction expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix subtraction
+ for( size_t i=0UL; i<(~lhs).rows(); ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( i, r->index(), -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( i, l->index(), l->value()-r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( i, r->index(), -r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( i );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix subtraction to a column-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a sparse matrix-sparse matrix subtraction
+ // expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+
+ // Counting the number of elements per column
+ std::vector<size_t> nonzeros( n, 0UL );
+ for( size_t i=0UL; i<m; ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ ++nonzeros[l->index()];
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ ++nonzeros[r->index()];
+ ++r;
+ }
+ else {
+ ++nonzeros[l->index()];
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ ++nonzeros[l->index()];
+ ++l;
+ }
+
+ while( r != rend ) {
+ ++nonzeros[r->index()];
+ ++r;
+ }
+ }
+
+ // Resizing the left-hand side sparse matrix
+ for( size_t j=0UL; j<n; ++j ) {
+ (~lhs).reserve( j, nonzeros[j] );
+ }
+
+ // Performing the matrix subtraction
+ for( size_t i=0UL; i<m; ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( i, r->index(), -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( i, l->index(), l->value()-r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( i, r->index(), -r->value() );
+ ++r;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse matrix subtraction to a column-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // matrix subtraction expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) - trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-sparse matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-sparse matrix subtraction to a dense
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-sparse matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of two row-major sparse matrices (\f$ A=B-C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix subtraction.
+// \param rhs The right-hand side sparse matrix to be subtracted from the left-hand side matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the subtraction of two row-major sparse matrices:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const SMatSMatSubExpr<T1,T2>
+ operator-( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatSMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatSMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatSMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< SMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< SMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatSMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatSVecMultExpr.h b/src/cpu/blaze/math/expressions/SMatSVecMultExpr.h
new file mode 100644
index 00000000..44762924
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatSVecMultExpr.h
@@ -0,0 +1,1077 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatSVecMultExpr.h
+// \brief Header file for the sparse matrix/sparse vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-sparse vector multiplications.
+// \ingroup sparse_vector_expression
+//
+// The SMatSVecMultExpr class represents the compile time expression for multiplications
+// between row-major sparse matrices and sparse vectors.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename VT > // Type of the right-hand side sparse vector
+class SMatSVecMultExpr : public SparseVector< SMatSVecMultExpr<MT,VT>, false >
+ , private MatVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side sparse vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse vector expression.
+ enum : bool { evaluateVector = RequiresEvaluation<VT>::value || IsComputation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateMatrix || evaluateVector ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatSVecMultExpr<MT,VT> This; //!< Type of this SMatSVecMultExpr instance.
+ typedef MultTrait_<MRT,VRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the right-hand side sparse vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatSVecMultExpr class.
+ //
+ // \param mat The left-hand side sparse matrix operand of the multiplication expression.
+ // \param vec The right-hand side sparse vector operand of the multiplication expression.
+ */
+ explicit inline SMatSVecMultExpr( const MT& mat, const VT& vec ) noexcept
+ : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
+ , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
+ return row( mat_, index ) * vec_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns an estimation for the number of non-zero elements in the sparse vector.
+ //
+ // \return The estimate for the number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_SMATSVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand mat_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand vec_; //!< Right-hand side sparse vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Resetting the left-hand side target dense vector
+ reset( ~lhs );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ SMatSVecMultExpr::selectAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a sparse matrix-sparse vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the sparse matrix-sparse vector
+ // multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > MatrixIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > VectorIterator;
+
+ const VectorIterator vend( x.end() );
+
+ for( size_t i=0UL; i<y.size(); ++i )
+ {
+ const MatrixIterator mend ( A.end(i) );
+ MatrixIterator melem( A.begin(i) );
+
+ if( melem == mend ) continue;
+
+ VectorIterator velem( x.begin() );
+
+ while( true ) {
+ if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else {
+ y[i] = melem->value() * velem->value();
+ ++melem;
+ ++velem;
+ break;
+ }
+ }
+
+ if( melem != mend && velem != vend )
+ {
+ while( true ) {
+ if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else {
+ y[i] += melem->value() * velem->value();
+ ++melem;
+ if( melem == mend ) break;
+ ++velem;
+ if( velem == vend ) break;
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-sparse vector multiplication to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-sparse
+ // vector multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > MatrixIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > VectorIterator;
+
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side sparse vector operand
+ if( x.nonZeros() == 0UL ) return;
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ ElementType accu;
+ const VectorIterator vend( x.end() );
+
+ for( size_t i=0UL; i<(~lhs).size(); ++i )
+ {
+ const MatrixIterator mend ( A.end(i) );
+ MatrixIterator melem( A.begin(i) );
+
+ if( melem == mend ) continue;
+
+ VectorIterator velem( x.begin() );
+
+ reset( accu );
+
+ while( true ) {
+ if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else {
+ accu = melem->value() * velem->value();
+ ++melem;
+ ++velem;
+ break;
+ }
+ }
+
+ if( melem != mend && velem != vend )
+ {
+ while( true ) {
+ if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else {
+ accu += melem->value() * velem->value();
+ ++melem;
+ if( melem == mend ) break;
+ ++velem;
+ if( velem == vend ) break;
+ }
+ }
+ }
+
+ if( !isDefault( accu ) )
+ (~lhs).insert( i, accu );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ SMatSVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a sparse matrix-sparse vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the sparse matrix-sparse
+ // vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > MatrixIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > VectorIterator;
+
+ const VectorIterator vend( x.end() );
+
+ for( size_t i=0UL; i<y.size(); ++i )
+ {
+ const MatrixIterator mend ( A.end(i) );
+ MatrixIterator melem( A.begin(i) );
+
+ if( melem == mend ) continue;
+
+ VectorIterator velem( x.begin() );
+
+ while( true ) {
+ if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else {
+ y[i] += melem->value() * velem->value();
+ ++melem;
+ if( melem == mend ) break;
+ ++velem;
+ if( velem == vend ) break;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ SMatSVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a sparse matrix-sparse vector multiplication
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the sparse matrix-
+ // sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > MatrixIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > VectorIterator;
+
+ const VectorIterator vend( x.end() );
+
+ for( size_t i=0UL; i<y.size(); ++i )
+ {
+ const MatrixIterator mend ( A.end(i) );
+ MatrixIterator melem( A.begin(i) );
+
+ if( melem == mend ) continue;
+
+ VectorIterator velem( x.begin() );
+
+ while( true ) {
+ if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else {
+ y[i] -= melem->value() * velem->value();
+ ++melem;
+ if( melem == mend ) break;
+ ++velem;
+ if( velem == vend ) break;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse matrix-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // matrix-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-sparse
+ // vector multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Resetting the left-hand side target dense vector
+ reset( ~lhs );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ smpAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-sparse vector multiplication to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ smpAddAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-sparse vector multiplication to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ smpSubAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse matrix-sparse vector multiplication to a
+ // dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // sparse matrix-sparse vector multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR( MT, VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major sparse matrix and a
+// sparse vector (\f$ \vec{a}=B*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param mat The left-hand side sparse matrix for the multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator represents the multiplication between a row-major sparse matrix and a sparse
+// vector:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ blaze::CompressedMatrix<double,rowMajor> A;
+ blaze::CompressedVector<double,columnVector> x, y;
+ // ... Resizing and initialization
+ y = A * x;
+ \endcode
+
+// The operator returns an expression representing a sparse vector of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both the
+// sparse matrix type \a T1 and the sparse vector type \a T2 as well as the two element types
+// \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of columns
+// of the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const DisableIf_< Or< IsSymmetric<T1>, IsMatMatMultExpr<T1> >, SMatSVecMultExpr<T1,T2> >
+ operator*( const SparseMatrix<T1,false>& mat, const SparseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return SMatSVecMultExpr<T1,T2>( ~mat, ~vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a symmetric row-major sparse matrix
+// and a sparse vector (\f$ \vec{a}=B*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param mat The left-hand side sparse matrix for the multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// symmetric row-major sparse matrix and a sparse vector. It restructures the expression
+// \f$ \vec{y}=A*\vec{x} \f$ to the expression \f$ \vec{y}=A^T*\vec{x} \f$.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const EnableIf_< IsSymmetric<T1>, MultExprTrait_<T1,T2> >
+ operator*( const SparseMatrix<T1,false>& mat, const SparseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATMULTEXPR_TYPE( T1 );
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return trans( ~mat ) * (~vec);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-matrix
+// multiplication expression and a sparse vector (\f$ \vec{y}=(A*B)*\vec{x} \f$).
+// \ingroup sparse_vector
+//
+// \param mat The left-hand side sparse matrix-matrix multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The resulting vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a sparse
+// matrix-matrix multiplication expression and a sparse vector. It restructures the expression
+// \f$ \vec{y}=(A*B)*\vec{x} \f$ to the expression \f$ \vec{y}=A*(B*\vec{x}) \f$.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , bool SO // Storage order of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const EnableIf_< IsMatMatMultExpr<T1>, MultExprTrait_<T1,T2> >
+ operator*( const SparseMatrix<T1,SO>& mat, const SparseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( T1 );
+
+ return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct Size< SMatSVecMultExpr<MT,VT> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, bool AF >
+struct SubvectorExprTrait< SMatSVecMultExpr<MT,VT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>
+ , SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatScalarDivExpr.h b/src/cpu/blaze/math/expressions/SMatScalarDivExpr.h
new file mode 100644
index 00000000..9a81eb80
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatScalarDivExpr.h
@@ -0,0 +1,1201 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatScalarDivExpr.h
+// \brief Header file for the sparse matrix/scalar division expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSCALARDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatScalarDivExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMultExpr.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATSCALARDIVEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-scalar divisions.
+// \ingroup sparse_matrix_expression
+//
+// The SMatScalarMult class represents the compile time expression for divisions between
+// a sparse matrix and a scalar value.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST // Type of the right-hand side scalar value
+ , bool SO > // Storage order
+class SMatScalarDivExpr : public SparseMatrix< SMatScalarDivExpr<MT,ST,SO>, SO >
+ , private MatScalarDivExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the sparse matrix expression.
+ typedef ReturnType_<MT> RN; //!< Return type of the sparse matrix expression.
+ typedef CompositeType_<MT> CT; //!< Composite type of the sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If the matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef DivExprTrait_<RN,ST> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the division expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the division expression. In case the given sparse
+ matrix expression of type \a MT requires an intermediate evaluation, \a useAssign will
+ be set to 1 and the division expression will be evaluated via the \a assign function
+ family. Otherwise Otherwise \a useAssign will be set to 0 and the expression will be
+ evaluated via the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target matrix or the sparse matrix operand is not SMP
+ assignable and the matrix operand requires an intermediate evaluation, \a value is set
+ to 1 and the expression specific evaluation strategy is selected. Otherwise \a value is
+ set to 0 and the default strategy is chosen. */
+ template< typename MT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatScalarDivExpr<MT,ST,SO> This; //!< Type of this SMatScalarDivExpr instance.
+ typedef MultTrait_<RT,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SMatScalarDivExpr& > CompositeType;
+
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse matrix/scalar division expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse matrix expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse matrix expression.
+ typedef ConstIterator_< RemoveReference_<LeftOperand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType matrix, RightOperand scalar )
+ : matrix_( matrix ) // Iterator over the elements of the left-hand side sparse matrix expression
+ , scalar_( scalar ) // Right-hand side scalar of the division expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++matrix_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return The element at the current iterator position.
+ */
+ inline const Element operator*() const {
+ return Element( matrix_->value() / scalar_, matrix_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return Reference to the sparse matrix element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return matrix_->value() / scalar_;
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return matrix_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return matrix_ == rhs.matrix_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return matrix_ != rhs.matrix_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return matrix_ - rhs.matrix_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType matrix_; //!< Iterator over the elements of the left-hand side sparse matrix expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the division expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatScalarDivExpr class.
+ //
+ // \param matrix The left-hand side sparse matrix of the division expression.
+ // \param scalar The right-hand side scalar of the division expression.
+ */
+ explicit inline SMatScalarDivExpr( const MT& matrix, ST scalar ) noexcept
+ : matrix_( matrix ) // Left-hand side sparse matrix of the division expression
+ , scalar_( scalar ) // Right-hand side scalar of the division expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ return matrix_(i,j) / scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= matrix_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= matrix_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( matrix_.begin(i), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( matrix_.end(i), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return matrix_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return matrix_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return matrix_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return matrix_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific matrix element.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( matrix_.find( i, j ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( matrix_.lowerBound( i, j ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( matrix_.upperBound( i, j ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return matrix_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return matrix_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return matrix_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand matrix_; //!< Left-hand side sparse matrix of the division expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the division expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-scalar division to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-scalar
+ // division expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand
+ // requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.matrix_ );
+ (~lhs) /= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-scalar division to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-scalar
+ // division expression to a sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand
+ // requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( SparseMatrix<MT2,SO2>& lhs, const SMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.matrix_ );
+ (~lhs) /= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-scalar division to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse
+ // matrix-scalar division expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ addAssign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-scalar division to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // matrix-scalar division expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ subAssign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-scalar division to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-scalar division expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-scalar division to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-scalar division expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ElementType );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division operator for the division of a sparse matrix by a scalar value (\f$ A=B/s \f$).
+// \ingroup sparse_matrix
+//
+// \param mat The left-hand side sparse matrix for the division.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result matrix.
+//
+// This operator represents the division of a sparse matrix by a scalar value:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = A / 0.24;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the involved data types \a T1::ElementType and \a T2. Note that this operator only
+// works for scalar values of built-in data type.
+//
+// \note A division by zero is only checked by a user assert.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , bool SO // Storage order of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<T2>, DivExprTrait_<T1,T2> >
+ operator/( const SparseMatrix<T1,SO>& mat, T2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_USER_ASSERT( scalar != T2(0), "Division by zero detected" );
+
+ typedef DivExprTrait_<T1,T2> ReturnType;
+ typedef RightOperand_<ReturnType> ScalarType;
+
+ if( IsMultExpr<ReturnType>::value ) {
+ return ReturnType( ~mat, ScalarType(1)/ScalarType(scalar) );
+ }
+ else {
+ return ReturnType( ~mat, scalar );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar division
+// expression and a scalar value (\f$ A=(B/s1)*s2 \f$).
+// \ingroup sparse_matrix
+//
+// \param mat The left-hand side sparse matrix-scalar division.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// sparse matrix-scalar division expression and a scalar value.
+*/
+template< typename MT // Type of the sparse matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the sparse matrix
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< And< IsNumeric<ST2>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , MultExprTrait_< SMatScalarDivExpr<MT,ST1,SO>, ST2 > >
+ operator*( const SMatScalarDivExpr<MT,ST1,SO>& mat, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( scalar / mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a scalar value and a sparse matrix-
+// scalar division expression (\f$ A=s2*(B/s1) \f$).
+// \ingroup sparse_matrix
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param mat The right-hand side sparse matrix-scalar division.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// scalar value and a sparse matrix-scalar division expression.
+*/
+template< typename ST1 // Type of the left-hand side scalar
+ , typename MT // Type of the sparse matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the sparse matrix
+inline const EnableIf_< And< IsNumeric<ST1>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , MultExprTrait_< ST1, SMatScalarDivExpr<MT,ST2,SO> > >
+ operator*( ST1 scalar, const SMatScalarDivExpr<MT,ST2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( scalar / mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division operator for the division of a sparse matrix-scalar division expression
+// and a scalar value (\f$ A=(B/s1)/s2 \f$).
+// \ingroup sparse_matrix
+//
+// \param mat The left-hand side sparse matrix-scalar division.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the division of a sparse
+// matrix-scalar division expression and a scalar value.
+*/
+template< typename MT // Type of the sparse matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the sparse matrix
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<ST2>
+ , DivExprTrait_< MT, MultTrait_<ST1,ST2> > >
+ operator/( const SMatScalarDivExpr<MT,ST1,SO>& mat, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" );
+
+ typedef MultTrait_<ST1,ST2> MultType;
+ typedef DivExprTrait_<MT,MultType> ReturnType;
+ typedef RightOperand_<ReturnType> ScalarType;
+
+ if( IsMultExpr<ReturnType>::value ) {
+ return ReturnType( mat.leftOperand(), ScalarType(1)/( mat.rightOperand() * scalar ) );
+ }
+ else {
+ return ReturnType( mat.leftOperand(), mat.rightOperand() * scalar );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct Rows< SMatScalarDivExpr<MT,ST,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct Columns< SMatScalarDivExpr<MT,ST,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsSymmetric< SMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsHermitian< SMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsLower< SMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsStrictlyLower< SMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsUpper< SMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsStrictlyUpper< SMatScalarDivExpr<MT,ST,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct SMatScalarMultExprTrait< SMatScalarDivExpr<MT,ST1,false>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = DivTrait_<ST2,ST1>;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , SMatScalarMultExprTrait_<MT,ScalarType>
+ , SMatScalarMultExpr< SMatScalarDivExpr<MT,ST1,false>, ST2, false > >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct TSMatScalarMultExprTrait< SMatScalarDivExpr<MT,ST1,true>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = DivTrait_<ST2,ST1>;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , SMatScalarMultExprTrait_<MT,ScalarType>
+ , SMatScalarMultExpr< SMatScalarDivExpr<MT,ST1,true>, ST2, true > >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO, bool AF >
+struct SubmatrixExprTrait< SMatScalarDivExpr<MT,ST,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< SubmatrixExprTrait_<const MT,AF>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct RowExprTrait< SMatScalarDivExpr<MT,ST,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< RowExprTrait_<const MT>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct ColumnExprTrait< SMatScalarDivExpr<MT,ST,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< ColumnExprTrait_<const MT>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatScalarMultExpr.h b/src/cpu/blaze/math/expressions/SMatScalarMultExpr.h
new file mode 100644
index 00000000..0ddc9ad8
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatScalarMultExpr.h
@@ -0,0 +1,2540 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatScalarMultExpr.h
+// \brief Header file for the sparse matrix/scalar multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSCALARMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatScalarMultExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATSCALARMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-scalar multiplications.
+// \ingroup sparse_matrix_expression
+//
+// The SMatScalarMult class represents the compile time expression for multiplications between
+// a sparse matrix and a scalar value.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST // Type of the right-hand side scalar value
+ , bool SO > // Storage order
+class SMatScalarMultExpr : public SparseMatrix< SMatScalarMultExpr<MT,ST,SO>, SO >
+ , private MatScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the sparse matrix expression.
+ typedef ReturnType_<MT> RN; //!< Return type of the sparse matrix expression.
+ typedef CompositeType_<MT> CT; //!< Composite type of the sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If the matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN,ST> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the multiplication expression. In case the given sparse
+ matrix expression of type \a MT requires an intermediate evaluation, \a useAssign will be
+ set to 1 and the multiplication expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to 0 and the expression will be evaluated
+ via the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target matrix or the sparse matrix operand is not SMP
+ assignable and the matrix operand requires an intermediate evaluation, \a value is set
+ to 1 and the expression specific evaluation strategy is selected. Otherwise \a value is
+ set to 0 and the default strategy is chosen. */
+ template< typename MT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatScalarMultExpr<MT,ST,SO> This; //!< Type of this SMatScalarMultExpr instance.
+ typedef MultTrait_<RT,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SMatScalarMultExpr& > CompositeType;
+
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse matrix/scalar multiplication expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse matrix expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse matrix expression.
+ typedef ConstIterator_< RemoveReference_<LeftOperand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType matrix, RightOperand scalar )
+ : matrix_( matrix ) // Iterator over the elements of the left-hand side sparse matrix expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++matrix_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return The element at the current iterator position.
+ */
+ inline const Element operator*() const {
+ return Element( matrix_->value() * scalar_, matrix_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return Reference to the sparse matrix element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return matrix_->value() * scalar_;
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return matrix_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return matrix_ == rhs.matrix_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return matrix_ != rhs.matrix_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return matrix_ - rhs.matrix_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType matrix_; //!< Iterator over the elements of the left-hand side sparse matrix expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatScalarMultExpr class.
+ //
+ // \param matrix The left-hand side sparse matrix of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline SMatScalarMultExpr( const MT& matrix, ST scalar ) noexcept
+ : matrix_( matrix ) // Left-hand side sparse matrix of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ return matrix_(i,j) * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= matrix_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= matrix_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of row \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( matrix_.begin(i), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of row \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( matrix_.end(i), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return matrix_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return matrix_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return matrix_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return matrix_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific matrix element.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( matrix_.find( i, j ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( matrix_.lowerBound( i, j ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return ConstIterator( matrix_.upperBound( i, j ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return matrix_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return matrix_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return matrix_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand matrix_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-scalar multiplication to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-scalar
+ // multiplication expression to a dense matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand requires
+ // an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.matrix_ );
+ (~lhs) *= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-scalar multiplication to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-scalar
+ // multiplication expression to a sparse matrix. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand requires
+ // an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( SparseMatrix<MT2,SO2>& lhs, const SMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.matrix_ );
+ (~lhs) *= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-scalar multiplication to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // scalar multiplication expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the operand
+ // requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ addAssign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-scalar multiplication to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // scalar multiplication expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the operand
+ // requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ subAssign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-scalar multiplication to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-scalar multiplication expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-scalar multiplication to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-scalar multiplication expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const SMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL UNARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unary minus operator for the negation of a sparse matrix (\f$ A = -B \f$).
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be negated.
+// \return The negation of the matrix.
+//
+// This operator represents the negation of a sparse matrix:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = -A;
+ \endcode
+
+// The operator returns an expression representing the negation of the given sparse matrix.
+*/
+template< typename MT // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatScalarMultExpr<MT,UnderlyingBuiltin_<MT>,SO>
+ operator-( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef UnderlyingBuiltin_<MT> ElementType;
+ return SMatScalarMultExpr<MT,ElementType,SO>( ~sm, ElementType(-1) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a sparse matrix and a scalar value
+// (\f$ A=B*s \f$).
+// \ingroup sparse_matrix
+//
+// \param mat The left-hand side sparse matrix for the multiplication.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result matrix.
+//
+// This operator represents the multiplication between a sparse matrix and a scalar value:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = A * 1.25;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the involved data types \a T1::ElementType and \a T2. Note that this operator only
+// works for scalar values of built-in data type.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , bool SO // Storage order of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<T2>, MultExprTrait_<T1,T2> >
+ operator*( const SparseMatrix<T1,SO>& mat, T2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return MultExprTrait_<T1,T2>( ~mat, scalar );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a scalar value and a sparse matrix
+// (\f$ A=s*B \f$).
+// \ingroup sparse_matrix
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param mat The right-hand side sparse matrix for the multiplication.
+// \return The scaled result matrix.
+//
+// This operator represents the multiplication between a scalar value and a sparse matrix:
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = 1.25 * A;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the involved data types \a T1::ElementType and \a T2. Note that this operator only
+// works for scalar values of built-in data type.
+*/
+template< typename T1 // Type of the left-hand side scalar
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline const EnableIf_< IsNumeric<T1>, MultExprTrait_<T1,T2> >
+ operator*( T1 scalar, const SparseMatrix<T2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return MultExprTrait_<T1,T2>( ~mat, scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING UNARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unary minus operator for the negation of a sparse matrix-scalar multiplication
+// (\f$ A = -(B*s) \f$).
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix-scalar multiplication to be negated.
+// \return The negation of the sparse matrix-scalar multiplication.
+//
+// This operator implements a performance optimized treatment of the negation of a sparse matrix-
+// scalar multiplication expression.
+*/
+template< typename VT // Type of the sparse matrix
+ , typename ST // Type of the scalar
+ , bool TF > // Transpose flag
+inline const SMatScalarMultExpr<VT,ST,TF>
+ operator-( const SMatScalarMultExpr<VT,ST,TF>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatScalarMultExpr<VT,ST,TF>( sm.leftOperand(), -sm.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar multiplication
+// expression and a scalar value (\f$ A=(B*s1)*s2 \f$).
+// \ingroup sparse_matrix
+//
+// \param mat The left-hand side sparse matrix-scalar multiplication.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// sparse matrix-scalar multiplication expression and a scalar value.
+*/
+template< typename MT // Type of the sparse matrix
+ , typename ST1 // Type of the first scalar
+ , bool SO // Storage order of the sparse matrix
+ , typename ST2 > // Type of the second scalar
+inline const EnableIf_< IsNumeric<ST2>
+ , MultExprTrait_< SMatScalarMultExpr<MT,ST1,SO>, ST2 > >
+ operator*( const SMatScalarMultExpr<MT,ST1,SO>& mat, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( mat.rightOperand() * scalar );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar multiplication
+// expression and a scalar value (\f$ A=s2*(B*s1) \f$).
+// \ingroup sparse_matrix
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param mat The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// scalar value and a sparse matrix-scalar multiplication expression.
+*/
+template< typename ST1 // Type of the first scalar
+ , typename MT // Type of the sparse matrix
+ , typename ST2 // Type of the second scalar
+ , bool SO > // Storage order of the sparse matrix
+inline const EnableIf_< IsNumeric<ST1>
+ , MultExprTrait_< ST1, SMatScalarMultExpr<MT,ST2,SO> > >
+ operator*( ST1 scalar, const SMatScalarMultExpr<MT,ST2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( scalar * mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division operator for the division of a sparse matrix-scalar multiplication
+// expression by a scalar value (\f$ A=(B*s1)/s2 \f$).
+// \ingroup sparse_matrix
+//
+// \param mat The left-hand side sparse matrix-scalar multiplication.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result matrix.
+//
+// This operator implements a performance optimized treatment of the division of a
+// sparse matrix-scalar multiplication expression by a scalar value.
+*/
+template< typename MT // Type of the sparse matrix
+ , typename ST1 // Type of the first scalar
+ , bool SO // Storage order of the sparse matrix
+ , typename ST2 > // Type of the second scalar
+inline const EnableIf_< And< IsNumeric<ST2>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , DivExprTrait_< SMatScalarMultExpr<MT,ST1,SO>, ST2 > >
+ operator/( const SMatScalarMultExpr<MT,ST1,SO>& mat, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return mat.leftOperand() * ( mat.rightOperand() / scalar );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar
+// multiplication expression and a dense vector (\f$ \vec{a}=(B*s1)*\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side sparse matrix-scalar multiplication.
+// \param vec The right-hand side dense vector.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse matrix-scalar multiplication and a dense vector. It restructures the expression
+// \f$ \vec{a}=(B*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
+*/
+template< typename MT // Type of the sparse matrix of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the left-hand side expression
+ , typename VT > // Type of the right-hand side dense vector
+inline const MultExprTrait_< SMatScalarMultExpr<MT,ST,SO>, VT >
+ operator*( const SMatScalarMultExpr<MT,ST,SO>& mat, const DenseVector<VT,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * (~vec) ) * mat.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector and a sparse
+// matrix-scalar multiplication expression (\f$ \vec{a}^T=\vec{c}^T*(B*s1) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector.
+// \param mat The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense vector and a sparse matrix-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=\vec{c}^T*(B*s1) \f$ to the expression \f$ \vec{a}^T=(\vec{c}^T*B)*s1 \f$.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename MT // Type of the sparse matrix of the right-hand side expression
+ , typename ST // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the right-hand side expression
+inline const MultExprTrait_< VT, SMatScalarMultExpr<MT,ST,SO> >
+ operator*( const DenseVector<VT,true>& vec, const SMatScalarMultExpr<MT,ST,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~vec) * mat.leftOperand() ) * mat.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar
+// multiplication expression and a dense vector-scalar multiplication expression
+// (\f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side sparse matrix-scalar multiplication.
+// \param vec The right-hand side dense vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a sparse matrix-scalar multiplication and a dense vector-scalar multiplication. It
+// restructures the expression \f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$ to the expression
+// \f$ \vec{a}=(B*\vec{c})*(s1*s2) \f$.
+*/
+template< typename MT // Type of the sparse matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the left-hand side expression
+ , typename VT // Type of the dense vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< SMatScalarMultExpr<MT,ST1,SO>, DVecScalarMultExpr<VT,ST2,false> >
+ operator*( const SMatScalarMultExpr<MT,ST1,SO>& mat, const DVecScalarMultExpr<VT,ST2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * vec.leftOperand() ) * ( mat.rightOperand() * vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector-scalar
+// multiplication expression and a sparse matrix-scalar multiplication expression
+// (\f$ \vec{a}^T=\vec{b}^T*(C*s1) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector-scalar multiplication.
+// \param mat The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a dense vector-scalar multiplication and a sparse matrix-scalar multiplication. It
+// restructures the expression \f$ \vec{a}=(\vec{b}^T*s1)*(C*s2) \f$ to the expression
+// \f$ \vec{a}^T=(\vec{b}^T*C)*(s1*s2) \f$.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , typename MT // Type of the sparse matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the right-hand side expression
+inline const MultExprTrait_< DVecScalarMultExpr<VT,ST1,true>, SMatScalarMultExpr<MT,ST2,SO> >
+ operator*( const DVecScalarMultExpr<VT,ST1,true>& vec, const SMatScalarMultExpr<MT,ST2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( vec.leftOperand() * mat.leftOperand() ) * ( vec.rightOperand() * mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar
+// multiplication expression and a sparse vector (\f$ \vec{a}=(B*s1)*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param mat The left-hand side sparse matrix-scalar multiplication.
+// \param vec The right-hand side sparse vector.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse matrix-scalar multiplication and a sparse vector. It restructures the expression
+// \f$ \vec{a}=(B*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
+*/
+template< typename MT // Type of the sparse matrix of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the left-hand side expression
+ , typename VT > // Type of the right-hand side sparse vector
+inline const MultExprTrait_< SMatScalarMultExpr<MT,ST,SO>, VT >
+ operator*( const SMatScalarMultExpr<MT,ST,SO>& mat, const SparseVector<VT,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * (~vec) ) * mat.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector and a sparse
+// matrix-scalar multiplication expression (\f$ \vec{a}^T=\vec{c}^T*(B*s1) \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side sparse vector.
+// \param mat The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse vector and a sparse matrix-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=\vec{c}^T*(B*s1) \f$ to the expression \f$ \vec{a}^T=(\vec{c}^T*B)*s1 \f$.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename MT // Type of the sparse matrix of the right-hand side expression
+ , typename ST // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the right-hand side expression
+inline const MultExprTrait_< VT, SMatScalarMultExpr<MT,ST,SO> >
+ operator*( const SparseVector<VT,true>& vec, const SMatScalarMultExpr<MT,ST,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~vec) * mat.leftOperand() ) * mat.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar
+// multiplication expression and a sparse vector-scalar multiplication expression
+// (\f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$).
+// \ingroup sparse_vector
+//
+// \param mat The left-hand side sparse matrix-scalar multiplication.
+// \param vec The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a sparse matrix-scalar multiplication and a sparse vector-scalar multiplication. It
+// restructures the expression \f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$ to the expression
+// \f$ \vec{a}=(B*\vec{c})*(s1*s2) \f$.
+*/
+template< typename MT // Type of the sparse matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO // Storage order of the left-hand side expression
+ , typename VT // Type of the sparse vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< SMatScalarMultExpr<MT,ST1,SO>, SVecScalarMultExpr<VT,ST2,false> >
+ operator*( const SMatScalarMultExpr<MT,ST1,SO>& mat, const SVecScalarMultExpr<VT,ST2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( mat.leftOperand() * vec.leftOperand() ) * ( mat.rightOperand() * vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector-scalar
+// multiplication expression and a sparse matrix-scalar multiplication expression
+// (\f$ \vec{a}^T=\vec{b}^T*(C*s1) \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side sparse vector-scalar multiplication.
+// \param mat The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication
+// of a sparse vector-scalar multiplication and a sparse matrix-scalar multiplication. It
+// restructures the expression \f$ \vec{a}=(\vec{b}^T*s1)*(C*s2) \f$ to the expression
+// \f$ \vec{a}^T=(\vec{b}^T*C)*(s1*s2) \f$.
+*/
+template< typename VT // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , typename MT // Type of the sparse matrix of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO > // Storage order of the right-hand side expression
+inline const MultExprTrait_< SVecScalarMultExpr<VT,ST1,true>, SMatScalarMultExpr<MT,ST2,SO> >
+ operator*( const SVecScalarMultExpr<VT,ST1,true>& vec, const SMatScalarMultExpr<MT,ST2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( vec.leftOperand() * mat.leftOperand() ) * ( vec.rightOperand() * mat.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar multiplication
+// expression and a dense matrix (\f$ A=(B*s1)*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix-scalar multiplication.
+// \param rhs The right-hand side dense matrix.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse matrix-scalar multiplication and a dense matrix. It restructures the expression
+// \f$ A=(B*s1)*C \f$ to the expression \f$ A=(B*C)*s1 \f$.
+*/
+template< typename MT1 // Type of the sparse matrix of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename MT2 // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline const MultExprTrait_< SMatScalarMultExpr<MT1,ST,SO1>, MT2 >
+ operator*( const SMatScalarMultExpr<MT1,ST,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix and a sparse matrix-
+// scalar multiplication expression (\f$ A=(B*s1)*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix.
+// \param rhs The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense matrix and a sparse matrix-scalar multiplication. It restructures the expression
+// \f$ A=B*(C*s1) \f$ to the expression \f$ A=(B*C)*s1 \f$.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the sparse matrix of the right-hand side expression
+ , typename ST // Type of the scalar of the right-hand side expression
+ , bool SO2 > // Storage order of the right-hand side expression
+inline const MultExprTrait_< MT1, SMatScalarMultExpr<MT2,ST,SO2> >
+ operator*( const DenseMatrix<MT1,SO1>& lhs, const SMatScalarMultExpr<MT2,ST,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix-scalar multiplication
+// expression and a sparse matrix (\f$ A=(B*s1)*C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix-scalar multiplication.
+// \param rhs The right-hand side sparse matrix.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse matrix-scalar multiplication and a sparse matrix. It restructures the expression
+// \f$ A=(B*s1)*C \f$ to the expression \f$ A=(B*C)*s1 \f$.
+*/
+template< typename MT1 // Type of the sparse matrix of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename MT2 // Type of the right-hand side sparse matrix
+ , bool SO2 > // Storage order of the right-hand side sparse matrix
+inline const MultExprTrait_< SMatScalarMultExpr<MT1,ST,SO1>, MT2 >
+ operator*( const SMatScalarMultExpr<MT1,ST,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix and a sparse matrix-
+// scalar multiplication expression (\f$ A=(B*s1)*C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix.
+// \param rhs The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse matrix and a sparse matrix-scalar multiplication. It restructures the expression
+// \f$ A=B*(C*s1) \f$ to the expression \f$ A=(B*C)*s1 \f$.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , bool SO1 // Storage order of the left-hand side sparse matrix
+ , typename MT2 // Type of the sparse matrix of the right-hand side expression
+ , typename ST // Type of the scalar of the right-hand side expression
+ , bool SO2 > // Storage order of the right-hand side expression
+inline const MultExprTrait_< MT1, SMatScalarMultExpr<MT2,ST,SO2> >
+ operator*( const SparseMatrix<MT1,SO1>& lhs, const SMatScalarMultExpr<MT2,ST,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of two sparse matrix-scalar
+// multiplication expressions (\f$ A=(B*s1)*(C*s2) \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix-scalar multiplication.
+// \param rhs The right-hand side sparse matrix-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the multiplication of
+// two sparse matrix-scalar multiplication expressions. It restructures the expression
+// \f$ A=(B*s1)*(C*s2) \f$ to the expression \f$ A=(B*C)*(s1*s2) \f$.
+*/
+template< typename MT1 // Type of the sparse matrix of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool SO1 // Storage order of the left-hand side expression
+ , typename MT2 // Type of the right-hand side sparse matrix
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool SO2 > // Storage order of the right-hand side expression
+inline const MultExprTrait_< SMatScalarMultExpr<MT1,ST1,SO1>, SMatScalarMultExpr<MT2,ST2,SO2> >
+ operator*( const SMatScalarMultExpr<MT1,ST1,SO1>& lhs, const SMatScalarMultExpr<MT2,ST2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct Rows< SMatScalarMultExpr<MT,ST,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct Columns< SMatScalarMultExpr<MT,ST,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsSymmetric< SMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsHermitian< SMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsLower< SMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsStrictlyLower< SMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsUpper< SMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct IsStrictlyUpper< SMatScalarMultExpr<MT,ST,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct SMatScalarMultExprTrait< SMatScalarMultExpr<MT,ST1,false>, ST2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SMatScalarMultExprTrait_< MT, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct TSMatScalarMultExprTrait< SMatScalarMultExpr<MT,ST1,true>, ST2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSMatScalarMultExprTrait_< MT, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATSCALARDIVEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct SMatScalarDivExprTrait< SMatScalarMultExpr<MT,ST1,false>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = DivTrait_<ST1,ST2>;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , SMatScalarMultExprTrait_<MT,ScalarType>
+ , SMatScalarDivExprTrait_<MT,ScalarType> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATSCALARDIVEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename ST2 >
+struct TSMatScalarDivExprTrait< SMatScalarMultExpr<MT,ST1,true>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = DivTrait_<ST1,ST2>;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , TSMatScalarMultExprTrait_<MT,ScalarType>
+ , TSMatScalarDivExprTrait_<MT,ScalarType> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, typename VT >
+struct SMatDVecMultExprTrait< SMatScalarMultExpr<MT,ST,false>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< SMatDVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename VT, typename ST2 >
+struct SMatDVecMultExprTrait< SMatScalarMultExpr<MT,ST1,false>, DVecScalarMultExpr<VT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DVecScalarMultExprTrait_< SMatDVecMultExprTrait_<MT,VT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, typename VT >
+struct TSMatDVecMultExprTrait< SMatScalarMultExpr<MT,ST,true>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< TSMatDVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename VT, typename ST2 >
+struct TSMatDVecMultExprTrait< SMatScalarMultExpr<MT,ST1,true>, DVecScalarMultExpr<VT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , DVecScalarMultExprTrait_< TSMatDVecMultExprTrait_<MT,VT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TDVecSMatMultExprTrait< VT, SMatScalarMultExpr<MT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename MT, typename ST2 >
+struct TDVecSMatMultExprTrait< DVecScalarMultExpr<VT,ST1,true>, SMatScalarMultExpr<MT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDVecScalarMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TDVecTSMatMultExprTrait< VT, SMatScalarMultExpr<MT,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename MT, typename ST2 >
+struct TDVecTSMatMultExprTrait< DVecScalarMultExpr<VT,ST1,true>, SMatScalarMultExpr<MT,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TDVecScalarMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, typename VT >
+struct SMatSVecMultExprTrait< SMatScalarMultExpr<MT,ST,false>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< SMatSVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename VT, typename ST2 >
+struct SMatSVecMultExprTrait< SMatScalarMultExpr<MT,ST1,false>, SVecScalarMultExpr<VT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SVecScalarMultExprTrait_< SMatSVecMultExprTrait_<MT,VT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, typename VT >
+struct TSMatSVecMultExprTrait< SMatScalarMultExpr<MT,ST,true>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< TSMatSVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST1, typename VT, typename ST2 >
+struct TSMatSVecMultExprTrait< SMatScalarMultExpr<MT,ST1,true>, SVecScalarMultExpr<VT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SVecScalarMultExprTrait_< TSMatSVecMultExprTrait_<MT,VT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TSVecSMatMultExprTrait< VT, SMatScalarMultExpr<MT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TSVecSMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename MT, typename ST2 >
+struct TSVecSMatMultExprTrait< SVecScalarMultExpr<VT,ST1,true>, SMatScalarMultExpr<MT,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSVecScalarMultExprTrait_< TSVecSMatMultExprTrait_<VT,MT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, typename ST >
+struct TSVecTSMatMultExprTrait< VT, SMatScalarMultExpr<MT,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TSVecTSMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename MT, typename ST2 >
+struct TSVecTSMatMultExprTrait< SVecScalarMultExpr<VT,ST1,true>, SMatScalarMultExpr<MT,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSVecScalarMultExprTrait_< TSVecTSMatMultExprTrait_<VT,MT>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct DMatSMatMultExprTrait< MT1, SMatScalarMultExpr<MT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DMatSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct DMatTSMatMultExprTrait< MT1, SMatScalarMultExpr<MT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< DMatTSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct TDMatSMatMultExprTrait< MT1, SMatScalarMultExpr<MT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TDMatSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct TDMatTSMatMultExprTrait< MT1, SMatScalarMultExpr<MT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TDMatTSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct SMatDMatMultExprTrait< SMatScalarMultExpr<MT1,ST,false>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< SMatDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct SMatTDMatMultExprTrait< SMatScalarMultExpr<MT1,ST,false>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , DMatScalarMultExprTrait_< SMatTDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TSMatDMatMultExprTrait< SMatScalarMultExpr<MT1,ST,true>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TSMatDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TSMatTDMatMultExprTrait< SMatScalarMultExpr<MT1,ST,true>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TDMatScalarMultExprTrait_< TSMatTDMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct SMatSMatMultExprTrait< SMatScalarMultExpr<MT1,ST,false>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , SMatScalarMultExprTrait_< SMatSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct SMatSMatMultExprTrait< MT1, SMatScalarMultExpr<MT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , SMatScalarMultExprTrait_< SMatSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct SMatSMatMultExprTrait< SMatScalarMultExpr<MT1,ST1,false>, SMatScalarMultExpr<MT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SMatScalarMultExprTrait_< SMatSMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct SMatTSMatMultExprTrait< SMatScalarMultExpr<MT1,ST,false>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , SMatScalarMultExprTrait_< SMatTSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct SMatTSMatMultExprTrait< MT1, SMatScalarMultExpr<MT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , SMatScalarMultExprTrait_< SMatTSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct SMatTSMatMultExprTrait< SMatScalarMultExpr<MT1,ST1,false>, SMatScalarMultExpr<MT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SMatScalarMultExprTrait_< SMatTSMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TSMatSMatMultExprTrait< SMatScalarMultExpr<MT1,ST,true>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TSMatScalarMultExprTrait_< TSMatSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct TSMatSMatMultExprTrait< MT1, SMatScalarMultExpr<MT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TSMatScalarMultExprTrait_< TSMatSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct TSMatSMatMultExprTrait< SMatScalarMultExpr<MT1,ST1,true>, SMatScalarMultExpr<MT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSMatScalarMultExprTrait_< TSMatSMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST, typename MT2 >
+struct TSMatTSMatMultExprTrait< SMatScalarMultExpr<MT1,ST,true>, MT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TSMatScalarMultExprTrait_< TSMatTSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename ST >
+struct TSMatTSMatMultExprTrait< MT1, SMatScalarMultExpr<MT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST> >
+ , TSMatScalarMultExprTrait_< TSMatTSMatMultExprTrait_<MT1,MT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename ST1, typename MT2, typename ST2 >
+struct TSMatTSMatMultExprTrait< SMatScalarMultExpr<MT1,ST1,true>, SMatScalarMultExpr<MT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSMatScalarMultExprTrait_< TSMatTSMatMultExprTrait_<MT1,MT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO, bool AF >
+struct SubmatrixExprTrait< SMatScalarMultExpr<MT,ST,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct RowExprTrait< SMatScalarMultExpr<MT,ST,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename ST, bool SO >
+struct ColumnExprTrait< SMatScalarMultExpr<MT,ST,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< ColumnExprTrait_<const MT>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatSerialExpr.h b/src/cpu/blaze/math/expressions/SMatSerialExpr.h
new file mode 100644
index 00000000..49b61237
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatSerialExpr.h
@@ -0,0 +1,1029 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatSerialExpr.h
+// \brief Header file for the sparse matrix serial evaluation expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSERIALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatSerialExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/SerialExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatSerialExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TSMatSerialExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATSERIALEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the forced serial evaluation of sparse matrices.
+// \ingroup sparse_matrix_expression
+//
+// The SMatSerialExpr class represents the compile time expression for the forced serial
+// evaluation of a sparse matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+class SMatSerialExpr : public SparseMatrix< SMatSerialExpr<MT,SO>, SO >
+ , private MatSerialExpr
+ , private Computation
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatSerialExpr<MT,SO> This; //!< Type of this SMatSerialExpr instance.
+ typedef ResultType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatSerialExpr class.
+ //
+ // \param sm The sparse matrix operand of the serial evaluation expression.
+ */
+ explicit inline SMatSerialExpr( const MT& sm ) noexcept
+ : sm_( sm ) // Sparse matrix of the serial evaluation expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < sm_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < sm_.columns(), "Invalid column access index" );
+ return sm_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= sm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= sm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return sm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return sm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return sm_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return sm_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the sparse matrix operand.
+ //
+ // \return The sparse matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return sm_;
+ }
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\brief Conversion to the type of the sparse matrix operand.
+ //
+ // \return The sparse matrix operand.
+ */
+ inline operator Operand() const noexcept {
+ return sm_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return sm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return sm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return sm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand sm_; //!< Sparse matrix of the serial evaluation expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix serial evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix serial
+ // evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix serial evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluatin expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix serial
+ // evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix serial evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix
+ // serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix serial evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix
+ // serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void addAssign( SparseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix serial evaluation expression to a dense
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix
+ // serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix serial evaluation expression to a sparse
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void subAssign( SparseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse matrix serial evaluation expression to a dense
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // matrix serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void multAssign( DenseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse matrix serial evaluation expression to a sparse
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void multAssign( SparseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix serial evaluation expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix
+ // serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAssign( DenseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix serial evaluation expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluatin expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix
+ // serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpAssign( SparseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix serial evaluation expression to a dense
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix serial evaluation expression to a sparse
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpAddAssign( SparseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix serial evaluation expression to a dense
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix serial evaluation expression to a sparse
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpSubAssign( SparseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse matrix serial evaluation expression to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // matrix serial evaluation expression to a dense matrix.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void smpMultAssign( DenseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse matrix serial evaluation expression to a
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // matrix serial evaluation expression to a sparse matrix.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void smpMultAssign( SparseMatrix<MT2,SO2>& lhs, const SMatSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Forces the serial evaluation of the given sparse matrix expression \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input matrix.
+// \return The evaluated sparse matrix.
+//
+// The \a serial function forces the serial evaluation of the given sparse matrix expression
+// \a sm. The function returns an expression representing the operation.\n
+// The following example demonstrates the use of the \a serial function
+
+ \code
+ blaze::CompressedMatrix<double> A, B;
+ // ... Resizing and initialization
+ B = serial( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatSerialExpr<MT,SO> serial( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatSerialExpr<MT,SO>( ~sm );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Evaluation of the given sparse matrix serial evaluation expression \a sm.
+// \ingroup sparse_matrix
+//
+// \param sm The input serial evaluation expression.
+// \return The evaluated sparse matrix.
+//
+// This function implements a performance optimized treatment of the serial evaluation of a sparse
+// matrix serial evaluation expression.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatSerialExpr<MT,SO> serial( const SMatSerialExpr<MT,SO>& sm )
+{
+ return sm;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Rows< SMatSerialExpr<MT,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Columns< SMatSerialExpr<MT,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< SMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< SMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsLower< SMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniLower< SMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyLower< SMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUpper< SMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniUpper< SMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyUpper< SMatSerialExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct SMatSerialExprTrait< SMatSerialExpr<MT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatSerialExpr<MT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TSMatSerialExprTrait< SMatSerialExpr<MT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatSerialExpr<MT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool AF >
+struct SubmatrixExprTrait< SMatSerialExpr<MT,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SerialExprTrait_< SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct RowExprTrait< SMatSerialExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SerialExprTrait_< RowExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct ColumnExprTrait< SMatSerialExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SerialExprTrait_< ColumnExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatTDMatMultExpr.h b/src/cpu/blaze/math/expressions/SMatTDMatMultExpr.h
new file mode 100644
index 00000000..f0ac7df7
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatTDMatMultExpr.h
@@ -0,0 +1,2088 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatTDMatMultExpr.h
+// \brief Header file for the sparse matrix/transpose dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATTDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-transpose dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The SMatTDMatMultExpr class represents the compile time expression for multiplications between
+// a row-major sparse matrix and a column-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class SMatTDMatMultExpr : public DenseMatrix< SMatTDMatMultExpr<MT1,MT2>, false >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the right-hand side dense matrix operand is symmetric,
+ \a value is set to 1 and an optimized evaluation strategy is selected. Otherwise
+ \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsSymmetric<T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the left-hand side matrix is not a diagonal and a loop-unrolled computation is
+ feasible, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !IsResizable<ET1>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatTDMatMultExpr<MT1,MT2> This; //!< Type of this SMatTDMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatTDMatMultExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the multiplication expression.
+ // \param rhs The right-hand side dense matrix operand of the multiplication expression.
+ */
+ explicit inline SMatTDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_SMATTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose dense matrix multiplication to a dense matrix
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatTDMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a sparse matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the sparse matrix-transpose
+ // dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t iend( min( ii+block, A.rows() ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= B.columns(); j+=4UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ if( element == end ) {
+ reset( C(i,j ) );
+ reset( C(i,j+1UL) );
+ reset( C(i,j+2UL) );
+ reset( C(i,j+3UL) );
+ continue;
+ }
+
+ C(i,j ) = element->value() * B(element->index(),j );
+ C(i,j+1UL) = element->value() * B(element->index(),j+1UL);
+ C(i,j+2UL) = element->value() * B(element->index(),j+2UL);
+ C(i,j+3UL) = element->value() * B(element->index(),j+3UL);
+ ++element;
+ for( ; element!=end; ++element ) {
+ C(i,j ) += element->value() * B(element->index(),j );
+ C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
+ C(i,j+2UL) += element->value() * B(element->index(),j+2UL);
+ C(i,j+3UL) += element->value() * B(element->index(),j+3UL);
+ }
+ }
+ }
+
+ for( ; (j+2UL) <= B.columns(); j+=2UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ if( element == end ) {
+ reset( C(i,j ) );
+ reset( C(i,j+1UL) );
+ continue;
+ }
+
+ C(i,j ) = element->value() * B(element->index(),j );
+ C(i,j+1UL) = element->value() * B(element->index(),j+1UL);
+ ++element;
+ for( ; element!=end; ++element ) {
+ C(i,j ) += element->value() * B(element->index(),j );
+ C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
+ }
+ }
+ }
+
+ for( ; j<B.columns(); ++j ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ if( element == end ) {
+ reset( C(i,j) );
+ continue;
+ }
+
+ C(i,j) = element->value() * B(element->index(),j);
+ ++element;
+ for( ; element!=end; ++element ) {
+ C(i,j) += element->value() * B(element->index(),j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a sparse matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the optimized assignment kernel for the sparse matrix-transpose
+ // dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
+
+ reset( C );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t iend( min( ii+block, A.rows() ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= B.columns(); j+=4UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
+ C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j ) += v1 * B(i1,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL);
+ C(i,j+2UL) += v1 * B(i1,j+2UL);
+ C(i,j+3UL) += v1 * B(i1,j+3UL);
+ }
+ }
+ }
+
+ for( ; (j+2UL) <= B.columns(); j+=2UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j ) += v1 * B(i1,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL);
+ }
+ }
+ }
+
+ for( ; j<B.columns(); ++j ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j) += v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose dense matrix multiplication to a sparse matrix
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a sparse matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a sparse matrix-
+ // transpose dense matrix multiplication expression. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case the symmetry
+ // of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a sparse matrix-transpose dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the sparse matrix-
+ // transpose dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t iend( min( ii+block, A.rows() ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= B.columns(); j+=4UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i,j ) += element->value() * B(element->index(),j );
+ C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
+ C(i,j+2UL) += element->value() * B(element->index(),j+2UL);
+ C(i,j+3UL) += element->value() * B(element->index(),j+3UL);
+ }
+ }
+ }
+
+ for( ; (j+2UL) <= B.columns(); j+=2UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i,j ) += element->value() * B(element->index(),j );
+ C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
+ }
+ }
+ }
+
+ for( ; j<B.columns(); ++j ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i,j) += element->value() * B(element->index(),j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a sparse matrix-transpose dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the optimized addition assignment kernel for the sparse matrix-
+ // transpose dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t iend( min( ii+block, A.rows() ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= B.columns(); j+=4UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
+ C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j ) += v1 * B(i1,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL);
+ C(i,j+2UL) += v1 * B(i1,j+2UL);
+ C(i,j+3UL) += v1 * B(i1,j+3UL);
+ }
+ }
+ }
+
+ for( ; (j+2UL) <= B.columns(); j+=2UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j ) += v1 * B(i1,j );
+ C(i,j+1UL) += v1 * B(i1,j+1UL);
+ }
+ }
+ }
+
+ for( ; j<B.columns(); ++j ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j) += v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a sparse matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a sparse
+ // matrix-transpose dense matrix multiplication expression. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case the
+ // symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ SMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a sparse matrix-transpose dense matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the sparse matrix-
+ // transpose dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t iend( min( ii+block, A.rows() ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= B.columns(); j+=4UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i,j ) -= element->value() * B(element->index(),j );
+ C(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
+ C(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
+ C(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
+ }
+ }
+ }
+
+ for( ; (j+2UL) <= B.columns(); j+=2UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i,j ) -= element->value() * B(element->index(),j );
+ C(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
+ }
+ }
+ }
+
+ for( ; j<B.columns(); ++j ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ for( ; element!=end; ++element ) {
+ C(i,j) -= element->value() * B(element->index(),j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a sparse matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the optimized subtraction assignment kernel for the sparse matrix-
+ // transpose dense matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t iend( min( ii+block, A.rows() ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+4UL) <= B.columns(); j+=4UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ C(i,j+2UL) -= v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
+ C(i,j+3UL) -= v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j ) -= v1 * B(i1,j );
+ C(i,j+1UL) -= v1 * B(i1,j+1UL);
+ C(i,j+2UL) -= v1 * B(i1,j+2UL);
+ C(i,j+3UL) -= v1 * B(i1,j+3UL);
+ }
+ }
+ }
+
+ for( ; (j+2UL) <= B.columns(); j+=2UL ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
+ C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j ) -= v1 * B(i1,j );
+ C(i,j+1UL) -= v1 * B(i1,j+1UL);
+ }
+ }
+ }
+
+ for( ; j<B.columns(); ++j ) {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const ConstIterator end( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
+ :( A.end(i) ) );
+ ConstIterator element( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
+ :( A.begin(i) ) );
+
+ const size_t nonzeros( end - element );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ C(i,j) -= v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+
+ C(i,j) -= v1 * B(i1,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a sparse matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a sparse
+ // matrix-transpose dense matrix multiplication expression. Due to the explicit application of
+ // the SFINAE principle this function can only be selected by the compiler in case the symmetry
+ // of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-transpose dense matrix multiplication to a dense
+ // matrix (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-transpose
+ // dense matrix multiplication expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-transpose dense matrix multiplication to a sparse
+ // matrix (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-transpose
+ // dense matrix multiplication expression to a sparse matrix. Due to the explicit application of
+ // the SFINAE principle this function can only be selected by the compiler in case either of the
+ // two matrix operands requires an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a sparse matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a sparse matrix-
+ // transpose dense matrix multiplication expression. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case the symmetry of
+ // either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-transpose dense matrix multiplication expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a sparse matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of
+ // a sparse matrix-transpose dense matrix multiplication expression. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-transpose dense matrix multiplication expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a sparse matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of
+ // sparse matrix-transpose dense matrix multiplication expression. Due to the explicit a
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major sparse matrix and a
+// column-major dense matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the multiplication.
+// \param rhs The right-hand side dense matrix for the multiplication.
+// \return The resulting matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the multiplication of a row-major sparse matrix and a column-major
+// dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A;
+ blaze::DynamicMatrix<double,columnMajor> B;
+ blaze::DynamicMatrix<double,rowMajor> C;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const SMatTDMatMultExpr<T1,T2>
+ operator*( const SparseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatTDMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatTDMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< SMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsAligned<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatDVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , SMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct DMatSVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , SMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTDMatMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TSVecTDMatMultExprTrait_< TSVecSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatTDMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatTDMatSubExpr.h b/src/cpu/blaze/math/expressions/SMatTDMatSubExpr.h
new file mode 100644
index 00000000..efee0b5c
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatTDMatSubExpr.h
@@ -0,0 +1,1022 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatTDMatSubExpr.h
+// \brief Header file for the sparse matrix/transpose dense matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATTDMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATTDMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATTDMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-transpose dense matrix subtractions.
+// \ingroup dense_matrix_expression
+//
+// The SMatTDMatSubExpr class represents the compile time expression for subtractions between
+// a row-major sparse matrix and a column-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class SMatTDMatSubExpr : public DenseMatrix< SMatTDMatSubExpr<MT1,MT2>, true >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatTDMatSubExpr<MT1,MT2> This; //!< Type of this SMatTDMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatTDMatSubExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the addition expression.
+ // \param rhs The right-hand side dense matrix operand of the addition expression.
+ */
+ explicit inline SMatTDMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) ) ||
+ ( IsExpression<MT2>::value && rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return lhs_.isAliased( alias ) && rhs_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // dense matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const SMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign ( ~lhs, -rhs.rhs_ );
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // dense matrix subtraction expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const SMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-transpose dense matrix subtraction to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // transpose dense matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const SMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.rhs_ );
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // transpose dense matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const SMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.rhs_ );
+ subAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-transpose dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-transpose
+ // dense matrix subtraction expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const SMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign ( ~lhs, -rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-transpose dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-transpose
+ // dense matrix subtraction expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const SMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const SMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const SMatTDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a row-major sparse matrix and a column-major
+// dense matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the sparse matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the subtraction of a row-major sparse matrix and a column-major dense
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A;
+ blaze::DynamicMatrix<double,columnMajor> B;
+ blaze::DynamicMatrix<double,rowMajor> C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const SMatTDMatSubExpr<T1,T2>
+ operator-( const SparseMatrix<T1,false>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatTDMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a sparse matrix-transpose dense matrix
+// subtraction expression and a dense matrix (\f$ A=(B-C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix-transpose dense matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a sparse
+// matrix-transpose dense matrix subtraction expression to a dense matrix.
+*/
+template< typename T1 // Type of the sparse matrix of the left-hand side expression
+ , typename T2 // Type of the dense matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< SMatTDMatSubExpr<T1,T2>, T3 >
+ operator+( const SMatTDMatSubExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~rhs) - lhs.rightOperand() ) + lhs.leftOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a sparse matrix-dense matrix subtraction
+// expression and a dense matrix (\f$ A=(B-C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix-dense matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a sparse
+// matrix-dense matrix subtraction expression and a dense matrix.
+*/
+template< typename T1 // Type of the sparse matrix of the left-hand side expression
+ , typename T2 // Type of the dense matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< SMatTDMatSubExpr<T1,T2>, T3 >
+ operator-( const SMatTDMatSubExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return lhs.leftOperand() - ( lhs.rightOperand() + (~rhs) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatTDMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatTDMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< SMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< SMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatTDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< SMatTDMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< DMatTDMatSubExprTrait_<MT3,MT2>, MT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< SMatTDMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatSMatAddExprTrait_< TDMatTDMatSubExprTrait_<MT3,MT2>, MT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< SMatTDMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , SMatDMatSubExprTrait_< MT1, TDMatDMatAddExprTrait_<MT2,MT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< SMatTDMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , SMatTDMatSubExprTrait_< MT1, TDMatTDMatAddExprTrait_<MT2,MT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatTDMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatTDMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatTDMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatTSMatAddExpr.h b/src/cpu/blaze/math/expressions/SMatTSMatAddExpr.h
new file mode 100644
index 00000000..24133993
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatTSMatAddExpr.h
@@ -0,0 +1,1108 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatTSMatAddExpr.h
+// \brief Header file for the sparse matrix/transpose sparse matrix addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATTSMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATTSMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATTSMATADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-transpose sparse matrix additions.
+// \ingroup sparse_matrix_expression
+//
+// The SMatTSMatAddExpr class represents the compile time expression for additions between
+// a row-major sparse matrix and a column-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class SMatTSMatAddExpr : public SparseMatrix< SMatTSMatAddExpr<MT1,MT2>, false >
+ , private MatMatAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Evaluation type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Evaluation type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSymmetricKernel struct is a helper struct for the selection of the serial
+ evaluation strategy. In case the two given matrix types have a different storage
+ order and in case the second matrix type is symmetric, \a value is set to 1 and
+ an optimized evaluation strategy is selected. Otherwise \a value is set to 0 and
+ the default strategy is chosen. */
+ template< typename T1, typename T2 >
+ struct UseSymmetricKernel {
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_DIFFERENT_STORAGE_ORDER( T1, T2 );
+ enum : bool { value = IsSymmetric<T2>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = MT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatTSMatAddExpr<MT1,MT2> This; //!< Type of this SMatTSMatAddExpr instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatTSMatAddExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the addition expression.
+ // \param rhs The right-hand side sparse matrix operand of the addition expression.
+ */
+ explicit inline SMatTSMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the addition expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) + rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() + rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return lhs_.nonZeros(i) + rhs_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the addition expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix addition to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ assign( ~lhs, rhs.lhs_ );
+
+ if( !IsResizable< ElementType_<MT> >::value ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else
+ {
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
+ const RightIterator end( B.end(j) );
+ for( RightIterator element=B.begin(j); element!=end; ++element ) {
+ if( isDefault( (~lhs)(element->index(),j) ) )
+ (~lhs)(element->index(),j) = element->value();
+ else
+ (~lhs)(element->index(),j) += element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix addition to a row-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a sparse matrix-transpose sparse matrix
+ // addition expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< OppositeType_<RT2> > RightIterator;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ CT1 A( serial( rhs.lhs_ ) );
+
+ // Evaluation of the right-hand side sparse matrix operand
+ const OppositeType_<RT2> B( serial( rhs.rhs_ ) );
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix addition
+ for( size_t i=0UL; i<(~lhs).rows(); ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( i, r->index(), r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( i, l->index(), l->value()+r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( i, r->index(), r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( i );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix addition to a row-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // sparse matrix addition expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.lhs_ + trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix addition to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a sparse matrix-transpose sparse matrix
+ // addition expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT1> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< OppositeType_<RT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ const OppositeType_<RT1> A( serial( rhs.lhs_ ) );
+
+ // Evaluation of the right-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) );
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix addition
+ for( size_t j=0UL; j<(~lhs).columns(); ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), j, r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), j, l->value()+r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), j, r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( j );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix addition to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // sparse matrix addition expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT1> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) + rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-transpose sparse matrix addition to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // transpose sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-transpose sparse matrix addition to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // transpose sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-transpose sparse matrix addition to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-transpose sparse matrix addition expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-transpose sparse matrix addition to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-transpose sparse matrix addition expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a row-major and a column-major sparse matrix
+// (\f$ A=B+C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix addition.
+// \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the addition of a row-major and a column-major sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const SMatTSMatAddExpr<T1,T2>
+ operator+( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatTSMatAddExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a column-major and a row-major sparse matrix
+// (\f$ A=B+C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix addition.
+// \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the addition of a column-major and a row-major sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const SMatTSMatAddExpr<T2,T1>
+ operator+( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatTSMatAddExpr<T2,T1>( ~rhs, ~lhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatTSMatAddExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatTSMatAddExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< SMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< SMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >
+ , And< IsUniLower<MT2>, IsStrictlyLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >
+ , And< IsUniUpper<MT2>, IsStrictlyUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatTSMatAddExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatTSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatTSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatTSMatMultExpr.h b/src/cpu/blaze/math/expressions/SMatTSMatMultExpr.h
new file mode 100644
index 00000000..2e4994eb
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatTSMatMultExpr.h
@@ -0,0 +1,1432 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatTSMatMultExpr.h
+// \brief Header file for the sparse matrix/transpose sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATTSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATTSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SMatSVecMultExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TSVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATTSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-transpose sparse matrix multiplications.
+// \ingroup sparse_matrix_expression
+//
+// The SMatTSMatMultExpr class represents the compile time expression for multiplications between
+// a row-major and a column-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class SMatTSMatMultExpr : public SparseMatrix< SMatTSMatMultExpr<MT1,MT2>, false >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the target matrix is row-major and the right-hand side
+ matrix operand of type \a T3 is symmetric or in case the target matrix is column-major
+ and the left-hand side matrix operands of type \a T2 is symmetric, \a value is set to
+ 1 and an optimized evaluation strategy is selected. Otherwise \a value is set to 0 and
+ the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = ( IsRowMajorMatrix<T1>::value && IsSymmetric<T3>::value ) ||
+ ( IsColumnMajorMatrix<T1>::value && IsSymmetric<T2>::value ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatTSMatMultExpr<MT1,MT2> This; //!< Type of this SMatTSMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatTSMatMultExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the multiplication expression.
+ // \param rhs The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline SMatTSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline constexpr size_t nonZeros() const noexcept {
+ return 0UL;
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const noexcept {
+ UNUSED_PARAMETER( i );
+ return 0UL;
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_SMATTSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to row-major matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix multiplication to a row-major
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // sparse matrix multiplication expression to a row-major matrix.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT2> );
+
+ const OppositeType_<MT2> tmp( serial( rhs.rhs_ ) );
+ assign( ~lhs, rhs.lhs_ * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to row-major matrices**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a sparse matrix-transpose sparse matrix multiplication to
+ // a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a row-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major matrices*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix multiplication to a
+ // column-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // sparse matrix multiplication expression to a column-major matrix.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT1> );
+
+ const OppositeType_<MT1> tmp( serial( rhs.lhs_ ) );
+ assign( ~lhs, tmp * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to column-major matrices*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a sparse matrix-transpose sparse matrix multiplication to
+ // a column-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to row-major dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-transpose sparse matrix multiplication to a
+ // row-major dense matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT2> );
+
+ const OppositeType_<MT2> tmp( serial( rhs.rhs_ ) );
+ addAssign( ~lhs, rhs.lhs_ * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to row-major matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a sparse matrix-transpose sparse matrix
+ // multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a sparse
+ // matrix-transpose sparse matrix multiplication expression to a row-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to column-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-transpose sparse matrix multiplication to a
+ // column-major dense matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT1> );
+
+ const OppositeType_<MT1> tmp( serial( rhs.lhs_ ) );
+ addAssign( ~lhs, tmp * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to column-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a sparse matrix-transpose sparse matrix
+ // multiplication to a column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a sparse
+ // matrix-transpose sparse matrix multiplication expression to a column-major matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to row-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-transpose sparse matrix multiplication
+ // to a row-major dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT2> );
+
+ const OppositeType_<MT2> tmp( serial( rhs.rhs_ ) );
+ subAssign( ~lhs, rhs.lhs_ * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to row-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a sparse matrix-transpose sparse matrix
+ // multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // sparse matrix-transpose sparse matrix multiplication expression to a row-major matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to column-major dense matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-transpose sparse matrix multiplication
+ // to a column-major dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT1> );
+
+ const OppositeType_<MT1> tmp( serial( rhs.lhs_ ) );
+ subAssign( ~lhs, tmp * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to column-major matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a sparse matrix-transpose sparse matrix
+ // multiplication to a column-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a sparse
+ // matrix-transpose sparse matrix multiplication expression to a column-major matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to row-major matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-transpose sparse matrix multiplication to a
+ // row-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a row-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT2> );
+
+ const OppositeType_<MT2> tmp( rhs.rhs_ );
+ smpAssign( ~lhs, rhs.lhs_ * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to row-major matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a sparse matrix-transpose sparse matrix multiplication
+ // to a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a row-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to column-major matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-transpose sparse matrix multiplication to a
+ // column-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-
+ // transpose sparse matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT1> );
+
+ const OppositeType_<MT1> tmp( rhs.lhs_ );
+ smpAssign( ~lhs, tmp * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to column-major matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a sparse matrix-transpose sparse matrix multiplication
+ // to a column-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a sparse
+ // matrix-transpose sparse matrix multiplication expression to a column-major matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to row-major dense matrices*****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-transpose sparse matrix multiplication
+ // to a row-major dense matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-transpose sparse matrix multiplication expression to a row-major dense matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT2> );
+
+ const OppositeType_<MT2> tmp( rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to column-major dense matrices**************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-transpose sparse matrix multiplication
+ // to a column-major dense matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-transpose sparse matrix multiplication expression to a column-major dense matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT1> );
+
+ const OppositeType_<MT1> tmp( rhs.lhs_ );
+ smpAddAssign( ~lhs, tmp * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to row-major matrices*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a sparse matrix-transpose sparse matrix
+ // multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // sparse matrix-transpose sparse matrix multiplication expression to a row-major matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to column-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a sparse matrix-transpose sparse matrix
+ // multiplication to a column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // sparse matrix-transpose sparse matrix multiplication expression to a column-major matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to row-major dense matrices**************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-transpose sparse matrix multiplication
+ // to a row-major dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-transpose sparse matrix multiplication expression to a row-major dense matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT2> );
+
+ const OppositeType_<MT2> tmp( rhs.rhs_ );
+ smpSubAssign( ~lhs, rhs.lhs_ * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to column-major dense matrices***********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-transpose sparse matrix multiplication
+ // to a column-major dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-transpose sparse matrix multiplication expression to a column-major dense matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT1> );
+
+ const OppositeType_<MT1> tmp( rhs.lhs_ );
+ smpSubAssign( ~lhs, tmp * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to row-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a sparse matrix-transpose sparse matrix
+ // multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // sparse matrix-transpose sparse matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to column-major matrices***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a sparse matrix-transpose sparse matrix
+ // multiplication to a column-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // sparse matrix-transpose sparse matrix multiplication expression to a column-major matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a row-major sparse matrix and a
+// column-major sparse matrix (\f$ A=B*C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix multiplication.
+// \param rhs The right-hand side sparse matrix for the matrix multiplication.
+// \return The product of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the multiplication of a row-major sparse matrix and a column-major
+// sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const SMatTSMatMultExpr<T1,T2>
+ operator*( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatTSMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatTSMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct SMatDVecMultExprTrait< SMatTSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , SMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct SMatSVecMultExprTrait< SMatTSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , SMatSVecMultExprTrait_< MT1, TSMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecSMatMultExprTrait< VT, SMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTSMatMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecSMatMultExprTrait< VT, SMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTSMatMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatTSMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatTSMatSubExpr.h b/src/cpu/blaze/math/expressions/SMatTSMatSubExpr.h
new file mode 100644
index 00000000..247feb81
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatTSMatSubExpr.h
@@ -0,0 +1,1060 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatTSMatSubExpr.h
+// \brief Header file for the sparse matrix/transpose sparse matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATTSMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATTSMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATTSMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-transpose sparse matrix subtractions.
+// \ingroup sparse_matrix_expression
+//
+// The SMatTSMatSubExpr class represents the compile time expression for subtractions between
+// a row-major sparse matrix and a column-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class SMatTSMatSubExpr : public SparseMatrix< SMatTSMatSubExpr<MT1,MT2>, false >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSymmetricKernel struct is a helper struct for the selection of the serial
+ evaluation strategy. In case the two given matrix types have a different storage
+ order and in case the second matrix type is symmetric, \a value is set to 1 and
+ an optimized evaluation strategy is selected. Otherwise \a value is set to 0 and
+ the default strategy is chosen. */
+ template< typename T1, typename T2 >
+ struct UseSymmetricKernel {
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_DIFFERENT_STORAGE_ORDER( T1, T2 );
+ enum : bool { value = IsSymmetric<T2>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = MT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatTSMatSubExpr<MT1,MT2> This; //!< Type of this SMatTSMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatTSMatSubExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the subtraction expression.
+ // \param rhs The right-hand side sparse matrix operand of the subtraction expression.
+ */
+ explicit inline SMatTSMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() + rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return lhs_.nonZeros(i) + rhs_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse matrix operand.
+ //
+ // \return The left-hand side sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ assign( ~lhs, rhs.lhs_ );
+
+ if( !IsResizable< ElementType_<MT> >::value ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else
+ {
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
+ const RightIterator end( B.end(j) );
+ for( RightIterator element=B.begin(j); element!=end; ++element ) {
+ if( isDefault( (~lhs)(element->index(),j) ) )
+ (~lhs)(element->index(),j) = -element->value();
+ else
+ (~lhs)(element->index(),j) -= element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix subtraction to a row-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a sparse matrix-transpose sparse matrix
+ // subtraction expression to a sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< OppositeType_<RT2> > RightIterator;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ CT1 A( serial( rhs.lhs_ ) );
+
+ // Evaluation of the right-hand side sparse matrix operand
+ const OppositeType_<RT2> B( serial( rhs.rhs_ ) );
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix subtraction
+ for( size_t i=0UL; i<(~lhs).rows(); ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( i, r->index(), -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( i, l->index(), l->value()-r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( i, r->index(), -r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( i );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix subtraction to a row-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // sparse matrix subtraction expression to a sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.lhs_ - trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix subtraction to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a sparse matrix-transpose sparse matrix
+ // subtraction expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT1> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< OppositeType_<RT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ const OppositeType_<RT1> A( serial( rhs.lhs_ ) );
+
+ // Evaluation of the right-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) );
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix subtraction
+ for( size_t j=0UL; j<(~lhs).columns(); ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), j, -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), j, l->value()-r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), j, -r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( j );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose sparse matrix subtraction to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // sparse matrix subtraction expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT1> >
+ assign( SparseMatrix<MT,true>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) - rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-transpose sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse
+ // matrix-transpose sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-transpose sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // transpose sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-transpose sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-transpose sparse matrix subtraction expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-transpose sparse matrix subtraction
+ // to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix-transpose sparse matrix subtraction expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a row-major and a column-major sparse
+// matrix (\f$ A=B-C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix subtraction.
+// \param rhs The right-hand side sparse matrix to be subtracted from the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the subtraction of a row-major and a column-major sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, C;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const SMatTSMatSubExpr<T1,T2>
+ operator-( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return SMatTSMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< SMatTSMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< SMatTSMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< SMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< SMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< SMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< SMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< SMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< SMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< SMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< SMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< SMatTSMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< SMatTSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< SMatTSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatTransExpr.h b/src/cpu/blaze/math/expressions/SMatTransExpr.h
new file mode 100644
index 00000000..ceb69a15
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatTransExpr.h
@@ -0,0 +1,1110 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatTransExpr.h
+// \brief Header file for the sparse matrix transpose expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATTRANSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DMatTransposer.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatTransExpr.h>
+#include <blaze/math/expressions/SMatTransposer.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatTransExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/traits/TSMatTransExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EmptyType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATTRANSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix transpositions.
+// \ingroup sparse_matrix_expression
+//
+// The SMatTransExpr class represents the compile time expression for transpositions of
+// sparse matrices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+class SMatTransExpr : public SparseMatrix< SMatTransExpr<MT,SO>, SO >
+ , private MatTransExpr
+ , private If< IsComputation<MT>, Computation, EmptyType >::Type
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> RT; //!< Result type of the sparse matrix expression.
+ typedef CompositeType_<MT> CT; //!< Composite type of the sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the transposition expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the transposition expression. In case the given sparse
+ matrix expression of type \a MT requires an intermediate evaluation, \a useAssign will be
+ set to 1 and the transposition expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to 0 and the expression will be evaluated via
+ the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<MT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable and the sparse matrix operand requires
+ an intermediate evaluation, \a value is set to 1 and the expression specific evaluation
+ strategy is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename MT2 >
+ struct UseSMPAssign {
+ enum : bool { value = MT2::smpAssignable && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatTransExpr<MT,SO> This; //!< Type of this SMatTransExpr instance.
+ typedef TransposeType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef ResultType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SMatTransExpr& > CompositeType;
+
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > Operand;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse matrix transposition expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Iterator type of the sparse matrix expression.
+ typedef ConstIterator_< RemoveReference_<Operand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef typename std::iterator_traits<IteratorType>::value_type ValueType; //!< Type of the underlying pointers.
+ typedef typename std::iterator_traits<IteratorType>::pointer PointerType; //!< Pointer return type.
+ typedef typename std::iterator_traits<IteratorType>::reference ReferenceType; //!< Reference return type.
+ typedef typename std::iterator_traits<IteratorType>::difference_type DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType it )
+ : it_( it ) // Iterator over the elements of the sparse matrix expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const ValueType operator*() const {
+ return *it_;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return Reference to the sparse matrix element at the current iterator position.
+ */
+ inline const IteratorType operator->() const {
+ return it_;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return it_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator over the elements of the sparse matrix expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatTransExpr class.
+ //
+ // \param sm The sparse matrix operand of the transposition expression.
+ */
+ explicit inline SMatTransExpr( const MT& sm ) noexcept
+ : sm_( sm )
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < sm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < sm_.rows() , "Invalid column access index" );
+ return sm_(j,i);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= sm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= sm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator to the first non-zero element of row/column \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return sm_.begin(i);
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator just past the last non-zero element of row/column \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return sm_.end(i);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return sm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return sm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return sm_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row/column.
+ //
+ // \param i The index of the row/column.
+ // \return The number of non-zero elements of row/column \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return sm_.nonZeros( i );
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific matrix element.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return sm_.find( j, i );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return sm_.lowerBound( j, i );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+ return sm_.upperBound( j, i );
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the sparse matrix operand.
+ //
+ // \return The sparse matrix operand.
+ */
+ inline Operand operand() const noexcept {
+ return sm_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return sm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return sm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return sm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand sm_; //!< Sparse matrix of the transposition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix transposition expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix
+ // transposition expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( DenseMatrix<MT2,SO2>& lhs, const SMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ assign( tmp, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix transposition expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix
+ // transposition expression to a sparse matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ assign( SparseMatrix<MT2,SO2>& lhs, const SMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ SMatTransposer<MT2,!SO2> tmp( ~lhs );
+ assign( tmp, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix transposition expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse
+ // matrix transposition expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ addAssign( DenseMatrix<MT2,SO2>& lhs, const SMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ addAssign( tmp, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix transposition expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // matrix transposition expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT2> >
+ subAssign( DenseMatrix<MT2,SO2>& lhs, const SMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ subAssign( tmp, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix transposition expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix
+ // transposition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( DenseMatrix<MT2,SO2>& lhs, const SMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ smpAssign( tmp, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix transposition expression to a sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix
+ // transposition expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAssign( SparseMatrix<MT2,SO2>& lhs, const SMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ SMatTransposer<MT2,!SO2> tmp( ~lhs );
+ smpAssign( tmp, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix transposition expression to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix transposition expression to a dense matrix. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpAddAssign( DenseMatrix<MT2,SO2>& lhs, const SMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ smpAddAssign( tmp, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix transposition expression to a dense
+ // matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side transposition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix transposition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT2 // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT2> >
+ smpSubAssign( DenseMatrix<MT2,SO2>& lhs, const SMatTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ DMatTransposer<MT2,!SO2> tmp( ~lhs );
+ smpSubAssign( tmp, rhs.sm_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( MT, !SO );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Calculation of the transpose of the given sparse matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be transposed.
+// \return The transpose of the matrix.
+//
+// This function returns an expression representing the transpose of the given sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ B = trans( A );
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline const SMatTransExpr<MT,!SO> trans( const SparseMatrix<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SMatTransExpr<MT,!SO>( ~sm );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating the transpose of a transpose sparse matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be (re-)transposed.
+// \return The transpose of the transpose matrix.
+//
+// This function implements a performance optimized treatment of the transpose operation on a
+// sparse matrix transpose expression. It returns an expression representing the transpose of a
+// transpose sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, B;
+ // ... Resizing and initialization
+ B = trans( trans( A ) );
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline typename SMatTransExpr<MT,SO>::Operand trans( const SMatTransExpr<MT,SO>& sm )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sm.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Rows< SMatTransExpr<MT,SO> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct Columns< SMatTransExpr<MT,SO> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsSymmetric< SMatTransExpr<MT,SO> >
+ : public BoolConstant< IsSymmetric<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsHermitian< SMatTransExpr<MT,SO> >
+ : public BoolConstant< IsHermitian<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsLower< SMatTransExpr<MT,SO> >
+ : public BoolConstant< IsUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniLower< SMatTransExpr<MT,SO> >
+ : public BoolConstant< IsUniUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyLower< SMatTransExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyUpper<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUpper< SMatTransExpr<MT,SO> >
+ : public BoolConstant< IsLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsUniUpper< SMatTransExpr<MT,SO> >
+ : public BoolConstant< IsUniLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsStrictlyUpper< SMatTransExpr<MT,SO> >
+ : public BoolConstant< IsStrictlyLower<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct SMatTransExprTrait< SMatTransExpr<MT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , Operand_< SMatTransExpr<MT,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT >
+struct TSMatTransExprTrait< SMatTransExpr<MT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , Operand_< SMatTransExpr<MT,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool AF >
+struct SubmatrixExprTrait< SMatTransExpr<MT,SO>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = TransExprTrait_< SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct RowExprTrait< SMatTransExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = TransExprTrait_< ColumnExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct ColumnExprTrait< SMatTransExpr<MT,SO> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = TransExprTrait_< RowExprTrait_<const MT> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SMatTransposer.h b/src/cpu/blaze/math/expressions/SMatTransposer.h
new file mode 100644
index 00000000..e064ba1e
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SMatTransposer.h
@@ -0,0 +1,1149 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SMatTransposer.h
+// \brief Header file for the sparse matrix transposer
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SMATTRANSPOSER_H_
+#define _BLAZE_MATH_EXPRESSIONS_SMATTRANSPOSER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATTRANSPOSER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the transposition of a sparse matrix.
+// \ingroup sparse_matrix_expression
+//
+// The SMatTransposer class is a wrapper object for the temporary transposition of a sparse matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+class SMatTransposer : public SparseMatrix< SMatTransposer<MT,SO>, SO >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatTransposer<MT,SO> This; //!< Type of this SMatTransposer instance.
+ typedef TransposeType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef MT OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef ResultType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatTransposer class.
+ //
+ // \param sm The sparse matrix operand.
+ */
+ explicit inline SMatTransposer( MT& sm ) noexcept
+ : sm_( sm ) // The sparse matrix operand
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline ConstReference operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < sm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < sm_.row() , "Invalid column access index" );
+ return sm_(j,i);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ConstReference at( size_t i, size_t j ) const {
+ if( i >= sm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= sm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator to the first non-zero element of row/column \a i.
+ //
+ // This function returns a row/column iterator to the first non-zero element of row/column \a i.
+ // In case the storage order is set to \a rowMajor the function returns an iterator to the first
+ // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+ // returns an iterator to the first non-zero element of column \a i.
+ */
+ inline Iterator begin( size_t i ) {
+ return sm_.begin(i);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator to the first non-zero element of row/column \a i.
+ //
+ // This function returns a row/column iterator to the first non-zero element of row/column \a i.
+ // In case the storage order is set to \a rowMajor the function returns an iterator to the first
+ // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+ // returns an iterator to the first non-zero element of column \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return sm_.cbegin(i);
+ }
+ //**********************************************************************************************
+
+ //**Cbegin function*****************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator to the first non-zero element of row/column \a i.
+ //
+ // This function returns a row/column iterator to the first non-zero element of row/column \a i.
+ // In case the storage order is set to \a rowMajor the function returns an iterator to the first
+ // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+ // returns an iterator to the first non-zero element of column \a i.
+ */
+ inline ConstIterator cbegin( size_t i ) const {
+ return sm_.cbegin(i);
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator just past the last non-zero element of row/column \a i.
+ //
+ // This function returns an row/column iterator just past the last non-zero element of row/column
+ // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+ // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+ // the function returns an iterator just past the last non-zero element of column \a i.
+ */
+ inline Iterator end( size_t i ) {
+ return sm_.end(i);
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator just past the last non-zero element of row/column \a i.
+ //
+ // This function returns an row/column iterator just past the last non-zero element of row/column
+ // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+ // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+ // the function returns an iterator just past the last non-zero element of column \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return sm_.cend(i);
+ }
+ //**********************************************************************************************
+
+ //**Cend function*******************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+ //
+ // \param i The row/column index.
+ // \return Iterator just past the last non-zero element of row/column \a i.
+ //
+ // This function returns an row/column iterator just past the last non-zero element of row/column
+ // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+ // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+ // the function returns an iterator just past the last non-zero element of column \a i.
+ */
+ inline ConstIterator cend( size_t i ) const {
+ return sm_.cend(i);
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment operator**********************************************************
+ /*!\brief Multiplication assignment operator for the multiplication between a matrix and
+ // a scalar value (\f$ A*=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the multiplication.
+ // \return Reference to this SMatTransposer.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, SMatTransposer >& operator*=( Other rhs )
+ {
+ (~sm_) *= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Division assignment operator****************************************************************
+ /*!\brief Division assignment operator for the division of a matrix by a scalar value
+ // (\f$ A/=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the division.
+ // \return Reference to this SMatTransposer.
+ //
+ // \note A division by zero is only checked by an user assert.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, SMatTransposer >& operator/=( Other rhs )
+ {
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ (~sm_) /= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return sm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return sm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Capacity function***************************************************************************
+ /*!\brief Returns the maximum capacity of the matrix.
+ //
+ // \return The capacity of the matrix.
+ */
+ inline size_t capacity() const noexcept {
+ return sm_.capacity();
+ }
+ //**********************************************************************************************
+
+ //**Capacity function***************************************************************************
+ /*!\brief Returns the current capacity of the specified row/column.
+ //
+ // \param i The index of the row/column.
+ // \return The current capacity of row/column \a i.
+ */
+ inline size_t capacity( size_t i ) const noexcept {
+ return sm_.capacity( i );
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the matrix
+ //
+ // \return The number of non-zero elements in the matrix.
+ */
+ inline size_t nonZeros() const {
+ return sm_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row/column.
+ //
+ // \param i The index of the row/column.
+ // \return The number of non-zero elements of row/column \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return sm_.nonZeros( i );
+ }
+ //**********************************************************************************************
+
+ //**Reset function******************************************************************************
+ /*!\brief Resets the matrix elements.
+ //
+ // \return void
+ */
+ inline void reset() {
+ return sm_.reset();
+ }
+ //**********************************************************************************************
+
+ //**Insert function*****************************************************************************
+ /*!\brief Inserting an element into the sparse matrix.
+ //
+ // \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+ // \param value The value of the element to be inserted.
+ // \return Iterator to the newly inserted element.
+ // \exception std::invalid_argument Invalid sparse matrix access index.
+ //
+ // This function insert a new element into the sparse matrix. However, duplicate elements are
+ // not allowed. In case the sparse matrix already contains an element with row index \a i and
+ // column index \a j, a \a std::invalid_argument exception is thrown.
+ */
+ inline Iterator insert( size_t i, size_t j, const ElementType& value ) {
+ return sm_.insert( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Reserve function****************************************************************************
+ /*!\brief Setting the minimum capacity of the sparse matrix.
+ //
+ // \param nonzeros The new minimum capacity of the sparse matrix.
+ // \return void
+ //
+ // This function increases the capacity of the sparse matrix to at least \a nonzeros elements.
+ // The current values of the matrix elements and the individual capacities of the matrix rows
+ // are preserved.
+ */
+ inline void reserve( size_t nonzeros ) {
+ sm_.reserve( nonzeros );
+ }
+ //**********************************************************************************************
+
+ //**Reserve function****************************************************************************
+ /*!\brief Setting the minimum capacity of a specific row/column of the sparse matrix.
+ //
+ // \param i The row/column index of the new element \f$[0..M-1]\f$ or \f$[0..N-1]\f$.
+ // \param nonzeros The new minimum capacity of the specified row.
+ // \return void
+ //
+ // This function increases the capacity of row/column \a i of the sparse matrix to at least
+ // \a nonzeros elements. The current values of the sparse matrix and all other individual
+ // row/column capacities are preserved. In case the storage order is set to \a rowMajor, the
+ // function reserves capacity for row \a i and the index has to be in the range \f$[0..M-1]\f$.
+ // In case the storage order is set to \a columnMajor, the function reserves capacity for column
+ // \a i and the index has to be in the range \f$[0..N-1]\f$.
+ */
+ inline void reserve( size_t i, size_t nonzeros ) {
+ sm_.reserve( i, nonzeros );
+ }
+ //**********************************************************************************************
+
+ //**Append function*****************************************************************************
+ /*!\brief Appending an element to the specified row/column of the sparse matrix.
+ //
+ // \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+ // \param value The value of the element to be appended.
+ // \param check \a true if the new value should be checked for default values, \a false if not.
+ // \return void
+ //
+ // This function provides a very efficient way to fill a sparse matrix with elements. It
+ // appends a new element to the end of the specified row/column without any additional
+ // memory allocation. Therefore it is strictly necessary to keep the following preconditions
+ // in mind:
+ //
+ // - the index of the new element must be strictly larger than the largest index of
+ // non-zero elements in the specified row/column of the sparse matrix
+ // - the current number of non-zero elements in row/column \a i must be smaller than
+ // the capacity of row/column \a i.
+ //
+ // Ignoring these preconditions might result in undefined behavior! The optional \a check
+ // parameter specifies whether the new value should be tested for a default value. If the new
+ // value is a default value (for instance 0 in case of an integral element type) the value is
+ // not appended. Per default the values are not tested.
+ //
+ // \note Although append() does not allocate new memory, it still invalidates all iterators
+ // returned by the end() functions!
+ */
+ inline void append( size_t i, size_t j, const ElementType& value, bool check=false ) {
+ sm_.append( j, i, value, check );
+ }
+ //**********************************************************************************************
+
+ //**Finalize function***************************************************************************
+ /*!\brief Finalizing the element insertion of a row/column.
+ //
+ // \param i The index of the row/column to be finalized \f$[0..M-1]\f$.
+ // \return void
+ //
+ // This function is part of the low-level interface to efficiently fill the matrix with elements.
+ // After completion of row/column \a i via the append() function, this function can be called to
+ // finalize row/column \a i and prepare the next row/column for insertion process via append().
+ //
+ // \note Although finalize() does not allocate new memory, it still invalidates all iterators
+ // returned by the end() functions!
+ */
+ inline void finalize( size_t i ) {
+ sm_.finalize( i );
+ }
+ //**********************************************************************************************
+
+ //**IsIntact function***************************************************************************
+ /*!\brief Returns whether the invariants of the matrix are intact.
+ //
+ // \return \a true in case the matrix's invariants are intact, \a false otherwise.
+ */
+ inline bool isIntact() const noexcept {
+ return isIntact( sm_ );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the matrix can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this matrix, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool canAlias( const Other* alias ) const noexcept
+ {
+ return sm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the matrix is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this matrix, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool isAliased( const Other* alias ) const noexcept
+ {
+ return sm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**CanSMPAssign function***********************************************************************
+ /*!\brief Returns whether the matrix can be used in SMP assignments.
+ //
+ // \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept
+ {
+ return sm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of row-major sparse matrices*******************************************
+ /*!\brief Implementation of the transpose assignment of a row-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void assign( const SparseMatrix<MT2,false>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( sm_.columns() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( sm_.rows() == (~rhs).columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( sm_.capacity() >= (~rhs).nonZeros(), "Capacity not sufficient" );
+
+ typedef ConstIterator_<MT2> RhsIterator;
+
+ const size_t m( rows() );
+
+ for( size_t i=0UL; i<m; ++i ) {
+ for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ sm_.append( element->index(), i, element->value() );
+ finalize( i );
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of column-major sparse matrices****************************************
+ /*!\brief Implementation of the transpose assignment of a column-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void assign( const SparseMatrix<MT2,true>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( sm_.columns() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( sm_.rows() == (~rhs).columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( sm_.capacity() >= (~rhs).nonZeros(), "Capacity not sufficient" );
+
+ typedef ConstIterator_<MT2> RhsIterator;
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+
+ // Counting the number of elements per row
+ std::vector<size_t> rowLengths( m, 0UL );
+ for( size_t j=0UL; j<n; ++j ) {
+ for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ ++rowLengths[element->index()];
+ }
+
+ // Resizing the sparse matrix
+ for( size_t i=0UL; i<m; ++i ) {
+ sm_.reserve( i, rowLengths[i] );
+ }
+
+ // Appending the elements to the rows of the sparse matrix
+ for( size_t j=0UL; j<n; ++j ) {
+ for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element ) {
+ sm_.append( j, element->index(), element->value() );
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ MT& sm_; //!< The sparse matrix operand.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR ROW-MAJOR MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of SMatTransposer for row-major matrices.
+// \ingroup sparse_matrix_expression
+//
+// This specialization of SMatTransposer adapts the class template to the requirements of
+// row-major matrices.
+*/
+template< typename MT > // Type of the sparse matrix
+class SMatTransposer<MT,true> : public SparseMatrix< SMatTransposer<MT,true>, true >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef SMatTransposer<MT,true> This; //!< Type of this SMatTransposer instance.
+ typedef TransposeType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef MT OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef ResultType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SMatTransposer class.
+ //
+ // \param sm The sparse matrix operand.
+ */
+ explicit inline SMatTransposer( MT& sm ) noexcept
+ : sm_( sm ) // The sparse matrix operand
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline ConstReference operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < sm_.columns(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < sm_.row() , "Invalid column access index" );
+ return sm_(j,i);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ConstReference at( size_t i, size_t j ) const {
+ if( i >= sm_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= sm_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator to the first non-zero element of column \a j.
+ */
+ inline Iterator begin( size_t j ) {
+ return sm_.begin(j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator to the first non-zero element of column \a j.
+ */
+ inline ConstIterator begin( size_t j ) const {
+ return sm_.cbegin(j);
+ }
+ //**********************************************************************************************
+
+ //**Cbegin function*****************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator to the first non-zero element of column \a j.
+ */
+ inline ConstIterator cbegin( size_t j ) const {
+ return sm_.cbegin(j);
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator just past the last non-zero element of column \a j.
+ */
+ inline Iterator end( size_t j ) {
+ return sm_.end(j);
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator just past the last non-zero element of column \a j.
+ */
+ inline ConstIterator end( size_t j ) const {
+ return sm_.cend(j);
+ }
+ //**********************************************************************************************
+
+ //**Cend function*******************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of column \a j.
+ //
+ // \param j The column index.
+ // \return Iterator just past the last non-zero element of column \a j.
+ */
+ inline ConstIterator cend( size_t j ) const {
+ return sm_.cend(j);
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment operator**********************************************************
+ /*!\brief Multiplication assignment operator for the multiplication between a matrix and
+ // a scalar value (\f$ A*=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the multiplication.
+ // \return Reference to this SMatTransposer.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, SMatTransposer >& operator*=( Other rhs )
+ {
+ (~sm_) *= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Division assignment operator****************************************************************
+ /*!\brief Division assignment operator for the division of a matrix by a scalar value
+ // (\f$ A/=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the division.
+ // \return Reference to this SMatTransposer.
+ //
+ // \note A division by zero is only checked by an user assert.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, SMatTransposer >& operator/=( Other rhs )
+ {
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ (~sm_) /= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return sm_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return sm_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Capacity function***************************************************************************
+ /*!\brief Returns the maximum capacity of the matrix.
+ //
+ // \return The capacity of the matrix.
+ */
+ inline size_t capacity() const noexcept {
+ return sm_.capacity();
+ }
+ //**********************************************************************************************
+
+ //**Capacity function***************************************************************************
+ /*!\brief Returns the current capacity of the specified column.
+ //
+ // \param j The index of the column.
+ // \return The current capacity of column \a j.
+ */
+ inline size_t capacity( size_t j ) const noexcept {
+ return sm_.capacity( j );
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the matrix
+ //
+ // \return The number of non-zero elements in the matrix.
+ */
+ inline size_t nonZeros() const {
+ return sm_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified column.
+ //
+ // \param j The index of the column.
+ // \return The number of non-zero elements of column \a j.
+ */
+ inline size_t nonZeros( size_t j ) const {
+ return sm_.nonZeros( j );
+ }
+ //**********************************************************************************************
+
+ //**Reset function******************************************************************************
+ /*!\brief Resets the matrix elements.
+ //
+ // \return void
+ */
+ inline void reset() {
+ return sm_.reset();
+ }
+ //**********************************************************************************************
+
+ //**Insert function*****************************************************************************
+ /*!\brief Inserting an element into the sparse matrix.
+ //
+ // \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+ // \param value The value of the element to be inserted.
+ // \return Iterator to the newly inserted element.
+ // \exception std::invalid_argument Invalid sparse matrix access index.
+ //
+ // This function insert a new element into the sparse matrix. However, duplicate elements are
+ // not allowed. In case the sparse matrix already contains an element with row index \a i and
+ // column index \a j, a \a std::invalid_argument exception is thrown.
+ */
+ inline Iterator insert( size_t i, size_t j, const ElementType& value ) {
+ return sm_.insert( j, i, value );
+ }
+ //**********************************************************************************************
+
+ //**Reserve function****************************************************************************
+ /*!\brief Setting the minimum capacity of the sparse matrix.
+ //
+ // \param nonzeros The new minimum capacity of the sparse matrix.
+ // \return void
+ //
+ // This function increases the capacity of the sparse matrix to at least \a nonzeros elements.
+ // The current values of the matrix elements and the individual capacities of the matrix rows
+ // are preserved.
+ */
+ inline void reserve( size_t nonzeros ) {
+ sm_.reserve( nonzeros );
+ }
+ //**********************************************************************************************
+
+ //**Reserve function****************************************************************************
+ /*!\brief Setting the minimum capacity of a specific column of the sparse matrix.
+ //
+ // \param j The column index of the new element \f$[0..N-1]\f$.
+ // \param nonzeros The new minimum capacity of the specified row.
+ // \return void
+ //
+ // This function increases the capacity of column \a j of the sparse matrix to at least
+ // \a nonzeros elements. The current values of the sparse matrix and all other individual
+ // column capacities are preserved.
+ */
+ inline void reserve( size_t i, size_t nonzeros ) {
+ sm_.reserve( i, nonzeros );
+ }
+ //**********************************************************************************************
+
+ //**Append function*****************************************************************************
+ /*!\brief Appending an element to the specified column of the sparse matrix.
+ //
+ // \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+ // \param value The value of the element to be appended.
+ // \param check \a true if the new value should be checked for default values, \a false if not.
+ // \return void
+ //
+ // This function provides a very efficient way to fill a sparse matrix with elements. It
+ // appends a new element to the end of the specified column without any additional memory
+ // allocation. Therefore it is strictly necessary to keep the following preconditions in
+ // mind:
+ //
+ // - the index of the new element must be strictly larger than the largest index of non-zero
+ // elements in the specified column of the sparse matrix
+ // - the current number of non-zero elements in column \a j must be smaller than the capacity
+ // of column \a j.
+ //
+ // Ignoring these preconditions might result in undefined behavior! The optional \a check
+ // parameter specifies whether the new value should be tested for a default value. If the new
+ // value is a default value (for instance 0 in case of an integral element type) the value is
+ // not appended. Per default the values are not tested.
+ //
+ // \note Although append() does not allocate new memory, it still invalidates all iterators
+ // returned by the end() functions!
+ */
+ void append( size_t i, size_t j, const ElementType& value, bool check=false ) {
+ sm_.append( j, i, value, check );
+ }
+ //**********************************************************************************************
+
+ //**Finalize function***************************************************************************
+ /*!\brief Finalizing the element insertion of a column.
+ //
+ // \param i The index of the column to be finalized \f$[0..M-1]\f$.
+ // \return void
+ //
+ // This function is part of the low-level interface to efficiently fill the matrix with elements.
+ // After completion of column \a i via the append() function, this function can be called to
+ // finalize column \a i and prepare the next row/column for insertion process via append().
+ //
+ // \note Although finalize() does not allocate new memory, it still invalidates all iterators
+ // returned by the end() functions!
+ */
+ inline void finalize( size_t j ) {
+ sm_.finalize( j );
+ }
+ //**********************************************************************************************
+
+ //**IsIntact function***************************************************************************
+ /*!\brief Returns whether the invariants of the matrix are intact.
+ //
+ // \return \a true in case the matrix's invariants are intact, \a false otherwise.
+ */
+ inline bool isIntact() const noexcept {
+ return isIntact( sm_ );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the matrix can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this matrix, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool canAlias( const Other* alias ) const noexcept
+ {
+ return sm_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the matrix is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this matrix, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool isAliased( const Other* alias ) const noexcept
+ {
+ return sm_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**CanSMPAssign function***********************************************************************
+ /*!\brief Returns whether the matrix can be used in SMP assignments.
+ //
+ // \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept
+ {
+ return sm_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of row-major sparse matrices*******************************************
+ /*!\brief Implementation of the transpose assignment of a row-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void assign( const SparseMatrix<MT2,false>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( sm_.columns() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( sm_.rows() == (~rhs).columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( sm_.capacity() >= (~rhs).nonZeros(), "Capacity not sufficient" );
+
+ typedef ConstIterator_<MT2> RhsIterator;
+
+ const size_t m( rows() );
+ const size_t n( columns() );
+
+ // Counting the number of elements per row
+ std::vector<size_t> columnLengths( n, 0UL );
+ for( size_t i=0UL; i<m; ++i ) {
+ for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ ++columnLengths[element->index()];
+ }
+
+ // Resizing the sparse matrix
+ for( size_t j=0UL; j<n; ++j ) {
+ sm_.reserve( j, columnLengths[j] );
+ }
+
+ // Appending the elements to the columns of the sparse matrix
+ for( size_t i=0UL; i<m; ++i ) {
+ for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element ) {
+ sm_.append( element->index(), i, element->value() );
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of column-major sparse matrices****************************************
+ /*!\brief Implementation of the transpose assignment of a column-major sparse matrix.
+ //
+ // \param rhs The right-hand side sparse matrix to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename MT2 > // Type of the right-hand side sparse matrix
+ inline void assign( const SparseMatrix<MT2,true>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( sm_.columns() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( sm_.rows() == (~rhs).columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( sm_.capacity() >= (~rhs).nonZeros(), "Capacity not sufficient" );
+
+ typedef ConstIterator_<MT2> RhsIterator;
+
+ const size_t n( columns() );
+
+ for( size_t j=0UL; j<n; ++j ) {
+ for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ sm_.append( j, element->index(), element->value() );
+ finalize( j );
+ }
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ MT& sm_; //!< The sparse matrix operand.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resetting the sparse matrix contained in a SMatTransposer.
+// \ingroup sparse_matrix_expression
+//
+// \param m The sparse matrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline void reset( SMatTransposer<MT,SO>& m )
+{
+ m.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the invariants of the given SMatTransposer are intact.
+// \ingroup sparse_matrix_expression
+//
+// \param m The sparse matrix to be tested.
+// \return \a true in caes the given matrix's invariants are intact, \a false otherwise.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+inline bool isIntact( const SMatTransposer<MT,SO>& m ) noexcept
+{
+ return m.isIntact();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct SubmatrixTrait< SMatTransposer<MT,SO> >
+{
+ using Type = SubmatrixTrait_< ResultType_< SMatTransposer<MT,SO> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecDVecCrossExpr.h b/src/cpu/blaze/math/expressions/SVecDVecCrossExpr.h
new file mode 100644
index 00000000..3572765e
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecDVecCrossExpr.h
@@ -0,0 +1,573 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecDVecCrossExpr.h
+// \brief Header file for the sparse vector/sparse vector cross product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECDVECCROSSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECDVECCROSSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/dense/Forward.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/CrossExpr.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECDVECCROSSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-dense vector cross products.
+// \ingroup dense_vector_expression
+//
+// The SVecDVecCrossExpr class represents the compile time expression for cross products
+// between a sparse vector and a dense vector.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class SVecDVecCrossExpr : public DenseVector< SVecDVecCrossExpr<VT1,VT2,TF>, TF >
+ , private CrossExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side sparse vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_< MultExprTrait_<RN1,RN2>, MultExprTrait_<RN1,RN2> > ExprReturnType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecDVecCrossExpr<VT1,VT2,TF> This; //!< Type of this SVecDVecCrossExpr instance.
+ typedef CrossTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef const StaticVector<ET1,3UL,TF> LT;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsComputation<VT2>, const StaticVector<ET2,3UL,TF>, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecDVecCrossExpr class.
+ //
+ // \param lhs The left-hand side operand of the cross product expression.
+ // \param rhs The right-hand side operand of the cross product expression.
+ */
+ explicit inline SVecDVecCrossExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the cross product expression
+ , rhs_( rhs ) // Right-hand side dense vector of the cross product expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( rhs.size() == 3UL, "Invalid vector size" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..2]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < 3UL, "Invalid vector access index" );
+
+ if( index == 0UL )
+ return lhs_[1UL] * rhs_[2UL] - lhs_[2UL] * rhs_[1UL];
+ else if( index == 1UL )
+ return lhs_[2UL] * rhs_[0UL] - lhs_[0UL] * rhs_[2UL];
+ else
+ return lhs_[0UL] * rhs_[1UL] - lhs_[1UL] * rhs_[0UL];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= 3UL ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline constexpr size_t size() const noexcept {
+ return 3UL;
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the cross product expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the cross product expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT,TF>& lhs, const SVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] = x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] = x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] = x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector cross product to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side cross product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector cross product expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const SVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // dense vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] += x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] += x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] += x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // dense vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] -= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] -= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] -= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-dense vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] *= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] *= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] *= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a sparse vector-dense vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a sparse vector-
+ // dense vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT,TF>& lhs, const SVecDVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ (~lhs)[0] /= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] /= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] /= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Operator for the cross product of a sparse vector and a dense vector
+// (\f$ \vec{a}=\vec{b} \times \vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector for the cross product.
+// \param rhs The right-hand side dense vector for the cross product.
+// \return The cross product of the two vectors.
+// \exception std::invalid_argument Invalid vector size for cross product.
+//
+// This operator represents the cross product of a sparse vector and a dense vector:
+
+ \code
+ blaze::CompressedVector<double> a( 3UL );
+ blaze::DynamicVector<double> b( 3UL );
+ blaze::StaticVector<double,3UL> c;
+ // ... Resizing and initialization
+ c = a % b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the CrossTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const SVecDVecCrossExpr<T1,T2,TF>
+ operator%( const SparseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != 3UL || (~rhs).size() != 3UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" );
+ }
+
+ return SVecDVecCrossExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Cross product of a sparse vector and a dense vector (\f$ \vec{a}=\vec{b} \times \vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector for the cross product.
+// \param rhs The right-hand side dense vector for the cross product.
+// \return The cross product of the two vectors.
+// \exception std::invalid_argument Invalid vector size for cross product.
+//
+// This function computes the cross product of a sparse vector and a dense vector:
+
+ \code
+ blaze::CompressedVector<double> a( 3UL );
+ blaze::DynamicVector<double> b( 3UL );
+ blaze::StaticVector<double,3UL> c;
+ // ... Resizing and initialization
+ c = a % b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the CrossTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const SVecDVecCrossExpr<T1,T2,TF>
+ cross( const SparseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ return lhs % rhs;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< SVecDVecCrossExpr<VT1,VT2,TF> > : public SizeT<3UL>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecDVecDivExpr.h b/src/cpu/blaze/math/expressions/SVecDVecDivExpr.h
new file mode 100644
index 00000000..0b7cea38
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecDVecDivExpr.h
@@ -0,0 +1,774 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecDVecDivExpr.h
+// \brief Header file for the sparse vector/sparse vector division expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECDVECDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECDVECDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecDivExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecVecDivExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECDVECDIVEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-dense vector divisions.
+// \ingroup sparse_vector_expression
+//
+// The SVecDVecDivExpr class represents the compile time expression for componentwise divisions
+// between a sparse vector and a dense vector.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class SVecDVecDivExpr : public SparseVector< SVecDVecDivExpr<VT1,VT2,TF>, TF >
+ , private VecVecDivExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef DivExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Evaluation strategy*************************************************************************
+ //! Compilation switch for the evaluation strategy of the division expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the division expression. In case either the sparse or the
+ dense vector operand requires an intermediate evaluation, \a useAssign will be set to
+ \a true and the division expression will be evaluated via the \a assign function family.
+ Otherwise \a useAssign will be set to \a false and the expression will be evaluated via
+ the subscript operator. */
+ enum : bool { useAssign = ( RequiresEvaluation<VT1>::value || RequiresEvaluation<VT2>::value ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecDVecDivExpr<VT1,VT2,TF> This; //!< Type of this SVecDVecDivExpr instance.
+ typedef DivTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SVecDVecDivExpr& > CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse vector-dense vector division expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse vector expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<LeftOperand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType it, RightOperand vec )
+ : it_ ( it ) // Iterator over the elements of the left-hand side sparse vector expression
+ , vec_( vec ) // Right-hand side dense vector expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( it_->value() / vec_[it_->index()], it_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return it_->value() / vec_[it_->index()];
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator over the elements of the left-hand side sparse vector expression.
+ RightOperand vec_; //!< Right-hand side dense vector expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecDVecDivExpr class.
+ //
+ // \param lhs The left-hand side sparse vector operand of the division expression.
+ // \param rhs The right-hand side dense vector operand of the division expression.
+ */
+ explicit inline SVecDVecDivExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the division expression
+ , rhs_( rhs ) // Right-hand side dense vector of the division expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] / rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( lhs_.begin(), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( lhs_.end(), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return rhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific vector element.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.find( index ), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.lowerBound( index ), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.upperBound( index ), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) ) || ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) ) || ( rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the division expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the division expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( DenseVector<VT,TF>& lhs, const SVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=x.begin(); element!=x.end(); ++element )
+ (~lhs)[element->index()] = element->value() / y[element->index()];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector division to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector division expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( SparseVector<VT,TF>& lhs, const SVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=x.begin(); element!=x.end(); ++element )
+ (~lhs).append( element->index(), element->value() / y[element->index()] );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-dense vector division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // dense vector division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ addAssign( DenseVector<VT,TF>& lhs, const SVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=x.begin(); element!=x.end(); ++element )
+ (~lhs)[element->index()] += element->value() / y[element->index()];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-dense vector division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // dense vector division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case either of the
+ // two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ subAssign( DenseVector<VT,TF>& lhs, const SVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=x.begin(); element!=x.end(); ++element )
+ (~lhs)[element->index()] -= element->value() / y[element->index()];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-dense vector division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-dense vector division expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ multAssign( DenseVector<VT,TF>& lhs, const SVecDVecDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const ConstIterator end( x.end() );
+ ConstIterator begin( x.begin() );
+ size_t i( 0UL );
+
+ for( ; begin!=end; ++begin ) {
+ const size_t index( begin->index() );
+ for( ; i<index; ++i )
+ reset( (~lhs)[i] );
+ (~lhs)[index] *= begin->value() / y[index];
+ ++i;
+ }
+
+ for( ; i<rhs.size(); ++i )
+ reset( (~lhs)[i] );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECDIVEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division operator for the componentwise division of a sparse vector and a dense
+// vector (\f$ \vec{a}=\vec{b}/\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the component product.
+// \param rhs The right-hand side dense vector for the component product.
+// \return The quotient of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the component quotient of a sparse vector and a dense vector:
+
+ \code
+ blaze::CompressedVector<double> a, c;
+ blaze::DynamicVector<double> b;
+ // ... Resizing and initialization
+ c = a / b;
+ \endcode
+
+// The operator returns an expression representing a sparse vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the DivTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const SVecDVecDivExpr<T1,T2,TF>
+ operator/( const SparseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return SVecDVecDivExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< SVecDVecDivExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< SVecDVecDivExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecDVecMultExpr.h b/src/cpu/blaze/math/expressions/SVecDVecMultExpr.h
new file mode 100644
index 00000000..b3f3c788
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecDVecMultExpr.h
@@ -0,0 +1,775 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecDVecMultExpr.h
+// \brief Header file for the sparse vector/sparse vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecVecMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-dense vector multiplications.
+// \ingroup sparse_vector_expression
+//
+// The SVecDVecMultExpr class represents the compile time expression for componentwise
+// multiplications between a sparse vector and a dense vector.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class SVecDVecMultExpr : public SparseVector< SVecDVecMultExpr<VT1,VT2,TF>, TF >
+ , private VecVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Evaluation strategy*************************************************************************
+ //! Compilation switch for the evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the multiplication expression. In case either the sparse or
+ the dense vector operand requires an intermediate evaluation, \a useAssign will be set
+ to \a true and the multiplication expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to \a false and the expression will be
+ evaluated via the subscript operator. */
+ enum : bool { useAssign = ( RequiresEvaluation<VT1>::value || RequiresEvaluation<VT2>::value ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecDVecMultExpr<VT1,VT2,TF> This; //!< Type of this SVecDVecMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SVecDVecMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse vector-dense vector multiplication expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse vector expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<LeftOperand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ElementType ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType it, RightOperand vec )
+ : it_ ( it ) // Iterator over the elements of the left-hand side sparse vector expression
+ , vec_( vec ) // Right-hand side dense vector expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( it_->value() * vec_[it_->index()], it_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return it_->value() * vec_[it_->index()];
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator over the elements of the left-hand side sparse vector expression.
+ RightOperand vec_; //!< Right-hand side dense vector expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecDVecMultExpr class.
+ //
+ // \param lhs The left-hand side sparse vector operand of the multiplication expression.
+ // \param rhs The right-hand side dense vector operand of the multiplication expression.
+ */
+ explicit inline SVecDVecMultExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] * rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( lhs_.begin(), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( lhs_.end(), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return rhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific vector element.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.find( index ), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.lowerBound( index ), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.upperBound( index ), rhs_ );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) ) || ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) ) || ( rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( DenseVector<VT,TF>& lhs, const SVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=x.begin(); element!=x.end(); ++element )
+ (~lhs)[element->index()] = element->value() * y[element->index()];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector multiplication to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector multiplication expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT> >
+ assign( SparseVector<VT,TF>& lhs, const SVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=x.begin(); element!=x.end(); ++element )
+ (~lhs).append( element->index(), element->value() * y[element->index()] );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-dense vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ addAssign( DenseVector<VT,TF>& lhs, const SVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=x.begin(); element!=x.end(); ++element )
+ (~lhs)[element->index()] += element->value() * y[element->index()];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-dense vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // dense vector multiplication expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case either
+ // of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ subAssign( DenseVector<VT,TF>& lhs, const SVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ for( ConstIterator element=x.begin(); element!=x.end(); ++element )
+ (~lhs)[element->index()] -= element->value() * y[element->index()];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-dense vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands requires an intermediate evaluation.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT> >
+ multAssign( DenseVector<VT,TF>& lhs, const SVecDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > ConstIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const ConstIterator end( x.end() );
+ ConstIterator begin( x.begin() );
+ size_t i( 0UL );
+
+ for( ; begin!=end; ++begin ) {
+ const size_t index( begin->index() );
+ for( ; i<index; ++i )
+ reset( (~lhs)[i] );
+ (~lhs)[index] *= begin->value() * y[index];
+ ++i;
+ }
+
+ for( ; i<rhs.size(); ++i )
+ reset( (~lhs)[i] );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECMULTEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the componentwise product of a sparse vector and a dense
+// vector (\f$ \vec{a}=\vec{b}*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the component product.
+// \param rhs The right-hand side dense vector for the component product.
+// \return The product of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the componentwise multiplication of a sparse vector and a dense
+// vector:
+
+ \code
+ blaze::CompressedVector<double> a, c;
+ blaze::DynamicVector<double> b;
+ // ... Resizing and initialization
+ c = a * b;
+ \endcode
+
+// The operator returns an expression representing a sparse vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const SVecDVecMultExpr<T1,T2,TF>
+ operator*( const SparseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return SVecDVecMultExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< SVecDVecMultExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< SVecDVecMultExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecDVecSubExpr.h b/src/cpu/blaze/math/expressions/SVecDVecSubExpr.h
new file mode 100644
index 00000000..05d950ff
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecDVecSubExpr.h
@@ -0,0 +1,893 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecDVecSubExpr.h
+// \brief Header file for the sparse vector/dense vector subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECDVECSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECDVECSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecSubExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecVecSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECDVECSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-dense vector subtractions.
+// \ingroup dense_vector_expression
+//
+// The SVecDVecSubExpr class represents the compile time expression for subtractions between
+// a sparse vector and a dense vector.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class SVecDVecSubExpr : public DenseVector< SVecDVecSubExpr<VT1,VT2,TF>, TF >
+ , private VecVecSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ typedef TransposeType_<VT1> TT1; //!< Transpose type of the left-hand side sparse vector expression.
+ typedef TransposeType_<VT2> TT2; //!< Transpose type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two vector operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT1::smpAssignable || !VT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecDVecSubExpr<VT1,VT2,TF> This; //!< Type of this SVecDVecSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecDVecSubExpr class.
+ //
+ // \param lhs The left-hand side sparse vector operand of the subtraction expression.
+ // \param rhs The right-hand side dense vector operand of the subtraction expression.
+ */
+ explicit inline SVecDVecSubExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the subtraction expression
+ , rhs_( rhs ) // Right-hand side dense vector of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] - rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) ) ||
+ ( IsExpression<VT2>::value && rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign ( ~lhs, -rhs.rhs_ );
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector addition to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector addition expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // dense vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.rhs_ );
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // dense vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.rhs_ );
+ subAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-dense vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a sparse vector-
+ // dense vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector-dense
+ // vector subtraction expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign ( ~lhs, -rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector-dense vector addition to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector-dense
+ // vector addition expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAssign( SparseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector-dense vector subtraction expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector-dense vector subtraction expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector-dense vector subtraction to a
+ // dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // sparse vector-dense vector subtraction expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a sparse vector-dense vector subtraction to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a sparse
+ // vector-dense vector subtraction expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpDivAssign( DenseVector<VT,TF>& lhs, const SVecDVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECSUBEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a sparse vector and a dense vector
+// (\f$ \vec{a}=\vec{b}-\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector for the vector subtraction.
+// \param rhs The right-hand side dense vector to be subtracted from the sparse vector.
+// \return The difference of the two vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the subtraction of a sparse vector and a dense vector:
+
+ \code
+ blaze::CompressedVector<double> a;
+ blaze::DynamicVector<double> b, c;
+ // ... Resizing and initialization
+ c = a - b;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved vector element types \a T1::ElementType and \a T2::ElementType.
+// Both vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+inline const SVecDVecSubExpr<T1,T2,TF>
+ operator-( const SparseVector<T1,TF>& lhs, const DenseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return SVecDVecSubExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a sparse vector-dense vector subtraction
+// expression and a dense vector (\f$ \vec{a}=(\vec{b}-\vec{c})+\vec{d} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector-dense vector subtraction.
+// \param rhs The right-hand side dense vector.
+// \return The sum of the two vectors.
+//
+// This operator implements a performance optimized treatment of the addition of a sparse
+// vector-dense vector subtraction expression to a dense vector.
+*/
+template< typename T1 // Type of the sparse vector of the left-hand side expression
+ , typename T2 // Type of the dense vector of the left-hand side expression
+ , bool TF // Transpose flag of the left-hand side expression
+ , typename T3 > // Type of right-hand side dense vector
+inline const AddExprTrait_< SVecDVecSubExpr<T1,T2,TF>, T3 >
+ operator+( const SVecDVecSubExpr<T1,T2,TF>& lhs, const DenseVector<T3,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~rhs) - lhs.rightOperand() ) + lhs.leftOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a sparse vector-dense vector subtraction
+// expression and a dense vector (\f$ \vec{a}=(\vec{b}-\vec{c})-\vec{d} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector-dense vector subtraction.
+// \param rhs The right-hand side dense vector.
+// \return The difference of the two vectors.
+//
+// This operator implements a performance optimized treatment of the subtraction of a
+// sparse vector-dense vector subtraction expression and a dense vector.
+*/
+template< typename T1 // Type of the sparse vector of the left-hand side expression
+ , typename T2 // Type of the dense vector of the left-hand side expression
+ , bool TF // Transpose flag of the left-hand side expression
+ , typename T3 > // Type of right-hand side dense vector
+inline const SubExprTrait_< SVecDVecSubExpr<T1,T2,TF>, T3 >
+ operator-( const SVecDVecSubExpr<T1,T2,TF>& lhs, const DenseVector<T3,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return lhs.leftOperand() - ( lhs.rightOperand() + (~rhs) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< SVecDVecSubExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct DVecDVecAddExprTrait< SVecDVecSubExpr<VT1,VT2,false>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2>
+ , IsDenseVector<VT3>, IsColumnVector<VT3> >
+ , DVecSVecAddExprTrait_< DVecDVecSubExprTrait_<VT3,VT2>, VT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct TDVecTDVecAddExprTrait< SVecDVecSubExpr<VT1,VT2,true>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsDenseVector<VT3>, IsRowVector<VT3> >
+ , TDVecTSVecAddExprTrait_< TDVecTDVecSubExprTrait_<VT3,VT2>, VT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct DVecDVecSubExprTrait< SVecDVecSubExpr<VT1,VT2,false>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2>
+ , IsDenseVector<VT3>, IsColumnVector<VT3> >
+ , SVecDVecSubExprTrait_< VT1, DVecDVecAddExprTrait_<VT2,VT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename VT3 >
+struct TDVecTDVecSubExprTrait< SVecDVecSubExpr<VT1,VT2,true>, VT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsDenseVector<VT3>, IsRowVector<VT3> >
+ , TSVecTDVecSubExprTrait_< VT1, TDVecTDVecAddExprTrait_<VT2,VT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< SVecDVecSubExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecEvalExpr.h b/src/cpu/blaze/math/expressions/SVecEvalExpr.h
new file mode 100644
index 00000000..0da32e3b
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecEvalExpr.h
@@ -0,0 +1,749 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecEvalExpr.h
+// \brief Header file for the sparse vector evaluation expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECEVALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecEvalExpr.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/traits/EvalExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/SVecEvalExprTrait.h>
+#include <blaze/math/traits/TSVecEvalExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECEVALEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the forced evaluation of sparse vectors.
+// \ingroup sparse_vector_expression
+//
+// The SVecEvalExpr class represents the compile time expression for the forced evaluation
+// of a sparse vector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+class SVecEvalExpr : public SparseVector< SVecEvalExpr<VT,TF>, TF >
+ , private VecEvalExpr
+ , private Computation
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecEvalExpr<VT,TF> This; //!< Type of this SVecEvalExpr instance.
+ typedef ResultType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecEvalExpr class.
+ //
+ // \param sv The sparse vector operand of the evaluation expression.
+ */
+ explicit inline SVecEvalExpr( const VT& sv ) noexcept
+ : sv_( sv ) // Sparse vector of the evaluation expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < sv_.size(), "Invalid vector access index" );
+ return sv_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= sv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return sv_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return sv_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the sparse vector operand.
+ //
+ // \return The sparse vector operand.
+ */
+ inline Operand operand() const noexcept {
+ return sv_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return sv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return sv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return sv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand sv_; //!< Sparse vector of the evaluation expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector evaluation
+ // expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector evaluation
+ // expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector
+ // evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector
+ // evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void addAssign( SparseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void subAssign( SparseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void multAssign( SparseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector
+ // evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpAssign( DenseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector
+ // evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpAssign( SparseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpAddAssign( DenseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpAddAssign( SparseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpSubAssign( DenseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpSubAssign( SparseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpMultAssign( DenseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpMultAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpMultAssign( SparseVector<VT2,TF>& lhs, const SVecEvalExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpMultAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Forces the evaluation of the given sparse vector expression \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The evaluated sparse vector.
+//
+// The \a eval function forces the evaluation of the given sparse vector expression \a sv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a eval function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = eval( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const SVecEvalExpr<VT,TF> eval( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecEvalExpr<VT,TF>( ~sv );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Evaluation of the given sparse vector evaluation expression \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input evaluation expression.
+// \return The evaluated sparse vector.
+//
+// This function implements a performance optimized treatment of the evaluation of a sparse vector
+// evaluation expression.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecEvalExpr<VT,TF> eval( const SVecEvalExpr<VT,TF>& sv )
+{
+ return sv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct Size< SVecEvalExpr<VT,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct SVecEvalExprTrait< SVecEvalExpr<VT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecEvalExpr<VT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TSVecEvalExprTrait< SVecEvalExpr<VT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecEvalExpr<VT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF, bool AF >
+struct SubvectorExprTrait< SVecEvalExpr<VT,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = EvalExprTrait_< SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecForEachExpr.h b/src/cpu/blaze/math/expressions/SVecForEachExpr.h
new file mode 100644
index 00000000..8f68fb83
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecForEachExpr.h
@@ -0,0 +1,2059 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecForEachExpr.h
+// \brief Header file for the sparse vector for-each expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECFOREACHEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecForEachExpr.h>
+#include <blaze/math/Functors.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/CTransExprTrait.h>
+#include <blaze/math/traits/ForEachExprTrait.h>
+#include <blaze/math/traits/ForEachTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECFOREACHEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the sparse vector forEach() function.
+// \ingroup sparse_vector_expression
+//
+// The SVecForEachExpr class represents the compile time expression for the evaluation of a
+// custom operation on each element of a sparse vector via the forEach() function.
+*/
+template< typename VT // Type of the sparse vector
+ , typename OP // Type of the custom operation
+ , bool TF > // Transpose flag
+class SVecForEachExpr : public SparseVector< SVecForEachExpr<VT,OP,TF>, TF >
+ , private VecForEachExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> RT; //!< Result type of the sparse vector expression.
+ typedef ReturnType_<VT> RN; //!< Return type of the sparse vector expression.
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the for-each expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for the
+ serial evaluation strategy of the for-each expression. In case the given sparse vector
+ expression of type \a VT requires an intermediate evaluation, \a useAssign will be set
+ to 1 and the for-each expression will be evaluated via the \a assign function family.
+ Otherwise \a useAssign will be set to 0 and the expression will be evaluated via the
+ subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<VT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target vector or the sparse vector operand is not SMP
+ assignable and the vector operand requires an intermediate evaluation, \a value is set
+ to 1 and the expression specific evaluation strategy is selected. Otherwise \a value is
+ set to 0 and the default strategy is chosen. */
+ template< typename VT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT2::smpAssignable || !VT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecForEachExpr<VT,OP,TF> This; //!< Type of this SVecForEachExpr instance.
+ typedef ForEachTrait_<VT,OP> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef decltype( std::declval<OP>()( std::declval<RN>() ) ) ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SVecForEachExpr& > CompositeType;
+
+ //! Composite data type of the sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > Operand;
+
+ //! Data type of the custom unary operation.
+ typedef OP Operation;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse vector for-each expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse vector expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<Operand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ //
+ // \param it Iterator to the initial vector element.
+ // \param op The custom unary operation.
+ */
+ inline ConstIterator( IteratorType it, OP op )
+ : it_( it ) // Iterator over the elements of the sparse vector expression
+ , op_( op ) // The custom unary operation
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( op_( it_->value() ), it_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return op_( it_->value() );
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator over the elements of the sparse vector expression.
+ OP op_; //!< The custom unary operation.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecForEachExpr class.
+ //
+ // \param sv The sparse vector operand of the for-each expression.
+ // \param op The custom unary operation.
+ */
+ explicit inline SVecForEachExpr( const VT& sv, OP op ) noexcept
+ : sv_( sv ) // Sparse vector of the for-each expression
+ , op_( op ) // The custom unary operation
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < sv_.size(), "Invalid vector access index" );
+ return op_( sv_[index] );
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= sv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( sv_.begin(), op_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( sv_.end(), op_ );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return sv_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return sv_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific vector element.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( sv_.find( index ), op_ );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( sv_.lowerBound( index ), op_ );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( sv_.upperBound( index ), op_ );
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the sparse vector operand.
+ //
+ // \return The sparse vector operand.
+ */
+ inline Operand operand() const noexcept {
+ return sv_;
+ }
+ //**********************************************************************************************
+
+ //**Operation access****************************************************************************
+ /*!\brief Returns a copy of the custom operation.
+ //
+ // \return A copy of the custom operation.
+ */
+ inline Operation operation() const {
+ return op_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return sv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return sv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return sv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand sv_; //!< Sparse vector of the for-each expression.
+ Operation op_; //!< The custom unary operation.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector for-each expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector for-each
+ // expression to a dense vector. Due to the explicit application of the SFINAE principle, this
+ // function can only be selected by the compiler in case the operand requires an intermediate
+ // evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.sv_ ) );
+ assign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector for-each expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector for-each
+ // expression to a sparse vector. Due to the explicit application of the SFINAE principle, this
+ // function can only be selected by the compiler in case the operand requires an intermediate
+ // evaluation and the underlying numeric data type of the operand and the target vector are
+ // identical.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< And< UseAssign<VT2>
+ , IsSame< UnderlyingNumeric<VT>, UnderlyingNumeric<VT2> > > >
+ assign( SparseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef Iterator_<VT2> Iterator;
+
+ assign( ~lhs, rhs.sv_ );
+
+ const Iterator end( (~lhs).end() );
+ for( Iterator element=(~lhs).begin(); element!=end; ++element ) {
+ element->value() = rhs.op_( element->value() );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector for-each expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector for-each
+ // expression to a sparse vector. Due to the explicit application of the SFINAE principle, this
+ // function can only be selected by the compiler in case the operand requires an intermediate
+ // evaluation and the underlying numeric data type of the operand and the target vector differ.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< And< UseAssign<VT2>
+ , Not< IsSame< UnderlyingNumeric<VT>, UnderlyingNumeric<VT2> > > > >
+ assign( SparseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.sv_ ) );
+ (~lhs).reserve( tmp.nonZeros() );
+ assign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector for-each expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector
+ // for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand requires
+ // an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.sv_ ) );
+ addAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector for-each expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // vector for-each expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.sv_ ) );
+ subAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector for-each expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the operand requires
+ // an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( serial( rhs.sv_ ) );
+ multAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector for-each expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector
+ // for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.sv_ );
+ smpAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector for-each expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector for-each expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.sv_ );
+ smpAddAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector for-each expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector for-each expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.sv_ );
+ smpSubAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector for-each expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side for-each expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // sparse vector for-each expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,TF>& lhs, const SVecForEachExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( RT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<RT> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const RT tmp( rhs.sv_ );
+ smpMultAssign( ~lhs, forEach( tmp, rhs.op_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluates the given custom operation on each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \param op The custom operation.
+// \return The custom operation applied to each single element of \a sv.
+//
+// The \a forEach() function evaluates the given custom operation on each non-zero element of the
+// input vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a forEach() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = forEach( a, []( double a ){ return std::sqrt( a ); } );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF // Transpose flag
+ , typename OP > // Type of the custom operation
+inline const SVecForEachExpr<VT,OP,TF> forEach( const SparseVector<VT,TF>& sv, OP op )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,OP,TF>( ~sv, op );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a abs() function to each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The resulting sparse vector.
+//
+// This function applies the \a abs() function to each non-zero element of the input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a abs() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = abs( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Abs,TF> abs( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Abs,TF>( ~sv, Abs() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a floor() function to each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The resulting sparse vector.
+//
+// This function applies the \a floor() function to each non-zero element of the input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a floor() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = floor( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Floor,TF> floor( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Floor,TF>( ~sv, Floor() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Applies the \a ceil() function to each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The resulting sparse vector.
+//
+// This function applies the \a ceil() function to each non-zero element of the input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a ceil() function:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ // ... Resizing and initialization
+ b = ceil( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Ceil,TF> ceil( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Ceil,TF>( ~sv, Ceil() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a vector containing the complex conjugate of each single element of \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The integral sparse input vector.
+// \return The complex conjugate of each single element of \a sv.
+//
+// The \a conj function calculates the complex conjugate of each element of the sparse input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a conj function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = conj( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Conj,TF> conj( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Conj,TF>( ~sv, Conj() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the conjugate transpose vector of \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The conjugate transpose of \a sv.
+//
+// The \a ctrans function returns an expression representing the conjugate transpose (also called
+// adjoint matrix, Hermitian conjugate matrix or transjugate matrix) of the given input vector
+// \a sv.\n
+// The following example demonstrates the use of the \a ctrans function:
+
+ \code
+ blaze::CompressedVector< complex<double> > a, b;
+ // ... Resizing and initialization
+ b = ctrans( a );
+ \endcode
+
+// Note that the \a ctrans function has the same effect as manually applying the \a conj and
+// \a trans function in any order:
+
+ \code
+ b = trans( conj( a ) ); // Computing the conjugate transpose vector
+ b = conj( trans( a ) ); // Computing the conjugate transpose vector
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const CTransExprTrait_<VT> ctrans( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return trans( conj( ~sv ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a vector containing the real parts of each single element of \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The integral sparse input vector.
+// \return The real part of each single element of \a sv.
+//
+// The \a real function calculates the real part of each element of the sparse input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a real function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = real( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Real,TF> real( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Real,TF>( ~sv, Real() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a vector containing the imaginary parts of each single element of \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The integral sparse input vector.
+// \return The imaginary part of each single element of \a sv.
+//
+// The \a imag function calculates the imaginary part of each element of the sparse input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a imag function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = imag( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Imag,TF> imag( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Imag,TF>( ~sv, Imag() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the square root of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[0..\infty)\f$.
+// \return The square root of each single element of \a sv.
+//
+// The \a sqrt() function computes the square root of each non-zero element of the input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sqrt() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = sqrt( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Sqrt,TF> sqrt( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Sqrt,TF>( ~sv, Sqrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse square root of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$(0..\infty)\f$.
+// \return The inverse square root of each single element of \a sv.
+//
+// The \a invsqrt() function computes the inverse square root of each non-zero element of the
+// input vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a invsqrt() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = invsqrt( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$(0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,InvSqrt,TF> invsqrt( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,InvSqrt,TF>( ~sv, InvSqrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the cubic root of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[0..\infty)\f$.
+// \return The cubic root of each single element of \a sv.
+//
+// The \a cbrt() function computes the cubic root of each non-zero element of the input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cbrt() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = cbrt( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Cbrt,TF> cbrt( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Cbrt,TF>( ~sv, Cbrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cubic root of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$(0..\infty)\f$.
+// \return The inverse cubic root of each single element of \a sv.
+//
+// The \a invcbrt() function computes the inverse cubic root of each non-zero element of the
+// input vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a invcbrt() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = invcbrt( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$(0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,InvCbrt,TF> invcbrt( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,InvCbrt,TF>( ~sv, InvCbrt() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the exponential value for each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \param exp The exponent.
+// \return The exponential value of each non-zero element of \a sv.
+//
+// The \a pow() function computes the exponential value for each non-zero element of the input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a pow() function:
+
+ \code
+ blaze::DynamicVector<double> A, B;
+ // ... Resizing and initialization
+ B = pow( A, 4.2 );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF // Transpose flag
+ , typename ET > // Type of the exponent
+inline const SVecForEachExpr<VT,Pow<ET>,TF> pow( const SparseVector<VT,TF>& sv, ET exp )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET );
+
+ return SVecForEachExpr<VT,Pow<ET>,TF>( ~sv, Pow<ET>( exp ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes \f$ e^x \f$ of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The resulting sparse vector.
+//
+// The \a exp() function computes \f$ e^x \f$ for each non-zero element of the input vector \a sv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a exp() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = exp( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Exp,TF> exp( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Exp,TF>( ~sv, Exp() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the natural logarithm of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[0..\infty)\f$.
+// \return The natural logaritm of each non-zero element of \a sv.
+//
+// The \a log() function computes the natural logarithm for each non-zero element of the input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a log() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = log( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Log,TF> log( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Log,TF>( ~sv, Log() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the common logarithm of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[0..\infty)\f$.
+// \return The common logaritm of each non-zero element of \a sv.
+//
+// The \a log10() function computes the common logarithm for each non-zero element of the input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a log10() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = log10( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[0..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Log10,TF> log10( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Log10,TF>( ~sv, Log10() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the sine of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The sine of each non-zero element of \a sv.
+//
+// The \a sin() function computes the sine for each non-zero element of the input vector \a sv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sin() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = sin( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Sin,TF> sin( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Sin,TF>( ~sv, Sin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse sine of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[-1..1]\f$.
+// \return The inverse sine of each non-zero element of \a sv.
+//
+// The \a asin() function computes the inverse sine for each non-zero element of the input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a asin() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = asin( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[-1..1]\f$. No runtime checks
+// are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Asin,TF> asin( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Asin,TF>( ~sv, Asin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic sine of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The hyperbolic sine of each non-zero element of \a sv.
+//
+// The \a sinh() function computes the hyperbolic sine for each non-zero element of the input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a sinh() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = sinh( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Sinh,TF> sinh( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Sinh,TF>( ~sv, Sinh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic sine of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The inverse hyperbolic sine of each non-zero element of \a sv.
+//
+// The \a asinh() function computes the inverse hyperbolic sine for each non-zero element of the
+// input vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a asinh() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = asinh( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Asinh,TF> asinh( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Asinh,TF>( ~sv, Asinh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the cosine of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The cosine of each non-zero element of \a sv.
+//
+// The \a cos() function computes the cosine for each non-zero element of the input vector \a sv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cos() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = cos( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Cos,TF> cos( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Cos,TF>( ~sv, Cos() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cosine of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[-1..1]\f$.
+// \return The inverse cosine of each non-zero element of \a sv.
+//
+// The \a acos() function computes the inverse cosine for each non-zero element of the input vector
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a acos() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = acos( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[-1..1]\f$. No runtime checks
+// are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Acos,TF> acos( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Acos,TF>( ~sv, Acos() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic cosine of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The hyperbolic cosine of each non-zero element of \a sv.
+//
+// The \a cosh() function computes the hyperbolic cosine for each non-zero element of the input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a cosh() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = cosh( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Cosh,TF> cosh( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Cosh,TF>( ~sv, Cosh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic cosine of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[1..\infty)\f$.
+// \return The inverse hyperbolic cosine of each non-zero element of \a sv.
+//
+// The \a acosh() function computes the inverse hyperbolic cosine for each non-zero element of
+// the input vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a acosh() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = acosh( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[1..\infty)\f$. No runtime
+// checks are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Acosh,TF> acosh( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Acosh,TF>( ~sv, Acosh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the tangent of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The tangent of each non-zero element of \a sv.
+//
+// The \a tan() function computes the tangent for each non-zero element of the input vector \a sv.
+// The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a tan() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = tan( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Tan,TF> tan( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Tan,TF>( ~sv, Tan() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse tangent of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The inverse tangent of each non-zero element of \a sv.
+//
+// The \a atan() function computes the inverse tangent for each non-zero element of the input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a atan() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = atan( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Atan,TF> atan( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Atan,TF>( ~sv, Atan() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the hyperbolic tangent of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[-1..1]\f$.
+// \return The hyperbolic tangent of each non-zero element of \a sv.
+//
+// The \a tanh() function computes the hyperbolic tangent for each non-zero element of the input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a tanh() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = tanh( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[-1..1]\f$. No runtime checks
+// are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Tanh,TF> tanh( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Tanh,TF>( ~sv, Tanh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the inverse hyperbolic tangent of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector; all non-zero elements must be in the range \f$[-1..1]\f$.
+// \return The inverse hyperbolic tangent of each non-zero element of \a sv.
+//
+// The \a atanh() function computes the inverse hyperbolic tangent for each non-zero element of
+// the input vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a atanh() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = atanh( a );
+ \endcode
+
+// \note All non-zero elements are expected to be in the range \f$[-1..1]\f$. No runtime checks
+// are performed to assert this precondition!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Atanh,TF> atanh( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Atanh,TF>( ~sv, Atanh() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the error function of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The error function of each non-zero element of \a sv.
+//
+// The \a erf() function computes the error function for each non-zero element of the input
+// vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a erf() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = erf( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Erf,TF> erf( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Erf,TF>( ~sv, Erf() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the complementary error function of each non-zero element of the sparse vector \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The complementary error function of each non-zero element of \a sv.
+//
+// The \a erfc() function computes the complementary error function for each non-zero element of
+// the input vector \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a erfc() function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = erfc( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Erfc,TF> erfc( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecForEachExpr<VT,Erfc,TF>( ~sv, Erfc() );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Absolute value function for absolute value sparse vector expressions.
+// \ingroup sparse_vector
+//
+// \param sv The absolute value sparse vector expression.
+// \return The absolute value of each single element of \a sv.
+//
+// This function implements a performance optimized treatment of the absolute value operation
+// on a sparse vector absolute value expression.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Abs,TF>& abs( const SVecForEachExpr<VT,Abs,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Applies the \a floor() function to a sparse vector \a floor() expressions.
+// \ingroup sparse_vector
+//
+// \param sv The sparse vector \a floor expression.
+// \return The resulting sparse vector.
+//
+// This function implements a performance optimized treatment of the \a floor() operation on
+// a sparse vector \a floor() expression.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Floor,TF>& floor( const SVecForEachExpr<VT,Floor,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Applies the \a ceil() function to a sparse vector \a ceil() expressions.
+// \ingroup sparse_vector
+//
+// \param sv The sparse vector \a ceil expression.
+// \return The resulting sparse vector.
+//
+// This function implements a performance optimized treatment of the \a ceil() operation on
+// a sparse vector \a ceil() expression.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Ceil,TF>& ceil( const SVecForEachExpr<VT,Ceil,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Complex conjugate function for complex conjugate sparse vector expressions.
+// \ingroup sparse_vector
+//
+// \param sv The complex conjugate sparse vector expression.
+// \return The original sparse vector.
+//
+// This function implements a performance optimized treatment of the complex conjugate operation
+// on a sparse vector complex conjugate expression. It returns an expression representing the
+// original sparse vector:
+
+ \code
+ blaze::CompressedVector< complex<double> > a, b;
+ // ... Resizing and initialization
+ b = conj( conj( a ) );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline typename SVecForEachExpr<VT,Conj,TF>::Operand conj( const SVecForEachExpr<VT,Conj,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sv.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Complex conjugate function for conjugate transpose sparse vector expressions.
+// \ingroup sparse_vector
+//
+// \param sv The conjugate transpose sparse vector expression.
+// \return The transpose sparse vector.
+//
+// This function implements a performance optimized treatment of the complex conjugate operation
+// on a sparse vector conjugate transpose expression. It returns an expression representing the
+// transpose of the sparse vector:
+
+ \code
+ blaze::CompressedVector< complex<double> > a, b;
+ // ... Resizing and initialization
+ b = conj( ctrans( a ) );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecTransExpr<VT,!TF> conj( const SVecTransExpr<SVecForEachExpr<VT,Conj,TF>,!TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecTransExpr<VT,!TF>( sv.operand().operand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Real part function for real part sparse vector expressions.
+// \ingroup sparse_vector
+//
+// \param sv The real part sparse vector expression.
+// \return The real part of each single element of \a sv.
+//
+// This function implements a performance optimized treatment of the real part operation on
+// a sparse vector real part expression.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecForEachExpr<VT,Real,TF>& real( const SVecForEachExpr<VT,Real,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename OP, bool TF >
+struct Size< SVecForEachExpr<VT,OP,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct SVecForEachExprTrait< SVecForEachExpr<VT,Abs,false>, Abs >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecForEachExpr<VT,Abs,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TSVecForEachExprTrait< SVecForEachExpr<VT,Abs,true>, Abs >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecForEachExpr<VT,Abs,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct SVecForEachExprTrait< SVecForEachExpr<VT,Conj,false>, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , Operand_< SVecForEachExpr<VT,Conj,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TSVecForEachExprTrait< SVecForEachExpr<VT,Conj,true>, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , Operand_< SVecForEachExpr<VT,Conj,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct SVecForEachExprTrait< SVecTransExpr< SVecForEachExpr<VT,Conj,true>, false >, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecTransExpr<VT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TSVecForEachExprTrait< SVecTransExpr< SVecForEachExpr<VT,Conj,false>, true >, Conj >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecTransExpr<VT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct SVecForEachExprTrait< SVecForEachExpr<VT,Real,false>, Real >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecForEachExpr<VT,Real,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TSVecForEachExprTrait< SVecForEachExpr<VT,Real,true>, Real >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecForEachExpr<VT,Real,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename OP, bool TF, bool AF >
+struct SubvectorExprTrait< SVecForEachExpr<VT,OP,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = ForEachExprTrait_< SubvectorExprTrait_<const VT,AF>, OP >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecSVecAddExpr.h b/src/cpu/blaze/math/expressions/SVecSVecAddExpr.h
new file mode 100644
index 00000000..581137f2
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecSVecAddExpr.h
@@ -0,0 +1,728 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecSVecAddExpr.h
+// \brief Header file for the sparse vector/sparse vector addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECSVECADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECSVECADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecAddExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecVecAddExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECSVECADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-sparse vector additions.
+// \ingroup sparse_vector_expression
+//
+// The SVecSVecAddExpr class represents the compile time expression for additions between
+// sparse vectors.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class SVecSVecAddExpr : public SparseVector< SVecSVecAddExpr<VT1,VT2,TF>, TF >
+ , private VecVecAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target vector is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = VT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecSVecAddExpr<VT1,VT2,TF> This; //!< Type of this SVecSVecAddExpr instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecSVecAddExpr class.
+ */
+ explicit inline SVecSVecAddExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the addition expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] + rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return min( lhs_.size(), lhs_.nonZeros() + rhs_.nonZeros() );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the addition expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the addition expression.
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a sparse vector-sparse vector addition to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a sparse vector-sparse vector
+ // addition expression to a dense vector. This function is used in case the element
+ // type is resizable.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< IsResizable< ElementType_<VT> > >
+ assign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( LeftIterator l=x.begin(); l!=lend; ++l ) {
+ (~lhs)[l->index()] = l->value();
+ }
+
+ for( RightIterator r=y.begin(); r!=rend; ++r ) {
+ if( isDefault( (~lhs)[r->index()] ) )
+ (~lhs)[r->index()] = r->value();
+ else
+ (~lhs)[r->index()] += r->value();
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a sparse vector-sparse vector addition to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector addition expression to a dense vector. This function is used in case the element
+ // type is not resizable.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline DisableIf_< IsResizable< ElementType_<VT> > >
+ assign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( LeftIterator l=x.begin(); l!=lend; ++l ) {
+ (~lhs)[l->index()] = l->value();
+ }
+
+ for( RightIterator r=y.begin(); r!=rend; ++r ) {
+ (~lhs)[r->index()] += r->value();
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector addition to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector addition expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ LeftIterator l( x.begin() );
+ RightIterator r( y.begin() );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), l->value() + r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), r->value() );
+ ++r;
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-sparse vector addition to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // sparse vector addition expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-sparse vector addition to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // sparse vector addition expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-sparse vector addition to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-sparse vector addition expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ // No special implementation for the SMP assignment to dense vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector-sparse vector addition to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector-sparse vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector-sparse vector addition to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector-sparse vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector-sparse vector addition to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side addition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector-sparse vector addition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECADDEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of two sparse vectors (\f$ \vec{a}=\vec{b}+\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the vector addition.
+// \param rhs The right-hand side sparse vector for the vector addition.
+// \return The sum of the two sparse vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the addition of two sparse vectors:
+
+ \code
+ blaze::CompressedVector<double> a, b, c;
+ // ... Resizing and initialization
+ c = a + b;
+ \endcode
+
+// The operator returns a sparse vector of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const SVecSVecAddExpr<T1,T2,TF>
+ operator+( const SparseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return SVecSVecAddExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< SVecSVecAddExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< SVecSVecAddExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecSVecCrossExpr.h b/src/cpu/blaze/math/expressions/SVecSVecCrossExpr.h
new file mode 100644
index 00000000..51cea356
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecSVecCrossExpr.h
@@ -0,0 +1,569 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecSVecCrossExpr.h
+// \brief Header file for the sparse vector/sparse vector cross product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECSVECCROSSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECSVECCROSSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/dense/Forward.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/CrossExpr.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECSVECCROSSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-sparse vector cross products.
+// \ingroup dense_vector_expression
+//
+// The SVecSVecCrossExpr class represents the compile time expression for cross products
+// between sparse vectors.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class SVecSVecCrossExpr : public DenseVector< SVecSVecCrossExpr<VT1,VT2,TF>, TF >
+ , private CrossExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side sparse vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_< MultExprTrait_<RN1,RN2>, MultExprTrait_<RN1,RN2> > ExprReturnType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecSVecCrossExpr<VT1,VT2,TF> This; //!< Type of this SVecSVecCrossExpr instance.
+ typedef CrossTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef const StaticVector<ET1,3UL,TF> LT;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef const StaticVector<ET2,3UL,TF> RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecSVecCrossExpr class.
+ //
+ // \param lhs The left-hand side operand of the cross product expression.
+ // \param rhs The right-hand side operand of the cross product expression.
+ */
+ explicit inline SVecSVecCrossExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the cross product expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the cross product expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( rhs.size() == 3UL, "Invalid vector size" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..2]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < 3UL, "Invalid vector access index" );
+
+ if( index == 0UL )
+ return lhs_[1UL] * rhs_[2UL] - lhs_[2UL] * rhs_[1UL];
+ else if( index == 1UL )
+ return lhs_[2UL] * rhs_[0UL] - lhs_[0UL] * rhs_[2UL];
+ else
+ return lhs_[0UL] * rhs_[1UL] - lhs_[1UL] * rhs_[0UL];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= 3UL ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline constexpr size_t size() const noexcept {
+ return 3UL;
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the cross product expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the cross product expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT,TF>& lhs, const SVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] = x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] = x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] = x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector cross product to a sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side cross product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector cross product expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const SVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // sparse vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] += x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] += x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] += x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // sparse vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] -= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] -= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] -= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-sparse vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] *= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] *= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] *= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a sparse vector-sparse vector cross product to a dense vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side cross product expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a sparse vector-
+ // sparse vector cross product expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT,TF>& lhs, const SVecSVecCrossExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == 3UL, "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() == 3UL, "Invalid vector size" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ (~lhs)[0] /= x[1UL]*y[2UL] - x[2UL]*y[1UL];
+ (~lhs)[1] /= x[2UL]*y[0UL] - x[0UL]*y[2UL];
+ (~lhs)[2] /= x[0UL]*y[1UL] - x[1UL]*y[0UL];
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Operator for the cross product of two sparse vectors (\f$ \vec{a}=\vec{b} \times \vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector for the cross product.
+// \param rhs The right-hand side sparse vector for the cross product.
+// \return The cross product of the two sparse vectors.
+// \exception std::invalid_argument Invalid vector size for cross product.
+//
+// This operator represents the cross product of two sparse vectors:
+
+ \code
+ blaze::CompressedVector<double> a( 3UL ), b( 3UL );
+ blaze::StaticVector<double,3UL> c;
+ // ... Resizing and initialization
+ c = a % b;
+ \endcode
+
+// The operator returns a dense vector of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the CrossTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const SVecSVecCrossExpr<T1,T2,TF>
+ operator%( const SparseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != 3UL || (~rhs).size() != 3UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" );
+ }
+
+ return SVecSVecCrossExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Cross product of two sparse vectors (\f$ \vec{a}=\vec{b} \times \vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side sparse vector for the cross product.
+// \param rhs The right-hand side sparse vector for the cross product.
+// \return The cross product of the two sparse vectors.
+// \exception std::invalid_argument Invalid vector size for cross product.
+//
+// This function computes the cross product of two sparse vectors:
+
+ \code
+ blaze::CompressedVector<double> a( 3UL ), b( 3UL );
+ blaze::StaticVector<double,3UL> c;
+ // ... Resizing and initialization
+ c = a % b;
+ \endcode
+
+// The operator returns a dense vector of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the CrossTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const SVecSVecCrossExpr<T1,T2,TF>
+ cross( const SparseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ return lhs % rhs;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< SVecSVecCrossExpr<VT1,VT2,TF> > : public SizeT<3UL>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecSVecMultExpr.h b/src/cpu/blaze/math/expressions/SVecSVecMultExpr.h
new file mode 100644
index 00000000..b957d771
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecSVecMultExpr.h
@@ -0,0 +1,662 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecSVecMultExpr.h
+// \brief Header file for the sparse vector/sparse vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecVecMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECSVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-sparse vector multiplications.
+// \ingroup sparse_vector_expression
+//
+// The SVecSVecMultExpr class represents the compile time expression for componentwise
+// multiplications between sparse vectors.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class SVecSVecMultExpr : public SparseVector< SVecSVecMultExpr<VT1,VT2,TF>, TF >
+ , private VecVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecSVecMultExpr<VT1,VT2,TF> This; //!< Type of this SVecSVecMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecSVecMultExpr class.
+ */
+ explicit inline SVecSVecMultExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] * rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return min( lhs_.nonZeros(), rhs_.nonZeros() );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector multiplication expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ LeftIterator l( x.begin() );
+ RightIterator r( y.begin() );
+
+ for( ; l!=lend; ++l ) {
+ while( r!=rend && r->index() < l->index() ) ++r;
+ if( r==rend ) break;
+ if( l->index() == r->index() ) {
+ (~lhs)[l->index()] = l->value() * r->value();
+ ++r;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector multiplication to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector multiplication expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ LeftIterator l( x.begin() );
+ RightIterator r( y.begin() );
+
+ for( ; l!=lend; ++l ) {
+ while( r!=rend && r->index() < l->index() ) ++r;
+ if( r==rend ) break;
+ if( l->index() == r->index() ) {
+ (~lhs).append( l->index(), l->value() * r->value() );
+ ++r;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ LeftIterator l( x.begin() );
+ RightIterator r( y.begin() );
+
+ for( ; l!=lend; ++l ) {
+ while( r!=rend && r->index() < l->index() ) ++r;
+ if( r==rend ) break;
+ if( l->index() == r->index() ) {
+ (~lhs)[l->index()] += l->value() * r->value();
+ ++r;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ LeftIterator l( x.begin() );
+ RightIterator r( y.begin() );
+
+ for( ; l!=lend; ++l ) {
+ while( r!=rend && r->index() < l->index() ) ++r;
+ if( r==rend ) break;
+ if( l->index() == r->index() ) {
+ (~lhs)[l->index()] -= l->value() * r->value();
+ ++r;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-sparse vector multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ LeftIterator l( x.begin() );
+ RightIterator r( y.begin() );
+
+ size_t i( 0 );
+
+ for( ; l!=lend; ++l ) {
+ while( r!=rend && r->index() < l->index() ) ++r;
+ if( r==rend ) break;
+ if( l->index() == r->index() ) {
+ for( ; i<r->index(); ++i )
+ reset( (~lhs)[i] );
+ (~lhs)[l->index()] *= l->value() * r->value();
+ ++r;
+ ++i;
+ }
+ }
+
+ for( ; i<rhs.size(); ++i )
+ reset( (~lhs)[i] );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-sparse vector multiplication to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-sparse vector multiplication expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void multAssign( SparseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_<VT> Iterator1;
+ typedef ConstIterator_< RemoveReference_<CT1> > Iterator2;
+ typedef ConstIterator_< RemoveReference_<CT2> > Iterator3;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ VT tmp( rhs.size(), rhs.nonZeros() );
+
+ const Iterator1 end1( (~lhs).end() );
+ const Iterator2 end2( x.end() );
+ const Iterator3 end3( y.end() );
+
+ Iterator1 i1( (~lhs).begin() );
+ Iterator2 i2( x.begin() );
+ Iterator3 i3( y.begin() );
+
+ for( ; i1!=end1; ++i1 ) {
+ while( i2!=end2 && i2->index() < i1->index() ) ++i2;
+ if( i2==end2 ) break;
+ while( i3!=end3 && i3->index() < i1->index() ) ++i3;
+ if( i3==end3 ) break;
+ if( i1->index() == i2->index() && i1->index() == i3->index() ) {
+ tmp.append( i1->index(), i1->value() * i2->value() * i3->value() );
+ ++i2;
+ ++i3;
+ }
+ }
+
+ swap( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECMULTEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the componentwise multiplication of two sparse vectors
+// (\f$ \vec{a}=\vec{b}*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the component product.
+// \param rhs The right-hand side sparse vector for the component product.
+// \return The product of the two sparse vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the componentwise multiplication of two sparse vectors:
+
+ \code
+ blaze::CompressedVector<double> a, b, c;
+ // ... Resizing and initialization
+ c = a * b;
+ \endcode
+
+// The operator returns a sparse vector of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const SVecSVecMultExpr<T1,T2,TF>
+ operator*( const SparseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return SVecSVecMultExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< SVecSVecMultExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< SVecSVecMultExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecSVecSubExpr.h b/src/cpu/blaze/math/expressions/SVecSVecSubExpr.h
new file mode 100644
index 00000000..e847d12b
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecSVecSubExpr.h
@@ -0,0 +1,729 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecSVecSubExpr.h
+// \brief Header file for the sparse vector/sparse vector subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECSVECSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECSVECSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/constraints/VecVecSubExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecVecSubExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECSVECSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-sparse vector subtractions.
+// \ingroup sparse_vector_expression
+//
+// The SVecSVecSubExpr class represents the compile time expression for subtractions between
+// sparse vectors.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class SVecSVecSubExpr : public SparseVector< SVecSVecSubExpr<VT1,VT2,TF>, TF >
+ , private VecVecSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target vector is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename VT >
+ struct UseSMPAssign {
+ enum : bool { value = VT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecSVecSubExpr<VT1,VT2,TF> This; //!< Type of this SVecSVecSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecSVecSubExpr class.
+ */
+ explicit inline SVecSVecSubExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
+ return lhs_[index] - rhs_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return min( lhs_.size(), lhs_.nonZeros() + rhs_.nonZeros() );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a sparse vector-sparse vector subtraction to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a sparse vector-sparse vector
+ // subtraction expression to a dense vector. This function is used in case the element
+ // type is resizable.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< IsResizable< ElementType_<VT> > >
+ assign( DenseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( LeftIterator l=x.begin(); l!=lend; ++l ) {
+ (~lhs)[l->index()] = l->value();
+ }
+
+ for( RightIterator r=y.begin(); r!=rend; ++r ) {
+ if( isDefault( (~lhs)[r->index()] ) )
+ (~lhs)[r->index()] = -r->value();
+ else
+ (~lhs)[r->index()] -= r->value();
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a sparse vector-sparse vector subtraction to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector subtraction expression to a dense vector. This function is used in case the element
+ // type is not resizable.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline DisableIf_< IsResizable< ElementType_<VT> > >
+ assign( DenseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( LeftIterator l=x.begin(); l!=lend; ++l ) {
+ (~lhs)[l->index()] = l->value();
+ }
+
+ for( RightIterator r=y.begin(); r!=rend; ++r ) {
+ (~lhs)[r->index()] -= r->value();
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector subtraction to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector subtraction expression to a sparse vector.
+ */
+ template< typename VT > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ CT2 y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ LeftIterator l( x.begin() );
+ RightIterator r( y.begin() );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), l->value() - r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), -r->value() );
+ ++r;
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-sparse vector subtraction to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // sparse vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-sparse vector subtraction to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // sparse vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-sparse vector subtraction to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-sparse vector subtraction expression to a dense vector.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ // No special implementation for the SMP assignment to dense vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector-sparse vector subtraction to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector-sparse vector subtraction expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpAddAssign( DenseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector-sparse vector subtraction to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector-sparse vector subtraction expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpSubAssign( DenseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector-sparse vector subtraction to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side subtraction expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector-sparse vector subtraction expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT> >
+ smpMultAssign( DenseVector<VT,TF>& lhs, const SVecSVecSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT1, TF );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECVECSUBEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of two sparse vectors (\f$ \vec{a}=\vec{b}-\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the vector subtraction.
+// \param rhs The right-hand side sparse vector to be subtracted from the vector.
+// \return The difference of the two sparse vectors.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the subtraction of two sparse vectors:
+
+ \code
+ blaze::CompressedVector<double> a, b, c;
+ // ... Resizing and initialization
+ c = a - b;
+ \endcode
+
+// The operator returns a sparse vector of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const SVecSVecSubExpr<T1,T2,TF>
+ operator-( const SparseVector<T1,TF>& lhs, const SparseVector<T2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ return SVecSVecSubExpr<T1,T2,TF>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF >
+struct Size< SVecSVecSubExpr<VT1,VT2,TF> >
+ : public Max< Size<VT1>, Size<VT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< SVecSVecSubExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecScalarDivExpr.h b/src/cpu/blaze/math/expressions/SVecScalarDivExpr.h
new file mode 100644
index 00000000..1af6aacc
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecScalarDivExpr.h
@@ -0,0 +1,1038 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecScalarDivExpr.h
+// \brief Header file for the sparse vector/scalar division expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECSCALARDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecScalarDivExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsMultExpr.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECSCALARDIVEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for divisions of a sparse vector by a scalar.
+// \ingroup sparse_vector_expression
+//
+// The SVecScalarDivExpr class represents the compile time expression for divisions of sparse
+// vectors by scalar values.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST // Type of the right-hand side scalar value
+ , bool TF > // Transpose flag
+class SVecScalarDivExpr : public SparseVector< SVecScalarDivExpr<VT,ST,TF>, TF >
+ , private VecScalarDivExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> RT; //!< Result type of the sparse vector expression.
+ typedef ReturnType_<VT> RN; //!< Return type of the sparse vector expression.
+ typedef CompositeType_<VT> CT; //!< Composite type of the sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If the vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef DivExprTrait_<RN,ST> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the multiplication expression. In case either the sparse
+ vector operand requires an intermediate evaluation, \a useAssign will be set to 1 and the
+ multiplication expression will be evaluated via the \a assign function family. Otherwise
+ \a useAssign will be set to 0 and the expression will be evaluated via the subscript
+ operator. */
+ enum : bool { useAssign = RequiresEvaluation<VT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target vector or the sparse vector operand is not SMP
+ assignable and the vector operand requires an intermediate evaluation, \a value is set
+ to 1 and the expression specific evaluation strategy is selected. Otherwise \a value is
+ set to 0 and the default strategy is chosen. */
+ template< typename VT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT2::smpAssignable || !VT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecScalarDivExpr<VT,ST,TF> This; //!< Type of this SVecScalarDivExpr instance.
+ typedef DivTrait_<RT,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SVecScalarDivExpr& > CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse vector/scalar multiplication expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse vector expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<LeftOperand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType vector, RightOperand scalar )
+ : vector_( vector ) // Iterator over the elements of the left-hand side sparse vector expression
+ , scalar_( scalar ) // Right hand side scalar of the multiplication expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++vector_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( vector_->value() / scalar_, vector_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return vector_->value() / scalar_;
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return vector_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return vector_ == rhs.vector_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return vector_ != rhs.vector_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return vector_ - rhs.vector_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType vector_; //!< Iterator over the elements of the left-hand side sparse vector expression.
+ RightOperand scalar_; //!< Right hand side scalar of the multiplication expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecScalarDivExpr class.
+ //
+ // \param vector The left-hand side sparse vector of the division expression.
+ // \param scalar The right-hand side scalar of the division expression.
+ */
+ explicit inline SVecScalarDivExpr( const VT& vector, ST scalar ) noexcept
+ : vector_( vector ) // Left-hand side sparse vector of the division expression
+ , scalar_( scalar ) // Right-hand side scalar of the division expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
+ return vector_[index] / scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= vector_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( vector_.begin(), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( vector_.end(), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return vector_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return vector_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific vector element.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( vector_.find( index ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( vector_.lowerBound( index ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( vector_.upperBound( index ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vector_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vector_; //!< Left-hand side sparse vector of the division expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the division expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-scalar division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-scalar
+ // division expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the vector
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,TF>& lhs, const SVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.vector_ );
+ (~lhs) /= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-scalar division to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side division expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-scalar
+ // division expression to a sparse vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the vector
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,TF>& lhs, const SVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.vector_ );
+ (~lhs) /= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-scalar division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // scalar division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,TF>& lhs, const SVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-scalar division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // scalar division expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the vector operand
+ // requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,TF>& lhs, const SVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-scalar division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-scalar division expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // vector operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,TF>& lhs, const SVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ // No special implementation for the SMP assignment to dense vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector-scalar division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector-scalar division expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,TF>& lhs, const SVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector-scalar division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector-scalar division expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,TF>& lhs, const SVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector-scalar division to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side division expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector-scalar division expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,TF>& lhs, const SVecScalarDivExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ElementType );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division operator for the divison of a sparse vector by a scalar value
+// (\f$ \vec{a}=\vec{b}/s \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side sparse vector for the division.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result vector.
+//
+// This operator represents the division of a sparse vector by a scalar value:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = a / 0.24;
+ \endcode
+
+// The operator returns a sparse vector of the higher-order element type of the involved data
+// types \a T1::ElementType and \a T2. Note that this operator only works for scalar values
+// of built-in data type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side scalar
+ , bool TF > // Transpose flag
+inline const EnableIf_< IsNumeric<T2>, DivExprTrait_<T1,T2> >
+ operator/( const SparseVector<T1,TF>& vec, T2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_USER_ASSERT( scalar != T2(0), "Division by zero detected" );
+
+ typedef DivExprTrait_<T1,T2> ReturnType;
+ typedef RightOperand_<ReturnType> ScalarType;
+
+ if( IsMultExpr<ReturnType>::value ) {
+ return ReturnType( ~vec, ScalarType(1)/ScalarType(scalar) );
+ }
+ else {
+ return ReturnType( ~vec, scalar );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector-scalar division
+// expression and a scalar value (\f$ \vec{a}=(\vec{b}/s1)*s2 \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side sparse vector-scalar division.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// sparse vector-scalar division expression and a scalar value.
+*/
+template< typename VT // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the sparse vector
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< And< IsNumeric<ST2>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , MultExprTrait_< SVecScalarDivExpr<VT,ST1,TF>, ST2 > >
+ operator*( const SVecScalarDivExpr<VT,ST1,TF>& vec, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( scalar / vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a scalar value and a sparse vector-
+// scalar division expression (\f$ \vec{a}=s2*(\vec{b}/s1) \f$).
+// \ingroup sparse_vector
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param vec The right-hand side sparse vector-scalar division.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// scalar value and a sparse vector-scalar division expression.
+*/
+template< typename ST1 // Type of the left-hand side scalar
+ , typename VT // Type of the sparse vector of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool TF > // Transpose flag of the sparse vector
+inline const EnableIf_< And< IsNumeric<ST1>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , MultExprTrait_< ST1, SVecScalarDivExpr<VT,ST2,TF> > >
+ operator*( ST1 scalar, const SVecScalarDivExpr<VT,ST2,TF>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( scalar / vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division operator for the division of a sparse vector-scalar division expression
+// and a scalar value (\f$ \vec{a}=(\vec{b}/s1)/s2 \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side sparse vector-scalar division.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the division of a sparse
+// vector-scalar division expression and a scalar value.
+*/
+template< typename VT // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the sparse vector
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<ST2>
+ , DivExprTrait_< VT, MultTrait_<ST1,ST2> > >
+ operator/( const SVecScalarDivExpr<VT,ST1,TF>& vec, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" );
+
+ typedef MultTrait_<ST1,ST2> MultType;
+ typedef DivExprTrait_<VT,MultType> ReturnType;
+ typedef RightOperand_<ReturnType> ScalarType;
+
+ if( IsMultExpr<ReturnType>::value ) {
+ return ReturnType( vec.leftOperand(), ScalarType(1)/( vec.rightOperand() * scalar ) );
+ }
+ else {
+ return ReturnType( vec.leftOperand(), vec.rightOperand() * scalar );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF >
+struct Size< SVecScalarDivExpr<VT,ST,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct SVecScalarMultExprTrait< SVecScalarDivExpr<VT,ST1,false>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = DivTrait_<ST2,ST1>;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , SVecScalarMultExprTrait_<VT,ScalarType>
+ , SVecScalarMultExpr< SVecScalarDivExpr<VT,ST1,false>, ST2, false > >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct TSVecScalarMultExprTrait< SVecScalarDivExpr<VT,ST1,true>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = DivTrait_<ST2,ST1>;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , SVecScalarMultExprTrait_<VT,ScalarType>
+ , SVecScalarMultExpr< SVecScalarDivExpr<VT,ST1,true>, ST2, true > >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTOREXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF, bool AF >
+struct SubvectorExprTrait< SVecScalarDivExpr<VT,ST,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = DivExprTrait_< SubvectorExprTrait_<const VT,AF>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecScalarMultExpr.h b/src/cpu/blaze/math/expressions/SVecScalarMultExpr.h
new file mode 100644
index 00000000..9c74a026
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecScalarMultExpr.h
@@ -0,0 +1,2168 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecScalarMultExpr.h
+// \brief Header file for the sparse vector/scalar multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECSCALARMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/VecScalarMultExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECSCALARMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-scalar multiplications.
+// \ingroup sparse_vector_expression
+//
+// The SVecScalarMultExpr class represents the compile time expression for multiplications between
+// a sparse vector and a scalar value.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST // Type of the right-hand side scalar value
+ , bool TF > // Transpose flag
+class SVecScalarMultExpr : public SparseVector< SVecScalarMultExpr<VT,ST,TF>, TF >
+ , private VecScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> RT; //!< Result type of the sparse vector expression.
+ typedef ReturnType_<VT> RN; //!< Return type of the sparse vector expression.
+ typedef CompositeType_<VT> CT; //!< Composite type of the sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If the vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN,ST> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the multiplication expression. In case the sparse
+ vector operand requires an intermediate evaluation, \a useAssign will be set to 1 and
+ the multiplication expression will be evaluated via the \a assign function family.
+ Otherwise \a useAssign will be set to 0 and the expression will be evaluated via the
+ subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<VT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the target vector or the sparse vector operand is not SMP
+ assignable and the vector operand requires an intermediate evaluation, \a value is set
+ to 1 and the expression specific evaluation strategy is selected. Otherwise \a value is
+ set to 0 and the default strategy is chosen. */
+ template< typename VT2 >
+ struct UseSMPAssign {
+ enum : bool { value = ( !VT2::smpAssignable || !VT::smpAssignable ) && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecScalarMultExpr<VT,ST,TF> This; //!< Type of this SVecScalarMultExpr instance.
+ typedef MultTrait_<RT,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SVecScalarMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse vector/scalar multiplication expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse vector expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<LeftOperand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType vector, RightOperand scalar )
+ : vector_( vector ) // Iterator over the elements of the left-hand side sparse vector expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++vector_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( vector_->value() * scalar_, vector_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return vector_->value() * scalar_;
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return vector_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return vector_ == rhs.vector_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return vector_ != rhs.vector_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return vector_ - rhs.vector_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType vector_; //!< Iterator over the elements of the left-hand side sparse vector expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecScalarMultExpr class.
+ //
+ // \param vector The left-hand side sparse vector of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline SVecScalarMultExpr( const VT& vector, ST scalar ) noexcept
+ : vector_( vector ) // Left-hand side sparse vector of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
+ return vector_[index] * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= vector_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( vector_.begin(), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( vector_.end(), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return vector_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return vector_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific vector element.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( vector_.find( index ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( vector_.lowerBound( index ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( vector_.upperBound( index ), scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vector_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vector_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-scalar multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-scalar
+ // multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,TF>& lhs, const SVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.vector_ );
+ (~lhs) *= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-scalar multiplication to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-scalar
+ // multiplication expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,TF>& lhs, const SVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.vector_ );
+ (~lhs) *= rhs.scalar_;
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-scalar multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // scalar multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,TF>& lhs, const SVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ addAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-scalar multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // scalar multiplication expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the vector
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,TF>& lhs, const SVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ subAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector-scalar multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector-scalar multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // vector operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,TF>& lhs, const SVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ // No special implementation for the SMP assignment to dense vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector-scalar multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector-scalar multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,TF>& lhs, const SVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAddAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector-scalar multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // vector-scalar multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,TF>& lhs, const SVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpSubAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector-scalar multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector-scalar multiplication expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,TF>& lhs, const SVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL UNARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unary minus operator for the negation of a sparse vector (\f$ \vec{a} = -\vec{b} \f$).
+// \ingroup sparse_vector
+//
+// \param sv The sparse vector to be negated.
+// \return The negation of the vector.
+//
+// This operator represents the negation of a sparse vector:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = -a;
+ \endcode
+
+// The operator returns an expression representing the negation of the given sparse vector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecScalarMultExpr<VT,UnderlyingBuiltin_<VT>,TF>
+ operator-( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef UnderlyingBuiltin_<VT> ElementType;
+ return SVecScalarMultExpr<VT,ElementType,TF>( ~sv, ElementType(-1) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a sparse vector and a scalar value
+// (\f$ \vec{a}=\vec{b}*s \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side sparse vector for the multiplication.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result vector.
+//
+// This operator represents the multiplication between a sparse vector and a scalar value:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = a * 1.25;
+ \endcode
+
+// The operator returns a sparse vector of the higher-order element type of the involved data
+// types \a T1::ElementType and \a T2. Note that this operator only works for scalar values
+// of built-in data type.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side scalar
+ , bool TF > // Transpose flag
+inline const EnableIf_< IsNumeric<T2>, MultExprTrait_<T1,T2> >
+ operator*( const SparseVector<T1,TF>& vec, T2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return MultExprTrait_<T1,T2>( ~vec, scalar );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a scalar value and a sparse vector
+// (\f$ \vec{a}=s*\vec{b} \f$).
+// \ingroup sparse_vector
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The scaled result vector.
+//
+// This operator represents the multiplication between a a scalar value and sparse vector:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = 1.25 * a;
+ \endcode
+
+// The operator returns a sparse vector of the higher-order element type of the involved data
+// types \a T1 and \a T2::ElementType. Note that this operator only works for scalar values
+// of built-in data type.
+*/
+template< typename T1 // Type of the left-hand side scalar
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+inline const EnableIf_< IsNumeric<T1>, MultExprTrait_<T1,T2> >
+ operator*( T1 scalar, const SparseVector<T2,TF>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return MultExprTrait_<T1,T2>( ~vec, scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Normalization of the sparse vector (\f$|\vec{a}|=1\f$).
+//
+// \param vec The given sparse vector.
+// \return The normalized result vector.
+//
+// This function represents the normalization of a sparse vector:
+
+ \code
+ blaze::CompressedVector<double> a;
+ // ... Resizing and initialization
+ a = normalize( a );
+ \endcode
+
+// The function returns an expression representing the normalized sparse vector. Note that
+// this function only works for floating point vectors. The attempt to use this function for
+// an integral vector results in a compile time error.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecScalarMultExpr<VT,ElementType_<VT>,TF>
+ normalize( const SparseVector<VT,TF>& vec )
+{
+ typedef ElementType_<VT> ElementType;
+
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType );
+
+ const ElementType len ( length( ~vec ) );
+ const ElementType ilen( ( len != ElementType(0) )?( ElementType(1) / len ):( 0 ) );
+
+ return SVecScalarMultExpr<VT,ElementType,TF>( ~vec, ilen );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING UNARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unary minus operator for the negation of a sparse vector-scalar multiplication
+// (\f$ \vec{a} = -(\vec{b} * s) \f$).
+// \ingroup sparse_vector
+//
+// \param sv The sparse vector-scalar multiplication to be negated.
+// \return The negation of the sparse vector-scalar multiplication.
+//
+// This operator implements a performance optimized treatment of the negation of a sparse vector-
+// scalar multiplication expression.
+*/
+template< typename VT // Type of the sparse vector
+ , typename ST // Type of the scalar
+ , bool TF > // Transpose flag
+inline const SVecScalarMultExpr<VT,ST,TF>
+ operator-( const SVecScalarMultExpr<VT,ST,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecScalarMultExpr<VT,ST,TF>( sv.leftOperand(), -sv.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector-scalar multiplication
+// expression and a scalar value (\f$ \vec{a}=(\vec{b}*s1)*s2 \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side sparse vector-scalar multiplication.
+// \param scalar The right-hand side scalar value for the multiplication.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// sparse vector-scalar multiplication expression and a scalar value.
+*/
+template< typename VT // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the sparse vector
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< IsNumeric<ST2>, MultExprTrait_< SVecScalarMultExpr<VT,ST1,TF>, ST2 > >
+ operator*( const SVecScalarMultExpr<VT,ST1,TF>& vec, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( vec.rightOperand() * scalar );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector-scalar multiplication
+// expression and a scalar value (\f$ \vec{a}=s2*(\vec{b}*s1) \f$).
+// \ingroup sparse_vector
+//
+// \param scalar The left-hand side scalar value for the multiplication.
+// \param vec The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a
+// scalar value and a sparse vector-scalar multiplication expression.
+*/
+template< typename ST1 // Type of the left-hand side scalar
+ , typename VT // Type of the sparse vector of the right-hand side expression
+ , typename ST2 // Type of the scalar of the right-hand side expression
+ , bool TF > // Transpose flag of the sparse vector
+inline const EnableIf_< IsNumeric<ST1>, MultExprTrait_< ST1, SVecScalarMultExpr<VT,ST2,TF> > >
+ operator*( ST1 scalar, const SVecScalarMultExpr<VT,ST2,TF>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( scalar * vec.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division operator for the division of a dense vector-scalar multiplication
+// expression by a scalar value (\f$ \vec{a}=(\vec{b}*s1)/s2 \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector-scalar multiplication.
+// \param scalar The right-hand side scalar value for the division.
+// \return The scaled result vector.
+//
+// This operator implements a performance optimized treatment of the division of a
+// dense vector-scalar multiplication expression by a scalar value.
+*/
+template< typename VT // Type of the dense vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the dense vector
+ , typename ST2 > // Type of the right-hand side scalar
+inline const EnableIf_< And< IsNumeric<ST2>, Or< IsInvertible<ST1>, IsInvertible<ST2> > >
+ , DivExprTrait_< SVecScalarMultExpr<VT,ST1,TF>, ST2 > >
+ operator/( const SVecScalarMultExpr<VT,ST1,TF>& vec, ST2 scalar )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return vec.leftOperand() * ( vec.rightOperand() / scalar );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector-scalar multiplication
+// expression and a dense vector (\f$ \vec{a}=(\vec{b}*s1)*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector-scalar multiplication.
+// \param rhs The right-hand side dense vector.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse vector-scalar multiplication and a dense vector. It restructures the expression
+// \f$ \vec{a}=(\vec{b}*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*s1 \f$.
+*/
+template< typename VT1 // Type of the sparse vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the dense vectors
+ , typename VT2 > // Type of the right-hand side dense vector
+inline const MultExprTrait_< SVecScalarMultExpr<VT1,ST,TF>, VT2 >
+ operator*( const SVecScalarMultExpr<VT1,ST,TF>& lhs, const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense vector and a sparse vector-
+// scalar multiplication expression (\f$ \vec{a}=\vec{b}*(\vec{c}*s1) \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side dense vector.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense vector and a sparse vector-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=\vec{b}*(\vec{c}*s1) \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*s1 \f$.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF // Transpose flag of the dense vectors
+ , typename VT2 // Type of the sparse vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< VT1, SVecScalarMultExpr<VT2,ST,TF> >
+ operator*( const DenseVector<VT1,TF>& lhs, const SVecScalarMultExpr<VT2,ST,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a sparse vector-scalar multiplication
+// expression and a dense vector (\f$ A=(\vec{b}*s1)*\vec{c}^T \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse vector-scalar multiplication.
+// \param rhs The right-hand side dense vector.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product of a
+// sparse vector-scalar multiplication and a dense vector. It restructures the expression
+// \f$ A=(\vec{b}*s1)*\vec{c}^T \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*s1 \f$.
+*/
+template< typename VT1 // Type of the sparse vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , typename VT2 > // Type of the right-hand side dense vector
+inline const MultExprTrait_< SVecScalarMultExpr<VT1,ST,false>, VT2 >
+ operator*( const SVecScalarMultExpr<VT1,ST,false>& lhs, const DenseVector<VT2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a dense vector and a sparse vector-
+// scalar multiplication expression (\f$ A=\vec{b}*(\vec{c}^T*s1) \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side dense vector.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product of a
+// dense vector and a sparse vector-scalar multiplication. It restructures the expression
+// \f$ A=\vec{b}*(\vec{c}^T*s1) \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*s1 \f$.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the sparse vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< VT1, SVecScalarMultExpr<VT2,ST,true> >
+ operator*( const DenseVector<VT1,false>& lhs, const SVecScalarMultExpr<VT2,ST,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector-scalar multiplication
+// expression and a sparse vector (\f$ \vec{a}=(\vec{b}*s1)*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector-scalar multiplication.
+// \param rhs The right-hand side sparse vector.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse vector-scalar multiplication and a sparse vector. It restructures the expression
+// \f$ \vec{a}=(\vec{b}*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*s1 \f$.
+*/
+template< typename VT1 // Type of the sparse vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the vectors
+ , typename VT2 > // Type of the right-hand side sparse vector
+inline const MultExprTrait_< SVecScalarMultExpr<VT1,ST,TF>, VT2 >
+ operator*( const SVecScalarMultExpr<VT1,ST,TF>& lhs, const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse vector and a sparse vector-
+// scalar multiplication expression (\f$ \vec{a}=\vec{b}*(\vec{c}*s1) \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse vector and a sparse vector-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=\vec{b}*(\vec{c}*s1) \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*s1 \f$.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , bool TF // Transpose flag of the vectors
+ , typename VT2 // Type of the sparse vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< VT1, SVecScalarMultExpr<VT2,ST,TF> >
+ operator*( const SparseVector<VT1,TF>& lhs, const SVecScalarMultExpr<VT2,ST,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of two sparse vector-scalar
+// multiplication expressions (\f$ \vec{a}=(\vec{b}*s1)*(\vec{c}*s2) \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector-scalar multiplication.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of
+// two sparse vector-scalar multiplication expressions. It restructures the expression
+// \f$ \vec{a}=(\vec{b}*s1)*(\vec{c}*s2) \f$ to the expression \f$ \vec{a}=(\vec{b}*\vec{c})*(s1*s2) \f$.
+*/
+template< typename VT1 // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , bool TF // Transpose flag of the sparse vectors
+ , typename VT2 // Type of the sparse vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< SVecScalarMultExpr<VT1,ST1,TF>, SVecScalarMultExpr<VT2,ST2,TF> >
+ operator*( const SVecScalarMultExpr<VT1,ST1,TF>& lhs, const SVecScalarMultExpr<VT2,ST2,TF>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a sparse vector-scalar multiplication
+// expression and a sparse vector (\f$ A=(\vec{b}*s1)*\vec{c}^T \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse vector-scalar multiplication.
+// \param rhs The right-hand side sparse vector.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product of a
+// sparse vector-scalar multiplication and a sparse vector. It restructures the expression
+// \f$ A=(\vec{b}*s1)*\vec{c}^T \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*s1 \f$.
+*/
+template< typename VT1 // Type of the sparse vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , typename VT2 > // Type of the right-hand side sparse vector
+inline const MultExprTrait_< SVecScalarMultExpr<VT1,ST,false>, VT2 >
+ operator*( const SVecScalarMultExpr<VT1,ST,false>& lhs, const SparseVector<VT2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of a sparse vector and a sparse vector-
+// scalar multiplication expression (\f$ A=\vec{b}*(\vec{c}^T*s1) \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse vector.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product of a
+// sparse vector and a sparse vector-scalar multiplication. It restructures the expression
+// \f$ A=\vec{b}*(\vec{c}^T*s1) \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*s1 \f$.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the sparse vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< VT1, SVecScalarMultExpr<VT2,ST,true> >
+ operator*( const SparseVector<VT1,false>& lhs, const SVecScalarMultExpr<VT2,ST,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the outer product of two a sparse vector-scalar
+// multiplication expressions (\f$ A=(\vec{b}*s1)*(\vec{c}^T*s2) \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse vector-scalar multiplication.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result matrix.
+//
+// This operator implements the performance optimized treatment of the outer product
+// of two sparse vector-scalar multiplications. It restructures the expression
+// \f$ A=(\vec{b}*s1)*(\vec{c}^T*s2) \f$ to the expression \f$ A=(\vec{b}*\vec{c}^T)*(s1*s2) \f$.
+*/
+template< typename VT1 // Type of the sparse vector of the left-hand side expression
+ , typename ST1 // Type of the scalar of the left-hand side expression
+ , typename VT2 // Type of the sparse vector of the right-hand side expression
+ , typename ST2 > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< SVecScalarMultExpr<VT1,ST1,false>, SVecScalarMultExpr<VT2,ST2,true> >
+ operator*( const SVecScalarMultExpr<VT1,ST1,false>& lhs, const SVecScalarMultExpr<VT2,ST2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a dense matrix and a sparse
+// vector-scalar multiplication expression (\f$ \vec{a}=B*(\vec{c}*s1) \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense matrix.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// dense matrix and a sparse vector-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=B*(\vec{c}*s1) \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename VT // Type of the sparse vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< MT, SVecScalarMultExpr<VT,ST,false> >
+ operator*( const DenseMatrix<MT,SO>& mat, const SVecScalarMultExpr<VT,ST,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~mat) * vec.leftOperand() ) * vec.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector-scalar
+// multiplication expression and a dense matrix (\f$ \vec{a}^T=(\vec{b}^T*s1)*C \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side transpose sparse vector-scalar multiplication.
+// \param rhs The right-hand side dense matrix.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// transpose sparse vector-scalar multiplication and a dense matrix. It restructures the
+// expression \f$ \vec{a}^T=(\vec{b}^T*s1)*C \f$ to the expression \f$ \vec{a}^T=(\vec{b}^T*C)*s1 \f$.
+*/
+template< typename VT // Type of the sparse vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const MultExprTrait_< SVecScalarMultExpr<VT,ST,true>, MT >
+ operator*( const SVecScalarMultExpr<VT,ST,true>& vec, const DenseMatrix<MT,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( vec.leftOperand() * (~mat) ) * vec.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a sparse matrix and a sparse
+// vector-scalar multiplication expression (\f$ \vec{a}=B*(\vec{c}*s1) \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse matrix.
+// \param rhs The right-hand side sparse vector-scalar multiplication.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// sparse matrix and a sparse vector-scalar multiplication. It restructures the expression
+// \f$ \vec{a}=B*(\vec{c}*s1) \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , bool SO // Storage order of the left-hand side sparse matrix
+ , typename VT // Type of the sparse vector of the right-hand side expression
+ , typename ST > // Type of the scalar of the right-hand side expression
+inline const MultExprTrait_< MT, SVecScalarMultExpr<VT,ST,false> >
+ operator*( const SparseMatrix<MT,SO>& mat, const SVecScalarMultExpr<VT,ST,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~mat) * vec.leftOperand() ) * vec.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector-scalar
+// multiplication expression and a sparse matrix (\f$ \vec{a}^T=(\vec{b}^T*s1)*C \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side transpose sparse vector-scalar multiplication.
+// \param rhs The right-hand side sparse matrix.
+// \return The scaled result vector.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// transpose sparse vector-scalar multiplication and a sparse matrix. It restructures the
+// expression \f$ \vec{a}^T=(\vec{b}^T*s1)*C \f$ to the expression \f$ \vec{a}^T=(\vec{b}^T*C)*s1 \f$.
+*/
+template< typename VT // Type of the sparse vector of the left-hand side expression
+ , typename ST // Type of the scalar of the left-hand side expression
+ , typename MT // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline const MultExprTrait_< SVecScalarMultExpr<VT,ST,true>, MT >
+ operator*( const SVecScalarMultExpr<VT,ST,true>& vec, const SparseMatrix<MT,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( vec.leftOperand() * (~mat) ) * vec.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF >
+struct Size< SVecScalarMultExpr<VT,ST,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct SVecScalarMultExprTrait< SVecScalarMultExpr<VT,ST1,false>, ST2 >
+{
+ public:
+ //**********************************************************************************************
+ typedef If_< And< IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SVecScalarMultExprTrait_< VT, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE > Type;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECSCALARMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct TSVecScalarMultExprTrait< SVecScalarMultExpr<VT,ST1,true>, ST2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSVecScalarMultExprTrait_< VT, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECSCALARDIVEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct SVecScalarDivExprTrait< SVecScalarMultExpr<VT,ST1,false>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = DivTrait_<ST1,ST2>;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , SVecScalarMultExprTrait_<VT,ScalarType>
+ , SVecScalarDivExprTrait_<VT,ScalarType> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECSCALARDIVEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST1, typename ST2 >
+struct TSVecScalarDivExprTrait< SVecScalarMultExpr<VT,ST1,true>, ST2 >
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = DivTrait_<ST1,ST2>;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , If_< IsInvertible<ScalarType>
+ , TSVecScalarMultExprTrait_<VT,ScalarType>
+ , TSVecScalarDivExprTrait_<VT,ScalarType> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct DVecSVecMultExprTrait< VT1, SVecScalarMultExpr<VT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< DVecSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECTSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct DVecTSVecMultExprTrait< VT1, SVecScalarMultExpr<VT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , SMatScalarMultExprTrait_< DVecTSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDVECTSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct TDVecTSVecMultExprTrait< VT1, SVecScalarMultExpr<VT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TDVecTSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct SVecDVecMultExprTrait< SVecScalarMultExpr<VT1,ST,false>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< SVecDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECTDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct SVecTDVecMultExprTrait< SVecScalarMultExpr<VT1,ST,false>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TSMatScalarMultExprTrait_< SVecTDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECTDVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct TSVecTDVecMultExprTrait< SVecScalarMultExpr<VT1,ST,true>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TSVecTDVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct SVecSVecMultExprTrait< SVecScalarMultExpr<VT1,ST,false>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< SVecSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct SVecSVecMultExprTrait< VT1, SVecScalarMultExpr<VT2,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< SVecSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct SVecSVecMultExprTrait< SVecScalarMultExpr<VT1,ST1,false>, SVecScalarMultExpr<VT2,ST2,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SVecScalarMultExprTrait_< SVecSVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVECTSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct SVecTSVecMultExprTrait< SVecScalarMultExpr<VT1,ST,false>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , SMatScalarMultExprTrait_< SVecTSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct SVecTSVecMultExprTrait< VT1, SVecScalarMultExpr<VT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , SMatScalarMultExprTrait_< SVecTSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct SVecTSVecMultExprTrait< SVecScalarMultExpr<VT1,ST1,false>, SVecScalarMultExpr<VT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , SMatScalarMultExprTrait_< SVecTSVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECTSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST, typename VT2 >
+struct TSVecTSVecMultExprTrait< SVecScalarMultExpr<VT1,ST,true>, VT2 >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TSVecTSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, typename ST >
+struct TSVecTSVecMultExprTrait< VT1, SVecScalarMultExpr<VT2,ST,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TSVecTSVecMultExprTrait_<VT1,VT2>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename ST1, typename VT2, typename ST2 >
+struct TSVecTSVecMultExprTrait< SVecScalarMultExpr<VT1,ST1,true>, SVecScalarMultExpr<VT2,ST2,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2>
+ , IsNumeric<ST1>, IsNumeric<ST2> >
+ , TSVecScalarMultExprTrait_< TSVecTSVecMultExprTrait_<VT1,VT2>, MultTrait_<ST1,ST2> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, typename ST >
+struct DMatSVecMultExprTrait< MT, SVecScalarMultExpr<VT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< DMatSVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TDMATSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, typename ST >
+struct TDMatSVecMultExprTrait< MT, SVecScalarMultExpr<VT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , DVecScalarMultExprTrait_< TDMatSVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, typename MT >
+struct TSVecDMatMultExprTrait< SVecScalarMultExpr<VT,ST,true>, MT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TSVecDMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECTDMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, typename MT >
+struct TSVecTDMatMultExprTrait< SVecScalarMultExpr<VT,ST,true>, MT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TDVecScalarMultExprTrait_< TSVecTDMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMATSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, typename ST >
+struct SMatSVecMultExprTrait< MT, SVecScalarMultExpr<VT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< SMatSVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSMATSVECMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, typename ST >
+struct TSMatSVecMultExprTrait< MT, SVecScalarMultExpr<VT,ST,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT>
+ , IsNumeric<ST> >
+ , SVecScalarMultExprTrait_< TSMatSVecMultExprTrait_<MT,VT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, typename MT >
+struct TSVecSMatMultExprTrait< SVecScalarMultExpr<VT,ST,true>, MT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TSVecSMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TSVECTSMATMULTEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, typename MT >
+struct TSVecTSMatMultExprTrait< SVecScalarMultExpr<VT,ST,true>, MT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsNumeric<ST> >
+ , TSVecScalarMultExprTrait_< TSVecTSMatMultExprTrait_<VT,MT>, ST >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTOREXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename ST, bool TF, bool AF >
+struct SubvectorExprTrait< SVecScalarMultExpr<VT,ST,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>, ST >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecSerialExpr.h b/src/cpu/blaze/math/expressions/SVecSerialExpr.h
new file mode 100644
index 00000000..3ff4b6be
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecSerialExpr.h
@@ -0,0 +1,769 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecSerialExpr.h
+// \brief Header file for the sparse vector serial evaluation expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECSERIALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/VecSerialExpr.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/traits/SerialExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/SVecSerialExprTrait.h>
+#include <blaze/math/traits/TSVecSerialExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECSERIALEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the forced serial evaluation of sparse vectors.
+// \ingroup sparse_vector_expression
+//
+// The SVecSerialExpr class represents the compile time expression for the forced serial
+// evaluation of a sparse vector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+class SVecSerialExpr : public SparseVector< SVecSerialExpr<VT,TF>, TF >
+ , private VecSerialExpr
+ , private Computation
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecSerialExpr<VT,TF> This; //!< Type of this SVecSerialExpr instance.
+ typedef ResultType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite data type of the sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecSerialExpr class.
+ //
+ // \param sv The sparse vector operand of the serial evaluation expression.
+ */
+ explicit inline SVecSerialExpr( const VT& sv ) noexcept
+ : sv_( sv ) // Sparse vector of the serial evaluation expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < sv_.size(), "Invalid vector access index" );
+ return sv_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= sv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return sv_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return sv_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the sparse vector operand.
+ //
+ // \return The sparse vector operand.
+ */
+ inline Operand operand() const noexcept {
+ return sv_;
+ }
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\brief Conversion to the type of the sparse vector operand.
+ //
+ // \return The sparse vector operand.
+ */
+ inline operator Operand() const noexcept {
+ return sv_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return sv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return sv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return sv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand sv_; //!< Sparse vector of the serial evaluation expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector serial evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector serial
+ // evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector serial evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector serial
+ // evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector serial evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector
+ // serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector serial evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector
+ // serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void addAssign( SparseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector serial evaluation expression to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector serial evaluation expression to a sparse
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void subAssign( SparseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector serial evaluation expression to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector serial evaluation expression to a sparse
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void multAssign( SparseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector serial evaluation expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector
+ // serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpAssign( DenseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector serial evaluation expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector
+ // serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpAssign( SparseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ assign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector serial evaluation expression to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpAddAssign( DenseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector serial evaluation expression to a sparse
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpAddAssign( SparseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector serial evaluation expression to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpSubAssign( DenseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector serial evaluation expression to a sparse
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpSubAssign( SparseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector serial evaluation expression to a
+ // dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector serial evaluation expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void smpMultAssign( DenseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector serial evaluation expression to a
+ // sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side serial evaluation expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector serial evaluation expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void smpMultAssign( SparseVector<VT2,TF>& lhs, const SVecSerialExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Forces the serial evaluation of the given sparse vector expression \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input vector.
+// \return The evaluated sparse vector.
+//
+// The \a serial function forces the serial evaluation of the given sparse vector expression
+// \a sv. The function returns an expression representing this operation.\n
+// The following example demonstrates the use of the \a serial function:
+
+ \code
+ blaze::CompressedVector<double> a, b;
+ // ... Resizing and initialization
+ b = serial( a );
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline const SVecSerialExpr<VT,TF> serial( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecSerialExpr<VT,TF>( ~sv );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Evaluation of the given sparse vector serial evaluation expression \a sv.
+// \ingroup sparse_vector
+//
+// \param sv The input serial evaluation expression.
+// \return The evaluated sparse vector.
+//
+// This function implements a performance optimized treatment of the serial evaluation of a sparse
+// vector serial evaluation expression.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecSerialExpr<VT,TF> serial( const SVecSerialExpr<VT,TF>& sv )
+{
+ return sv;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct Size< SVecSerialExpr<VT,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct SVecSerialExprTrait< SVecSerialExpr<VT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecSerialExpr<VT,false>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TSVecSerialExprTrait< SVecSerialExpr<VT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecSerialExpr<VT,true>
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF, bool AF >
+struct SubvectorExprTrait< SVecSerialExpr<VT,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SerialExprTrait_< SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecTDVecMultExpr.h b/src/cpu/blaze/math/expressions/SVecTDVecMultExpr.h
new file mode 100644
index 00000000..bc5d3a6c
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecTDVecMultExpr.h
@@ -0,0 +1,1331 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecTDVecMultExpr.h
+// \brief Header file for the sparse vector/dense vector outer product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECTDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECTDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/VecTVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/VecTVecMultExpr.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECTDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-dense vector outer products.
+// \ingroup sparse_matrix_expression
+//
+// The SVecTDVecMultExpr class represents the compile time expression for sparse vector-dense
+// vector outer products.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 > // Type of the right-hand side dense vector
+class SVecTDVecMultExpr : public SparseMatrix< SVecTDVecMultExpr<VT1,VT2>, true >
+ , private VecTVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side dense vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side dense vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side dense vector expression.
+ typedef ElementType_<VT1> ET1; //!< Element type of the left-hand side sparse vector expression.
+ typedef ElementType_<VT2> ET2; //!< Element type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Evaluation strategy*************************************************************************
+ //! Compilation switch for the evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the multiplication expression. In case either the sparse or
+ the dense vector operand is an expression or if any of two involved element types is not
+ a numeric data type, \a useAssign will be set to \a true and the multiplication expression
+ will be evaluated via the \a assign function family. Otherwise \a useAssign will be set to
+ \a false and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = ( IsComputation<VT1>::value || !IsNumeric<ET1>::value ||
+ IsComputation<VT2>::value || !IsNumeric<ET2>::value ) };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ outer product, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ T1::simdEnabled && T3::simdEnabled &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T1>, ElementType_<T1> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no vectorized computation is possible, the nested \value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseVectorizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecTDVecMultExpr<VT1,VT2> This; //!< Type of this SVecTDVecMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SVecTDVecMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense vector operand.
+ typedef If_< IsComputation<VT1>, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef If_< IsComputation<VT2>, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse vector-dense vector outer product expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Element type of the sparse matrix expression.
+ typedef ValueIndexPair<ElementType> Element;
+
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<LeftOperand> > IteratorType;
+
+ //! Element type of the dense vector expression
+ typedef ET2 RightElement;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Element ValueType; //!< Type of the underlying pointers.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef ValueType& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType it, RightElement v )
+ : it_( it ) // Iterator over the elements of the left-hand side sparse vector expression
+ , v_ ( v ) // Element of the right-hand side dense vector expression.
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const Element operator*() const {
+ return Element( it_->value() * v_, it_->index() );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse matrix element at the current iterator position.
+ //
+ // \return Reference to the sparse matrix element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return it_->value() * v_;
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator over the elements of the left-hand side sparse vector expression
+ RightElement v_; //!< Element of the right-hand side dense vector expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecTDVecMultExpr class.
+ //
+ // \param lhs The left-hand side sparse vector operand of the multiplication expression.
+ // \param rhs The right-hand side dense vector operand of the multiplication expression.
+ */
+ explicit inline SVecTDVecMultExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense vector of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.size(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.size(), "Invalid column access index" );
+
+ return lhs_[i] * rhs_[j];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of column \a i.
+ //
+ // \param i The row index.
+ // \return Iterator to the first non-zero element of column \a i.
+ */
+ inline ConstIterator begin( size_t i ) const {
+ return ConstIterator( lhs_.begin(), rhs_[i] );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of column \a i.
+ //
+ // \param i The row index.
+ // \return Iterator just past the last non-zero element of column \a i.
+ */
+ inline ConstIterator end( size_t i ) const {
+ return ConstIterator( lhs_.end(), rhs_[i] );
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() * rhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified column.
+ //
+ // \param i The index of the column.
+ // \return The number of non-zero elements of column \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ UNUSED_PARAMETER( i );
+ return lhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific matrix element.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.find( i ), rhs_[j] );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.lowerBound( i ), rhs_[j] );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param i The row index of the search element.
+ // \param j The column index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t i, size_t j ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT1 );
+ return ConstIterator( lhs_.upperBound( i ), rhs_[j] );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to row-major dense matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector outer product to a row-major dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector outer product expression to a row-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,false>& lhs, const SVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ SVecTDVecMultExpr::selectAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a sparse vector-dense vector outer product to a row-major
+ // dense matrix (\f$ A=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side sparse vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the sparse vector-dense vector
+ // outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ const ConstIterator end( x.end() );
+
+ for( ConstIterator element=x.begin(); element!=end; ++element ) {
+ if( !isDefault( element->value() ) ) {
+ for( size_t j=0UL; j<y.size(); ++j ) {
+ (~A)(element->index(),j) = element->value() * y[j];
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized assignment to row-major dense matrices*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized assignment of a sparse vector-dense vector outer product to a row-major
+ // dense matrix (\f$ A=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side sparse vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized assignment kernel for the sparse vector-dense vector
+ // outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT4>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const ConstIterator begin( x.begin() );
+ const ConstIterator end ( x.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element )
+ {
+ const SIMDTrait_<ElementType> x1( set( element->value() ) );
+
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ (~A).store( element->index(), j, x1 * y.load(j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ (~A)(element->index(),j) = element->value() * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector outer product expression to a column-major dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands is an expression or any of the two involved element
+ // types is non-numeric data type.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( DenseMatrix<MT,true>& lhs, const SVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator end( x.end() );
+
+ for( size_t i=0UL; i<y.size(); ++i ) {
+ if( !isDefault( y[i] ) ) {
+ for( ConstIterator element=x.begin(); element!=end; ++element ) {
+ (~lhs)(element->index(),i) = element->value() * y[i];
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector outer product to a row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector outer product expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,false>& lhs, const SVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns() , "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator begin( x.begin() );
+ const ConstIterator end ( x.end() );
+
+ if( begin == end )
+ return;
+
+ (~lhs).reserve( begin->index(), rhs.nonZeros() );
+
+ size_t index( 0UL );
+
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ if( !isDefault( element->value() ) ) {
+ for( ; index < element->index(); ++index ) {
+ (~lhs).finalize( index );
+ }
+ for( size_t i=0UL; i<y.size(); ++i ) {
+ (~lhs).append( element->index(), i, element->value() * y[i] );
+ }
+ (~lhs).finalize( index++ );
+ }
+ }
+
+ for( ; index < x.size(); ++index ) {
+ (~lhs).finalize( index );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-dense vector outer product to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-dense
+ // vector outer product expression to a column-major sparse matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands is an expression or any of the two involved element
+ // types is non-numeric data type.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ assign( SparseMatrix<MT,true>& lhs, const SVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).capacity() >= rhs.nonZeros(), "Insufficient capacity" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator begin( x.begin() );
+ const ConstIterator end ( x.end() );
+
+ if( begin == end )
+ return;
+
+ for( size_t i=0UL; i<y.size(); ++i ) {
+ if( !isDefault( y[i] ) ) {
+ for( ConstIterator element=begin; element!=end; ++element ) {
+ (~lhs).append( element->index(), i, element->value() * y[i] );
+ }
+ }
+ (~lhs).finalize( i );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to row-major dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-dense vector outer product to a row-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // dense vector outer product expression to a row-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,false>& lhs, const SVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ SVecTDVecMultExpr::selectAddAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a sparse vector-dense vector outer product to a
+ // row-major dense matrix (\f$ A+=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side sparse vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the sparse vector-dense
+ // vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectAddAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ const ConstIterator end( x.end() );
+
+ for( ConstIterator element=x.begin(); element!=end; ++element ) {
+ if( !isDefault( element->value() ) ) {
+ for( size_t i=0UL; i<y.size(); ++i ) {
+ (~A)(element->index(),i) += element->value() * y[i];
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized addition assignment to row-major dense matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized addition assignment of a sparse vector-dense vector outer product to a
+ // row-major dense matrix (\f$ A+=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side sparse vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized addition assignment kernel for the sparse vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectAddAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT4>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const ConstIterator begin( x.begin() );
+ const ConstIterator end ( x.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element )
+ {
+ const SIMDTrait_<ElementType> x1( set( element->value() ) );
+
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ (~A).store( element->index(), j, (~A).load(element->index(),j) + x1 * y.load(j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ (~A)(element->index(),j) += element->value() * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to column-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-dense vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // dense vector outer product expression to a column-major dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands is an expression or any of the two involved element
+ // types is non-numeric data type.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ addAssign( DenseMatrix<MT,true>& lhs, const SVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator end( x.end() );
+
+ for( size_t i=0UL; i<y.size(); ++i ) {
+ if( !isDefault( y[i] ) ) {
+ for( ConstIterator element=x.begin(); element!=end; ++element ) {
+ (~lhs)(element->index(),i) += element->value() * y[i];
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to row-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-dense vector outer product to a row-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // dense vector outer product expression to a row-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,false>& lhs, const SVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ SVecTDVecMultExpr::selectSubAssignKernel( ~lhs, x, y );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a sparse vector-dense vector outer product to a
+ // row-major dense matrix (\f$ A-=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side sparse vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the sparse vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<MT,VT3,VT4> >
+ selectSubAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ const ConstIterator end( x.end() );
+
+ for( ConstIterator element=x.begin(); element!=end; ++element ) {
+ if( !isDefault( element->value() ) ) {
+ for( size_t i=0UL; i<y.size(); ++i ) {
+ (~A)(element->index(),i) -= element->value() * y[i];
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized subtraction assignment to row-major dense matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized subtraction assignment of a sparse vector-dense vector outer product to a
+ // row-major dense matrix (\f$ A-=\vec{x}*\vec{y}^T \f$).
+ // \ingroup dense_vector
+ //
+ // \param A The target left-hand side dense matrix.
+ // \param x The left-hand side sparse vector operand.
+ // \param y The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized subtraction assignment kernel for the sparse vector-
+ // dense vector outer product.
+ */
+ template< typename MT // Type of the left-hand side target matrix
+ , typename VT3 // Type of the left-hand side vector operand
+ , typename VT4 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<MT,VT3,VT4> >
+ selectSubAssignKernel( DenseMatrix<MT,false>& A, const VT3& x, const VT4& y )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ const size_t N( (~A).columns() );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT4>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const ConstIterator begin( x.begin() );
+ const ConstIterator end ( x.end() );
+
+ for( ConstIterator element=begin; element!=end; ++element )
+ {
+ const SIMDTrait_<ElementType> x1( set( element->value() ) );
+
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ (~A).store( element->index(), j, (~A).load(element->index(),j) - x1 * y.load(j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ (~A)(element->index(),j) -= element->value() * y[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to column-major dense matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-dense vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // dense vector outer product expression to a column-major dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two operands is an expression or any of the two involved element
+ // types is non-numeric data type.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline EnableIf_< UseAssign<MT> >
+ subAssign( DenseMatrix<MT,true>& lhs, const SVecTDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const ConstIterator end( x.end() );
+
+ for( size_t i=0UL; i<y.size(); ++i ) {
+ if( !isDefault( y[i] ) ) {
+ for( ConstIterator element=x.begin(); element!=end; ++element ) {
+ (~lhs)(element->index(),i) -= element->value() * y[i];
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECTVECMULTEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the sparse vector-dense vector outer product
+// (\f$ A=\vec{b}*\vec{c}^T \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse vector for the outer product.
+// \param rhs The right-hand side transpose dense vector for the outer product.
+// \return The resulting sparse matrix.
+//
+// This operator represents the outer product between a sparse vector and a transpose dense
+// vector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+ using blaze::rowMajor;
+
+ blaze::CompressedVector<double,columnVector> a;
+ blaze::DynamicVector<double,rowVector> b;
+ blaze::CompressedMatrix<double<rowMajor> A;
+ // ... Resizing and initialization
+ A = a * b;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both
+// vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 > // Type of the right-hand side dense vector
+inline const SVecTDVecMultExpr<T1,T2>
+ operator*( const SparseVector<T1,false>& lhs, const DenseVector<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecTDVecMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct Rows< SVecTDVecMultExpr<VT1,VT2> > : public Size<VT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct Columns< SVecTDVecMultExpr<VT1,VT2> > : public Size<VT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool AF >
+struct SubmatrixExprTrait< SVecTDVecMultExpr<VT1,VT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct RowExprTrait< SVecTDVecMultExpr<VT1,VT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< ReturnType_<VT1>, VT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct ColumnExprTrait< SVecTDVecMultExpr<VT1,VT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< VT1, ReturnType_<VT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecTSVecMultExpr.h b/src/cpu/blaze/math/expressions/SVecTSVecMultExpr.h
new file mode 100644
index 00000000..2023ac1a
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecTSVecMultExpr.h
@@ -0,0 +1,846 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecTSVecMultExpr.h
+// \brief Header file for the sparse vector/sparse vector outer product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECTSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECTSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/VecTVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/VecTVecMultExpr.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECTSVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-sparse vector outer products.
+// \ingroup sparse_matrix_expression
+//
+// The SVecTSVecMultExpr class represents the compile time expression for sparse vector-sparse
+// vector outer products.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 > // Type of the right-hand side sparse vector
+class SVecTSVecMultExpr : public SparseMatrix< SVecTSVecMultExpr<VT1,VT2>, false >
+ , private VecTVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT1> RT1; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<VT2> RT2; //!< Result type of the right-hand side sparse vector expression.
+ typedef ReturnType_<VT1> RN1; //!< Return type of the left-hand side sparse vector expression.
+ typedef ReturnType_<VT2> RN2; //!< Return type of the right-hand side sparse vector expression.
+ typedef CompositeType_<VT1> CT1; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<VT2> CT2; //!< Composite type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either vector operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef MultExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecTSVecMultExpr<VT1,VT2> This; //!< Type of this SVecTSVecMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT1>, const VT1, const VT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT2>, const VT2, const VT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense vector operand.
+ typedef If_< IsComputation<VT1>, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef If_< IsComputation<VT2>, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecTSVecMultExpr class.
+ //
+ // \param lhs The left-hand side sparse vector operand of the multiplication expression.
+ // \param rhs The right-hand side sparse vector operand of the multiplication expression.
+ */
+ explicit inline SVecTSVecMultExpr( const VT1& lhs, const VT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse vector of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse vector of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.size(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.size(), "Invalid column access index" );
+
+ return lhs_[i] * rhs_[j];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() * rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return ( isDefault( lhs_[i] ) )?( size_t(0) ):( rhs_.nonZeros(i) );
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to row-major dense matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector outer product to a row-major dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector outer product expression to a row-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,false>& lhs, const SVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > RightIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( LeftIterator lelem=x.begin(); lelem!=lend; ++lelem ) {
+ if( !isDefault( lelem->value() ) ) {
+ for( RightIterator relem=y.begin(); relem!=rend; ++relem ) {
+ (~lhs)(lelem->index(),relem->index()) = lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,true>& lhs, const SVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > RightIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( RightIterator relem=y.begin(); relem!=rend; ++relem ) {
+ if( !isDefault( relem->value() ) ) {
+ for( LeftIterator lelem=x.begin(); lelem!=lend; ++lelem ) {
+ (~lhs)(lelem->index(),relem->index()) = lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector outer product to a row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector outer product expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,false>& lhs, const SVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).capacity() >= rhs.nonZeros(), "Insufficient capacity" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > RightIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+ size_t index( 0UL );
+
+ for( LeftIterator lelem=x.begin(); lelem!=lend; ++lelem ) {
+ if( !isDefault( lelem->value() ) ) {
+ for( ; index < lelem->index(); ++index ) {
+ (~lhs).finalize( index );
+ }
+ for( RightIterator relem=y.begin(); relem!=rend; ++relem ) {
+ (~lhs).append( lelem->index(), relem->index(), lelem->value() * relem->value() );
+ }
+ (~lhs).finalize( index++ );
+ }
+ }
+
+ for( ; index < x.size(); ++index ) {
+ (~lhs).finalize( index );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector-sparse vector outer product to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side outer product expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector-sparse
+ // vector outer product expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,true>& lhs, const SVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).capacity() >= rhs.nonZeros(), "Insufficient capacity" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > RightIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+ size_t index( 0UL );
+
+ for( RightIterator relem=y.begin(); relem!=rend; ++relem ) {
+ if( !isDefault( relem->value() ) ) {
+ for( ; index < relem->index(); ++index ) {
+ (~lhs).finalize( index );
+ }
+ for( LeftIterator lelem=x.begin(); lelem!=lend; ++lelem ) {
+ (~lhs).append( lelem->index(), relem->index(), lelem->value() * relem->value() );
+ }
+ (~lhs).finalize( index++ );
+ }
+ }
+
+ for( ; index < y.size(); ++index ) {
+ (~lhs).finalize( index );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to row-major dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-sparse vector outer product to a row-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // sparse vector outer product expression to a row-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,false>& lhs, const SVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > RightIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( LeftIterator lelem=x.begin(); lelem!=lend; ++lelem ) {
+ if( !isDefault( lelem->value() ) ) {
+ for( RightIterator relem=y.begin(); relem!=rend; ++relem ) {
+ (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to column-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector-sparse vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse vector-
+ // sparse vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,true>& lhs, const SVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > RightIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( RightIterator relem=y.begin(); relem!=rend; ++relem ) {
+ if( !isDefault( relem->value() ) ) {
+ for( LeftIterator lelem=x.begin(); lelem!=lend; ++lelem ) {
+ (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to row-major dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-sparse vector outer product to a row-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // sparse vector outer product expression to a row-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,false>& lhs, const SVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > RightIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( LeftIterator lelem=x.begin(); lelem!=lend; ++lelem ) {
+ if( !isDefault( lelem->value() ) ) {
+ for( RightIterator relem=y.begin(); relem!=rend; ++relem ) {
+ (~lhs)(lelem->index(),relem->index()) -= lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to column-major dense matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector-sparse vector outer product to a column-major
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side outer product expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse vector-
+ // sparse vector outer product expression to a column-major dense matrix.
+ */
+ template< typename MT > // Type of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,true>& lhs, const SVecTSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > RightIterator;
+
+ LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
+ RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
+
+ const LeftIterator lend( x.end() );
+ const RightIterator rend( y.end() );
+
+ for( RightIterator relem=y.begin(); relem!=rend; ++relem ) {
+ if( !isDefault( relem->value() ) ) {
+ for( LeftIterator lelem=x.begin(); lelem!=lend; ++lelem ) {
+ (~lhs)(lelem->index(),relem->index()) -= lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_VECTVECMULTEXPR( VT1, VT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the sparse vector-sparse vector outer product
+// (\f$ A=\vec{b}*\vec{c}^T \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse vector for the outer product.
+// \param rhs The right-hand side transpose sparse vector for the outer product.
+// \return The resulting sparse matrix.
+//
+// This operator represents the outer product between a sparse vector and a transpose sparse
+// vector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowMajor;
+
+ blaze::CompressedVector<double,columnVector> a, b;
+ blaze::CompressedMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ A = a * trans(b);
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both
+// vector types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const SVecTSVecMultExpr<T1,T2>
+ operator*( const SparseVector<T1,false>& lhs, const SparseVector<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecTSVecMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct Rows< SVecTSVecMultExpr<VT1,VT2> > : public Size<VT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct Columns< SVecTSVecMultExpr<VT1,VT2> > : public Size<VT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool AF >
+struct SubmatrixExprTrait< SVecTSVecMultExpr<VT1,VT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT1,AF>
+ , SubvectorExprTrait_<const VT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct RowExprTrait< SVecTSVecMultExpr<VT1,VT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< ReturnType_<VT1>, VT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2 >
+struct ColumnExprTrait< SVecTSVecMultExpr<VT1,VT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< VT1, ReturnType_<VT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecTransExpr.h b/src/cpu/blaze/math/expressions/SVecTransExpr.h
new file mode 100644
index 00000000..ac8cbb39
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecTransExpr.h
@@ -0,0 +1,903 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecTransExpr.h
+// \brief Header file for the sparse vector transpose expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECTRANSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DVecTransposer.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/SVecTransposer.h>
+#include <blaze/math/expressions/VecTransExpr.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/SVecTransExprTrait.h>
+#include <blaze/math/traits/TransExprTrait.h>
+#include <blaze/math/traits/TSVecTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EmptyType.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECTRANSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector transpositions.
+// \ingroup sparse_vector_expression
+//
+// The SVecTransExpr class represents the compile time expression for transpositions of
+// sparse vectors.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+class SVecTransExpr : public SparseVector< SVecTransExpr<VT,TF>, TF >
+ , private VecTransExpr
+ , private If< IsComputation<VT>, Computation, EmptyType >::Type
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef CompositeType_<VT> CT; //!< Composite type of the sparse vector expression.
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ //! Compilation switch for the serial evaluation strategy of the transposition expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the serial evaluation strategy of the transposition expression. In case the given sparse
+ vector expression of type \a VT requires an intermediate evaluation, \a useAssign will be
+ set to 1 and the transposition expression will be evaluated via the \a assign function
+ family. Otherwise \a useAssign will be set to 0 and the expression will be evaluated via
+ the subscript operator. */
+ enum : bool { useAssign = RequiresEvaluation<VT>::value };
+
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target vector is SMP assignable and the sparse vector operand requires
+ an intermediate evaluation, \a value is set to 1 and the expression specific evaluation
+ strategy is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename VT2 >
+ struct UseSMPAssign {
+ enum : bool { value = VT2::smpAssignable && useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecTransExpr<VT,TF> This; //!< Type of this SVecTransExpr instance.
+ typedef TransposeType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef ResultType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const SVecTransExpr& > CompositeType;
+
+ //! Composite data type of the sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > Operand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**ConstIterator class definition**************************************************************
+ /*!\brief Iterator over the elements of the sparse vector absolute value expression.
+ */
+ class ConstIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Iterator type of the sparse vector expression.
+ typedef ConstIterator_< RemoveReference_<Operand> > IteratorType;
+
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef typename std::iterator_traits<IteratorType>::value_type ValueType; //!< Type of the underlying pointers.
+ typedef typename std::iterator_traits<IteratorType>::pointer PointerType; //!< Pointer return type.
+ typedef typename std::iterator_traits<IteratorType>::reference ReferenceType; //!< Reference return type.
+ typedef typename std::iterator_traits<IteratorType>::difference_type DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ConstIterator class.
+ */
+ inline ConstIterator( IteratorType it )
+ : it_( it ) // Iterator over the elements of the sparse vector expression
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented expression iterator.
+ */
+ inline ConstIterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline const ValueType operator*() const {
+ return *it_;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const ConstIterator* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse element.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReturnType value() const {
+ return it_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline size_t index() const {
+ return it_->index();
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const ConstIterator& rhs ) const {
+ return it_ == rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ConstIterator objects.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const ConstIterator& rhs ) const {
+ return it_ != rhs.it_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two expression iterators.
+ //
+ // \param rhs The right-hand side expression iterator.
+ // \return The number of elements between the two expression iterators.
+ */
+ inline DifferenceType operator-( const ConstIterator& rhs ) const {
+ return it_ - rhs.it_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType it_; //!< Iterator over the elements of the sparse vector expression.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecTransExpr class.
+ //
+ // \param sv The sparse vector operand of the transposition expression.
+ */
+ explicit inline SVecTransExpr( const VT& sv ) noexcept
+ : sv_( sv ) // Sparse vector of the transposition expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < sv_.size(), "Invalid vector access index" );
+ return sv_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= sv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator begin() const {
+ return ConstIterator( sv_.begin() );
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator end() const {
+ return ConstIterator( sv_.end() );
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return sv_.size();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse vector.
+ //
+ // \return The number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return sv_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Searches for a specific vector element.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ */
+ inline ConstIterator find( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( sv_.find( index ) );
+ }
+ //**********************************************************************************************
+
+ //**LowerBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index not less then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index not less then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator lowerBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( sv_.lowerBound( index ) );
+ }
+ //**********************************************************************************************
+
+ //**UpperBound function*************************************************************************
+ /*!\brief Returns an iterator to the first index greater then the given index.
+ //
+ // \param index The index of the search element.
+ // \return Iterator to the first index greater then the given index, end() iterator otherwise.
+ */
+ inline ConstIterator upperBound( size_t index ) const {
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+ return ConstIterator( sv_.upperBound( index ) );
+ }
+ //**********************************************************************************************
+
+ //**Operand access******************************************************************************
+ /*!\brief Returns the sparse vector operand.
+ //
+ // \return The sparse vector operand.
+ */
+ inline Operand operand() const noexcept {
+ return sv_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return sv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return sv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return sv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ Operand sv_; //!< Sparse vector of the transposition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector transposition expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector
+ // transposition expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ assign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse vector transposition expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse vector
+ // transposition expression to a sparse vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ SVecTransposer<VT2,!TF> tmp( ~lhs );
+ assign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse vector transposition expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse
+ // vector transposition expression to a dense vector. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case
+ // the operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ addAssign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse vector transposition expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // vector transposition expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ subAssign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse vector transposition expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // vector transposition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the operand
+ // requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ multAssign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector transposition expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector
+ // transposition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpAssign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse vector transposition expression to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side transposition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse vector
+ // transposition expression to a sparse vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ SVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpAssign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse vector transposition expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // vector transposition expression to a dense vector. Due to the explicit application of
+ // the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpAddAssign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse vector transposition expression to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // vector transposition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpSubAssign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse vector transposition expression to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side transposition expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a sparse
+ // vector transposition expression to a dense vector. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,TF>& lhs, const SVecTransExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ DVecTransposer<VT2,!TF> tmp( ~lhs );
+ smpMultAssign( tmp, rhs.sv_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Calculation of the transpose of the given sparse vector.
+// \ingroup sparse_vector
+//
+// \param sv The sparse vector to be transposed.
+// \return The transpose of the sparse vector.
+//
+// This function returns an expression representing the transpose of the given sparse vector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ blaze::CompressedVector<double,columnVector> a;
+ blaze::CompressedVector<double,rowVector> b;
+ // ... Resizing and initialization
+ b = trans( a );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline const SVecTransExpr<VT,!TF> trans( const SparseVector<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SVecTransExpr<VT,!TF>( ~sv );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating the transpose of a transpose sparse vector.
+// \ingroup sparse_vector
+//
+// \param sv The sparse vector to be (re-)transposed.
+// \return The transpose of the transpose vector.
+//
+// This function implements a performance optimized treatment of the transpose operation on a
+// sparse vector transpose expression. It returns an expression representing the transpose of a
+// transpose sparse vector:
+
+ \code
+ using blaze::columnVector;
+
+ blaze::CompressedVector<double,columnVector> a, b;
+ // ... Resizing and initialization
+ b = trans( trans( a ) );
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline typename SVecTransExpr<VT,TF>::Operand trans( const SVecTransExpr<VT,TF>& sv )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return sv.operand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct Size< SVecTransExpr<VT,TF> > : public Size<VT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct SVecTransExprTrait< SVecTransExpr<VT,false> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , Operand_< SVecTransExpr<VT,false> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT >
+struct TSVecTransExprTrait< SVecTransExpr<VT,true> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , Operand_< SVecTransExpr<VT,true> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF, bool AF >
+struct SubvectorExprTrait< SVecTransExpr<VT,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = TransExprTrait_< SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SVecTransposer.h b/src/cpu/blaze/math/expressions/SVecTransposer.h
new file mode 100644
index 00000000..fedb89e3
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SVecTransposer.h
@@ -0,0 +1,509 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SVecTransposer.h
+// \brief Header file for the sparse vector transposer
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SVECTRANSPOSER_H_
+#define _BLAZE_MATH_EXPRESSIONS_SVECTRANSPOSER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SVECTRANSPOSER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for the transposition of a sparse vector.
+// \ingroup sparse_vector_expression
+//
+// The SVecTransposer class is a wrapper object for the temporary transposition of a sparse vector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+class SVecTransposer : public SparseVector< SVecTransposer<VT,TF>, TF >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef SVecTransposer<VT,TF> This; //!< Type of this SVecTransposer instance.
+ typedef TransposeType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef ResultType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Resulting element type.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<VT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<VT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<VT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<VT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SVecTransposer class.
+ //
+ // \param sv The sparse vector operand.
+ */
+ explicit inline SVecTransposer( VT& sv ) noexcept
+ : sv_( sv ) // The sparse vector operand
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Reference to the accessed value.
+ */
+ inline ConstReference operator[]( size_t index ) const {
+ BLAZE_USER_ASSERT( index < sv_.size(), "Invalid vector access index" );
+ return sv_[index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ConstReference at( size_t index ) const {
+ if( index >= sv_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline Iterator begin() {
+ return sv_.begin();
+ }
+ //**********************************************************************************************
+
+ //**Begin function******************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator begin() const {
+ return sv_.cbegin();
+ }
+ //**********************************************************************************************
+
+ //**Cbegin function*****************************************************************************
+ /*!\brief Returns an iterator to the first non-zero element of the sparse vector.
+ //
+ // \return Iterator to the first non-zero element of the sparse vector.
+ */
+ inline ConstIterator cbegin() const {
+ return sv_.cbegin();
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline Iterator end() {
+ return sv_.end();
+ }
+ //**********************************************************************************************
+
+ //**End function********************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator end() const {
+ return sv_.cend();
+ }
+ //**********************************************************************************************
+
+ //**Cend function*******************************************************************************
+ /*!\brief Returns an iterator just past the last non-zero element of the sparse vector.
+ //
+ // \return Iterator just past the last non-zero element of the sparse vector.
+ */
+ inline ConstIterator cend() const {
+ return sv_.cend();
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment operator**********************************************************
+ /*!\brief Multiplication assignment operator for the multiplication between a vector and
+ // a scalar value (\f$ \vec{a}*=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the multiplication.
+ // \return Reference to this SVecTransposer.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, SVecTransposer >& operator*=( Other rhs )
+ {
+ (~sv_) *= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Division assignment operator****************************************************************
+ /*!\brief Division assignment operator for the division of a vector by a scalar value
+ // (\f$ \vec{a}/=s \f$).
+ //
+ // \param rhs The right-hand side scalar value for the division.
+ // \return Reference to this SVecTransposer.
+ //
+ // \note A division by zero is only checked by an user assert.
+ */
+ template< typename Other > // Data type of the right-hand side scalar
+ inline EnableIf_< IsNumeric<Other>, SVecTransposer >& operator/=( Other rhs )
+ {
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ (~sv_) /= rhs;
+ return *this;
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return sv_.size();
+ }
+ //**********************************************************************************************
+
+ //**Reset function******************************************************************************
+ /*!\brief Resets the vector elements.
+ //
+ // \return void
+ */
+ inline void reset() {
+ return sv_.reset();
+ }
+ //**********************************************************************************************
+
+ //**Insert function*****************************************************************************
+ /*!\brief Inserting an element into the sparse vector.
+ //
+ // \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+ // \param value The value of the element to be inserted.
+ // \return Iterator to the inserted element.
+ // \exception std::invalid_argument Invalid sparse vector access index.
+ //
+ // This function inserts a new element into the sparse vector. However, duplicate elements are
+ // not allowed. In case the sparse matrix already contains an element with row index \a index,
+ // a \a std::invalid_argument exception is thrown.
+ */
+ inline Iterator insert( size_t index, const ElementType& value ) {
+ return sv_.insert( index, value );
+ }
+ //**********************************************************************************************
+
+ //**Find function*******************************************************************************
+ /*!\brief Inserting an element into the sparse vector.
+ //
+ // \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+ // \return Iterator to the element in case the index is found, end() iterator otherwise.
+ //
+ // This function can be used to check whether a specific element is contained in the sparse
+ // vector. It specifically searches for the element with index \a index. In case the element
+ // is found, the function returns an iterator to the element. Otherwise an iterator just past
+ // the last non-zero element of the sparse vector (the end() iterator) is returned. Note that
+ // the returned sparse vector iterator is subject to invalidation due to inserting operations
+ // via the subscript operator or the insert() function!
+ */
+ inline Iterator find( size_t index ) {
+ return sv_.find( index );
+ }
+ //**********************************************************************************************
+
+ //**Reserve function****************************************************************************
+ /*!\brief Setting the minimum capacity of the sparse vector.
+ //
+ // \param nonzeros The new minimum capacity of the sparse vector.
+ // \return void
+ //
+ // This function increases the capacity of the sparse vector to at least \a nonzeros elements.
+ // The current values of the vector elements are preserved.
+ */
+ inline void reserve( size_t nonzeros ) {
+ sv_.reserve( nonzeros );
+ }
+ //**********************************************************************************************
+
+ //**Append function*****************************************************************************
+ /*!\brief Appending an element to the sparse vector.
+ //
+ // \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+ // \param value The value of the element to be appended.
+ // \param check \a true if the new value should be checked for default values, \a false if not.
+ // \return void
+ //
+ // This function provides a very efficient way to fill a sparse vector with elements. It
+ // appends a new element to the end of the sparse vector without any additional memory
+ // allocation. Therefore it is strictly necessary to keep the following preconditions in
+ // mind:
+ //
+ // - the index of the new element must be strictly larger than the largest index of non-zero
+ // elements in the sparse vector
+ // - the current number of non-zero elements must be smaller than the capacity of the vector
+ //
+ // Ignoring these preconditions might result in undefined behavior! The optional \a check
+ // parameter specifies whether the new value should be tested for a default value. If the new
+ // value is a default value (for instance 0 in case of an integral element type) the value is
+ // not appended. Per default the values are not tested.
+ //
+ // \note Although append() does not allocate new memory, it still invalidates all iterators
+ // returned by the end() functions!
+ */
+ inline void append( size_t index, const ElementType& value, bool check=false ) {
+ sv_.append( index, value, check );
+ }
+ //**********************************************************************************************
+
+ //**CanAlias function***************************************************************************
+ /*!\brief Returns whether the vector can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this vector, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool canAlias( const Other* alias ) const noexcept
+ {
+ return sv_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**IsAliased function**************************************************************************
+ /*!\brief Returns whether the vector is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the alias corresponds to this vector, \a false if not.
+ */
+ template< typename Other > // Data type of the foreign expression
+ inline bool isAliased( const Other* alias ) const noexcept
+ {
+ return sv_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**CanSMPAssign function***********************************************************************
+ /*!\brief Returns whether the vector can be used in SMP assignments.
+ //
+ // \return \a true in case the vector can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept
+ {
+ return sv_.canSMPAssign();
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of dense vectors*******************************************************
+ /*!\brief Implementation of the transpose assignment of a dense vector.
+ //
+ // \param rhs The right-hand side dense vector to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side dense vector
+ inline void assign( const DenseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( sv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<sv_.size(); ++i ) {
+ if( !isDefault( (~rhs)[i] ) ) {
+ if( nonzeros++ == sv_.capacity() )
+ sv_.reserve( extendCapacity() );
+ sv_.append( i, (~rhs)[i] );
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Transpose assignment of sparse vectors******************************************************
+ /*!\brief Implementation of the transpose assignment of a sparse vector.
+ //
+ // \param rhs The right-hand side sparse vector to be assigned.
+ // \return void
+ //
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might result
+ // in erroneous results and/or in compilation errors. Instead of using this function use the
+ // assignment operator.
+ */
+ template< typename VT2 > // Type of the right-hand side sparse vector
+ inline void assign( const SparseVector<VT2,TF>& rhs )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF );
+
+ BLAZE_INTERNAL_ASSERT( sv_.size() == (~rhs).size(), "Invalid vector sizes" );
+
+ // Using the following formulation instead of a std::copy function call of the form
+ //
+ // end_ = std::copy( (~rhs).begin(), (~rhs).end(), begin_ );
+ //
+ // results in much less requirements on the ConstIterator type provided from the right-hand
+ // sparse vector type
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ sv_.append( element->index(), element->value() );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ /*!\brief Calculating a new vector capacity.
+ //
+ // \return The new compressed vector capacity.
+ //
+ // This function calculates a new vector capacity based on the current capacity of the sparse
+ // vector. Note that the new capacity is restricted to the interval \f$[7..size]\f$.
+ */
+ inline size_t extendCapacity() const noexcept
+ {
+ using blaze::max;
+ using blaze::min;
+
+ size_t nonzeros( 2UL*sv_.capacity()+1UL );
+ nonzeros = max( nonzeros, 7UL );
+ nonzeros = min( nonzeros, sv_.size() );
+
+ BLAZE_INTERNAL_ASSERT( nonzeros > sv_.capacity(), "Invalid capacity value" );
+
+ return nonzeros;
+ }
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ VT& sv_; //!< The sparse vector operand.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, !TF );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resetting the sparse vector contained in a SVecTransposer.
+// \ingroup sparse_vector_expression
+//
+// \param v The sparse vector to be resetted.
+// \return void
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline void reset( SVecTransposer<VT,TF>& v )
+{
+ v.reset();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct SubvectorTrait< SVecTransposer<VT,TF> >
+{
+ using Type = SubvectorTrait_< ResultType_< SVecTransposer<VT,TF> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SerialExpr.h b/src/cpu/blaze/math/expressions/SerialExpr.h
new file mode 100644
index 00000000..4338505d
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SerialExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SerialExpr.h
+// \brief Header file for the SerialExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SERIALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all serial evaluation expression templates.
+// \ingroup math
+//
+// The SerialExpr class serves as a tag for all expression templates that enforce a serial
+// evaluation. All classes, that represent a serialization operation and that are used within
+// the expression template environment of the Blaze library have to derive from this class in
+// order to qualify as serial evaluation expression template. Only in case a class is derived
+// from the SerialExpr base class, the IsSerialExpr type trait recognizes the class as valid
+// serial evaluation expression template.
+*/
+struct SerialExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SparseMatrix.h b/src/cpu/blaze/math/expressions/SparseMatrix.h
new file mode 100644
index 00000000..1a32a05a
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SparseMatrix.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SparseMatrix.h
+// \brief Header file for the SparseMatrix base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SPARSEMATRIX_H_
+#define _BLAZE_MATH_EXPRESSIONS_SPARSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Matrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup sparse_matrix Sparse Matrices
+// \ingroup matrix
+*/
+/*!\defgroup sparse_matrix_expression Expressions
+// \ingroup sparse_matrix
+*/
+/*!\brief Base class for sparse matrices.
+// \ingroup sparse_matrix
+//
+// The SparseMatrix class is a base class for all sparse matrix classes. It provides an
+// abstraction from the actual type of the sparse matrix, but enables a conversion back
+// to this type via the Matrix base class.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+struct SparseMatrix : public Matrix<MT,SO>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SparseVector.h b/src/cpu/blaze/math/expressions/SparseVector.h
new file mode 100644
index 00000000..3cf77c06
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SparseVector.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SparseVector.h
+// \brief Header file for the SparseVector base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SPARSEVECTOR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SPARSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Vector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup sparse_vector Sparse Vectors
+// \ingroup vector
+*/
+/*!\defgroup sparse_vector_expression Expressions
+// \ingroup sparse_vector
+*/
+/*!\brief Base class for sparse vectors.
+// \ingroup sparse_vector
+//
+// The SparseVector class is a base class for all arbitrarily sized (N-dimensional) sparse
+// vectors. It provides an abstraction from the actual type of the sparse vector, but enables
+// a conversion back to this type via the Vector base class.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+struct SparseVector : public Vector<VT,TF>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/SubExpr.h b/src/cpu/blaze/math/expressions/SubExpr.h
new file mode 100644
index 00000000..2ac42648
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/SubExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/SubExpr.h
+// \brief Header file for the SubExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_SUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_SUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all subtraction expression templates.
+// \ingroup math
+//
+// The SubExpr class serves as a tag for all expression templates that implement mathematical
+// subtractions. All classes, that represent a mathematical subtraction (vector subtractions
+// and matrix subtractions) and that are used within the expression template environment of the
+// Blaze library have to derive from this class in order to qualify as subtraction expression
+// template. Only in case a class is derived from the SubExpr base class, the IsSubExpr type
+// trait recognizes the class as valid subtraction expression template.
+*/
+struct SubExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDMatDMatMultExpr.h b/src/cpu/blaze/math/expressions/TDMatDMatMultExpr.h
new file mode 100644
index 00000000..0e1add13
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDMatDMatMultExpr.h
@@ -0,0 +1,11474 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDMatDMatMultExpr.h
+// \brief Header file for the transpose dense matrix/dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDMATDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDMATDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/gemm.h>
+#include <blaze/math/blas/trmm.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/expressions/MatScalarMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDMATDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense matrix-dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The TDMatDMatMultExpr class represents the compile time expression for multiplications between
+// a column-major dense matrix and a row-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class TDMatDMatMultExpr : public DenseMatrix< TDMatDMatMultExpr<MT1,MT2>, true >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the types of all three involved matrices are suited for a BLAS kernel, the nested
+ \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !( IsDiagonal<T2>::value && IsDiagonal<T3>::value ) &&
+ !( IsDiagonal<T2>::value && IsColumnMajorMatrix<T1>::value ) &&
+ !( IsDiagonal<T3>::value && IsRowMajorMatrix<T1>::value ) &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDMatDMatMultExpr<MT1,MT2> This; //!< Type of this TDMatDMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !( IsDiagonal<MT1>::value && IsDiagonal<MT2>::value ) &&
+ MT1::simdEnabled && MT2::simdEnabled &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDMatDMatMultExpr class.
+ //
+ // \param lhs The left-hand side operand of the multiplication expression.
+ // \param rhs The right-hand side operand of the multiplication expression.
+ */
+ explicit inline TDMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose dense matrix operand.
+ //
+ // \return The left-hand side transpose dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( rows() * columns() < TDMATDMATMULT_THRESHOLD ) ) &&
+ ( columns() > SMP_TDMATDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-dense matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const TDMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( rhs.lhs_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a transpose dense matrix-dense matrix
+ // multiplication to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value && IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < TDMATDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( C, A, B );
+ else
+ selectBlasAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (general/general)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general transpose dense matrix-general dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general transpose dense matrix-general
+ // dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ if( IsStrictlyTriangular<MT4>::value && kbegin == kend ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ continue;
+ }
+
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? kbegin+1UL : kbegin )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? kbegin : kbegin+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT4>::value && IsUpper<MT5>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ else if( IsStrictlyUpper<MT5>::value ) {
+ reset( (~C)(i,0UL) );
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) = A(i,kbegin) * B(kbegin,j);
+ }
+ if( IsLower<MT4>::value && IsLower<MT5>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ else if( IsStrictlyLower<MT5>::value ) {
+ reset( (~C)(i,N-1UL) );
+ }
+ }
+
+ for( size_t k=kbegin+1UL; k<kend; ++k )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? k-1UL : k )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ if( IsLower<MT5>::value ) {
+ (~C)(i,jend) = A(i,k) * B(k,jend);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (general/general)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general transpose dense matrix-general dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general transpose dense matrix-general
+ // dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ if( IsStrictlyTriangular<MT5>::value && kbegin == kend ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ continue;
+ }
+
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? kbegin+1UL : kbegin )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? kbegin : kbegin+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value && IsLower<MT5>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ else if( IsStrictlyLower<MT4>::value ) {
+ reset( (~C)(0UL,j) );
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) = A(i,kbegin) * B(kbegin,j);
+ }
+ if( IsUpper<MT4>::value && IsUpper<MT5>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ else if( IsStrictlyUpper<MT4>::value ) {
+ reset( (~C)(M-1UL,j) );
+ }
+ }
+
+ for( size_t k=kbegin+1UL; k<kend; ++k )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? k-1UL : k )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ if( IsUpper<MT4>::value ) {
+ (~C)(iend,j) = A(iend,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (general/diagonal)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general transpose dense matrix-diagonal dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general transpose dense matrix-diagonal
+ // dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT4>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ if( IsUpper<MT4>::value ) {
+ for( size_t j=jj; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) = A(i,j) * B(j,j);
+ }
+ if( IsLower<MT4>::value ) {
+ for( size_t j=jpos; j<jend; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (general/diagonal)************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general transpose dense matrix-diagonal dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general transpose dense matrix-diagonal
+ // dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) = A(i,j) * B(j,j);
+ }
+ if( IsUpper<MT4>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (diagonal/general)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal transpose dense matrix-general dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal transpose dense matrix-general
+ // dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT5>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) = A(i,i) * B(i,j);
+ }
+ if( IsLower<MT5>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (diagonal/general)************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal transpose dense matrix-general dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal transpose dense matrix-general
+ // dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyLower<MT5>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyUpper<MT5>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ if( IsLower<MT5>::value ) {
+ for( size_t i=ii; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) = A(i,i) * B(i,j);
+ }
+ if( IsUpper<MT5>::value ) {
+ for( size_t i=ipos; i<iend; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/diagonal)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal transpose dense matrix-diagonal dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal transpose dense matrix-
+ // diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) = A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small transpose dense matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (small matrices)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small transpose dense matrix-dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a transpose dense matrix-
+ // dense matrix multiplication expression to a row-major dense matrix. This kernel is
+ // optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i, j+SIMDSIZE*4UL, xmm5 );
+ (~C).store( i, j+SIMDSIZE*5UL, xmm6 );
+ (~C).store( i, j+SIMDSIZE*6UL, xmm7 );
+ (~C).store( i, j+SIMDSIZE*7UL, xmm8 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE , xmm2 );
+ (~C).store( i , j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i , j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j+SIMDSIZE , xmm6 );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, xmm7 );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, xmm8 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j+SIMDSIZE, xmm4 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+1UL, j, xmm2 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) = value1;
+ (~C)(i+1UL,j) = value2;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (small matrices)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small transpose dense matrix-dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a transpose dense matrix-
+ // dense matrix multiplication expression to a column-major dense matrix. This kernel is
+ // optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ (~C).store( i+SIMDSIZE*4UL, j, xmm5 );
+ (~C).store( i+SIMDSIZE*5UL, j, xmm6 );
+ (~C).store( i+SIMDSIZE*6UL, j, xmm7 );
+ (~C).store( i+SIMDSIZE*7UL, j, xmm8 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE , j , xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j , xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i+SIMDSIZE , j+1UL, xmm6 );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, xmm7 );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, xmm8 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i+SIMDSIZE, j+1UL, xmm4 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+1UL, xmm2 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) = value1;
+ (~C)(i,j+1UL) = value2;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose dense matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (large matrices)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large transpose dense matrix-dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a transpose dense matrix-
+ // dense matrix multiplication expression to a row-major dense matrix. This kernel is
+ // optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i ,j2) );
+ SIMDType xmm4( (~C).load(i ,j3) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j1) );
+ SIMDType xmm7( (~C).load(i+1UL,j2) );
+ SIMDType xmm8( (~C).load(i+1UL,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i , j2, xmm3 );
+ (~C).store( i , j3, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j1, xmm6 );
+ (~C).store( i+1UL, j2, xmm7 );
+ (~C).store( i+1UL, j3, xmm8 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+ SIMDType xmm3( (~C).load(i,j2) );
+ SIMDType xmm4( (~C).load(i,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ (~C).store( i, j2, xmm3 );
+ (~C).store( i, j3, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+ SIMDType xmm5( (~C).load(i+2UL,j ) );
+ SIMDType xmm6( (~C).load(i+2UL,j1) );
+ SIMDType xmm7( (~C).load(i+3UL,j ) );
+ SIMDType xmm8( (~C).load(i+3UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ (~C).store( i+2UL, j , xmm5 );
+ (~C).store( i+2UL, j1, xmm6 );
+ (~C).store( i+3UL, j , xmm7 );
+ (~C).store( i+3UL, j1, xmm8 );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (large matrices)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large transpose dense matrix-dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a transpose dense matrix-
+ // dense matrix multiplication expression to a column-major dense matrix. This kernel is
+ // optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i2,j ) );
+ SIMDType xmm4( (~C).load(i3,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i1,j+1UL) );
+ SIMDType xmm7( (~C).load(i2,j+1UL) );
+ SIMDType xmm8( (~C).load(i3,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i2, j , xmm3 );
+ (~C).store( i3, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i1, j+1UL, xmm6 );
+ (~C).store( i2, j+1UL, xmm7 );
+ (~C).store( i3, j+1UL, xmm8 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+ SIMDType xmm3( (~C).load(i2,j) );
+ SIMDType xmm4( (~C).load(i3,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ (~C).store( i2, j, xmm3 );
+ (~C).store( i3, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+ SIMDType xmm5( (~C).load(i ,j+2UL) );
+ SIMDType xmm6( (~C).load(i1,j+2UL) );
+ SIMDType xmm7( (~C).load(i ,j+3UL) );
+ SIMDType xmm8( (~C).load(i1,j+3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ (~C).store( i , j+2UL, xmm5 );
+ (~C).store( i1, j+2UL, xmm6 );
+ (~C).store( i , j+3UL, xmm7 );
+ (~C).store( i1, j+3UL, xmm8 );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices (default)*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices*****************************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based assignment of a transpose dense matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ assign( C, B );
+ trmm( C, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ assign( C, A );
+ trmm( C, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ }
+ else {
+ gemm( C, A, B, ET(1), ET(0) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-dense matrix multiplication to a sparse matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO>& lhs, const TDMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TDMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a transpose dense matrix-dense
+ // matrix multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value && IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < TDMATDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( C, A, B );
+ else
+ selectBlasAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (general/general)*******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general transpose dense matrix-general dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general transpose dense
+ // matrix-general dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ for( size_t k=kbegin; k<kend; ++k )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? k : k+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) += A(i,k) * B(k,j );
+ (~C)(i,j+1UL) += A(i,k) * B(k,j+1UL);
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) += A(i,k) * B(k,jpos);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (general/general)****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general transpose dense matrix-general dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general transpose dense
+ // matrix-dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ for( size_t k=kbegin; k<kend; ++k )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? k : k+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) += A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) += A(i+1UL,k) * B(k,j);
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) += A(ipos,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (general/diagonal)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general transpose dense matrix-diagonal dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general transpose dense
+ // matrix-diagonal dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT4>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) += A(i,j) * B(j,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (general/diagonal)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general transpose dense matrix-diagonal dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general transpose dense
+ // matrix-diagonal dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) += A(i ,j) * B(j,j);
+ (~C)(i+1UL,j) += A(i+1UL,j) * B(j,j);
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) += A(ipos,j) * B(j,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (diagonal/general)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal transpose dense matrix-general dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal transpose dense
+ // matrix-general dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) += A(i,i) * B(i,j );
+ (~C)(i,j+1UL) += A(i,i) * B(i,j+1UL);
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) += A(i,i) * B(i,jpos);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (diagonal/general)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal transpose dense matrix-general dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal transpose dense
+ // matrix-general dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyLower<MT5>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyUpper<MT5>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) += A(i,i) * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/diagonal)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal transpose dense matrix-diagonal dense
+ // matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal transpose dense
+ // matrix-diagonal dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) += A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (small matrices)*********
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i,j+SIMDSIZE*3UL) );
+ SIMDType xmm5( (~C).load(i,j+SIMDSIZE*4UL) );
+ SIMDType xmm6( (~C).load(i,j+SIMDSIZE*5UL) );
+ SIMDType xmm7( (~C).load(i,j+SIMDSIZE*6UL) );
+ SIMDType xmm8( (~C).load(i,j+SIMDSIZE*7UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i, j+SIMDSIZE*4UL, xmm5 );
+ (~C).store( i, j+SIMDSIZE*5UL, xmm6 );
+ (~C).store( i, j+SIMDSIZE*6UL, xmm7 );
+ (~C).store( i, j+SIMDSIZE*7UL, xmm8 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i ,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i ,j+SIMDSIZE*3UL) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j+SIMDSIZE ) );
+ SIMDType xmm7( (~C).load(i+1UL,j+SIMDSIZE*2UL) );
+ SIMDType xmm8( (~C).load(i+1UL,j+SIMDSIZE*3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE , xmm2 );
+ (~C).store( i , j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i , j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j+SIMDSIZE , xmm6 );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, xmm7 );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, xmm8 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i,j+SIMDSIZE*3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j+SIMDSIZE) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j+SIMDSIZE) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j+SIMDSIZE, xmm4 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+1UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+1UL, j, xmm2 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1( (~C)(i ,j) );
+ ElementType value2( (~C)(i+1UL,j) );;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) = value1;
+ (~C)(i+1UL,j) = value2;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (small matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a column-major dense matrix. This kernel
+ // is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j) );
+ SIMDType xmm5( (~C).load(i+SIMDSIZE*4UL,j) );
+ SIMDType xmm6( (~C).load(i+SIMDSIZE*5UL,j) );
+ SIMDType xmm7( (~C).load(i+SIMDSIZE*6UL,j) );
+ SIMDType xmm8( (~C).load(i+SIMDSIZE*7UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ (~C).store( i+SIMDSIZE*4UL, j, xmm5 );
+ (~C).store( i+SIMDSIZE*5UL, j, xmm6 );
+ (~C).store( i+SIMDSIZE*6UL, j, xmm7 );
+ (~C).store( i+SIMDSIZE*7UL, j, xmm8 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j ) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j ) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i+SIMDSIZE ,j+1UL) );
+ SIMDType xmm7( (~C).load(i+SIMDSIZE*2UL,j+1UL) );
+ SIMDType xmm8( (~C).load(i+SIMDSIZE*3UL,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE , j , xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j , xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i+SIMDSIZE , j+1UL, xmm6 );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, xmm7 );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, xmm8 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i+SIMDSIZE, j+1UL, xmm4 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+1UL, xmm2 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1( (~C)(i,j ) );
+ ElementType value2( (~C)(i,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) = value1;
+ (~C)(i,j+1UL) = value2;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (large matrices)*********
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i ,j2) );
+ SIMDType xmm4( (~C).load(i ,j3) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j1) );
+ SIMDType xmm7( (~C).load(i+1UL,j2) );
+ SIMDType xmm8( (~C).load(i+1UL,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i , j2, xmm3 );
+ (~C).store( i , j3, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j1, xmm6 );
+ (~C).store( i+1UL, j2, xmm7 );
+ (~C).store( i+1UL, j3, xmm8 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+ SIMDType xmm3( (~C).load(i,j2) );
+ SIMDType xmm4( (~C).load(i,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ (~C).store( i, j2, xmm3 );
+ (~C).store( i, j3, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+ SIMDType xmm5( (~C).load(i+2UL,j ) );
+ SIMDType xmm6( (~C).load(i+2UL,j1) );
+ SIMDType xmm7( (~C).load(i+3UL,j ) );
+ SIMDType xmm8( (~C).load(i+3UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ (~C).store( i+2UL, j , xmm5 );
+ (~C).store( i+2UL, j1, xmm6 );
+ (~C).store( i+3UL, j , xmm7 );
+ (~C).store( i+3UL, j1, xmm8 );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (large matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a column-major dense matrix. This kernel
+ // is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i2,j ) );
+ SIMDType xmm4( (~C).load(i3,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i1,j+1UL) );
+ SIMDType xmm7( (~C).load(i2,j+1UL) );
+ SIMDType xmm8( (~C).load(i3,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i2, j , xmm3 );
+ (~C).store( i3, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i1, j+1UL, xmm6 );
+ (~C).store( i2, j+1UL, xmm7 );
+ (~C).store( i3, j+1UL, xmm8 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+ SIMDType xmm3( (~C).load(i2,j) );
+ SIMDType xmm4( (~C).load(i3,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ (~C).store( i2, j, xmm3 );
+ (~C).store( i3, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+ SIMDType xmm5( (~C).load(i ,j+2UL) );
+ SIMDType xmm6( (~C).load(i1,j+2UL) );
+ SIMDType xmm7( (~C).load(i ,j+3UL) );
+ SIMDType xmm8( (~C).load(i1,j+3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ (~C).store( i , j+2UL, xmm5 );
+ (~C).store( i1, j+2UL, xmm6 );
+ (~C).store( i , j+3UL, xmm7 );
+ (~C).store( i1, j+3UL, xmm8 );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices (default)**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense matrix-dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices********************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based addition assignment of a transpose dense matrix-dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ addAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ addAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TDMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a transpose dense matrix-
+ // dense matrix multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value && IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < TDMATDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( C, A, B );
+ else
+ selectBlasSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (general/general)****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general transpose dense matrix-general dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general transpose dense
+ // matrix-general dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ for( size_t k=kbegin; k<kend; ++k )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? k : k+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) -= A(i,k) * B(k,j );
+ (~C)(i,j+1UL) -= A(i,k) * B(k,j+1UL);
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) -= A(i,k) * B(k,jpos);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (general/general)*************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general transpose dense matrix-general dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general transpose dense
+ // matrix-general dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ for( size_t k=kbegin; k<kend; ++k )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? k : k+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) -= A(i ,k) * B(k,j);
+ (~C)(i+1UL,j) -= A(i+1UL,k) * B(k,j);
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) -= A(ipos,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (general/diagonal)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general transpose dense matrix-diagonal dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general transpose dense
+ // matrix-diagonal dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT4>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) -= A(i,j) * B(j,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (general/diagonal)************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general transpose dense matrix-diagonal dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general transpose dense
+ // matrix-diagonal dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) -= A(i ,j) * B(j,j);
+ (~C)(i+1UL,j) -= A(i+1UL,j) * B(j,j);
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) -= A(ipos,j) * B(j,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (diagonal/general)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal transpose dense matrix-general dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal transpose dense
+ // matrix-general dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) -= A(i,i) * B(i,j );
+ (~C)(i,j+1UL) -= A(i,i) * B(i,j+1UL);
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) -= A(i,i) * B(i,jpos);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (diagonal/general)************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal transpose dense matrix-general dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal transpose dense
+ // matrix-general dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyLower<MT5>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyUpper<MT5>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) -= A(i,i) * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/diagonal)************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal transpose dense matrix-diagonal dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal transpose dense
+ // matrix-diagonal dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) -= A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small transpose dense matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (small matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small transpose dense matrix-dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i,j+SIMDSIZE*3UL) );
+ SIMDType xmm5( (~C).load(i,j+SIMDSIZE*4UL) );
+ SIMDType xmm6( (~C).load(i,j+SIMDSIZE*5UL) );
+ SIMDType xmm7( (~C).load(i,j+SIMDSIZE*6UL) );
+ SIMDType xmm8( (~C).load(i,j+SIMDSIZE*7UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 - a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 - a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 - a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 - a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 - a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 - a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i, j+SIMDSIZE*4UL, xmm5 );
+ (~C).store( i, j+SIMDSIZE*5UL, xmm6 );
+ (~C).store( i, j+SIMDSIZE*6UL, xmm7 );
+ (~C).store( i, j+SIMDSIZE*7UL, xmm8 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i ,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i ,j+SIMDSIZE*3UL) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j+SIMDSIZE ) );
+ SIMDType xmm7( (~C).load(i+1UL,j+SIMDSIZE*2UL) );
+ SIMDType xmm8( (~C).load(i+1UL,j+SIMDSIZE*3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a1 * b3;
+ xmm4 = xmm4 - a1 * b4;
+ xmm5 = xmm5 - a2 * b1;
+ xmm6 = xmm6 - a2 * b2;
+ xmm7 = xmm7 - a2 * b3;
+ xmm8 = xmm8 - a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE , xmm2 );
+ (~C).store( i , j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i , j+SIMDSIZE*3UL, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j+SIMDSIZE , xmm6 );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, xmm7 );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, xmm8 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE ) );
+ SIMDType xmm3( (~C).load(i,j+SIMDSIZE*2UL) );
+ SIMDType xmm4( (~C).load(i,j+SIMDSIZE*3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 - a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 - a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE , xmm2 );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j+SIMDSIZE) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j+SIMDSIZE) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a2 * b1;
+ xmm4 = xmm4 - a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j+SIMDSIZE, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j+SIMDSIZE, xmm4 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+SIMDSIZE) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+SIMDSIZE, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+1UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 - set( A(i ,k) ) * b1;
+ xmm2 = xmm2 - set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+1UL, j, xmm2 );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 - set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1( (~C)(i ,j) );
+ ElementType value2( (~C)(i+1UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 -= A(i ,k) * B(k,j);
+ value2 -= A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) = value1;
+ (~C)(i+1UL,j) = value2;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value -= A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (small matrices)***
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small transpose dense matrix-dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j) );
+ SIMDType xmm5( (~C).load(i+SIMDSIZE*4UL,j) );
+ SIMDType xmm6( (~C).load(i+SIMDSIZE*5UL,j) );
+ SIMDType xmm7( (~C).load(i+SIMDSIZE*6UL,j) );
+ SIMDType xmm8( (~C).load(i+SIMDSIZE*7UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 - A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 - A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 - A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 - A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 - A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 - A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ (~C).store( i+SIMDSIZE*4UL, j, xmm5 );
+ (~C).store( i+SIMDSIZE*5UL, j, xmm6 );
+ (~C).store( i+SIMDSIZE*6UL, j, xmm7 );
+ (~C).store( i+SIMDSIZE*7UL, j, xmm8 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j ) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j ) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i+SIMDSIZE ,j+1UL) );
+ SIMDType xmm7( (~C).load(i+SIMDSIZE*2UL,j+1UL) );
+ SIMDType xmm8( (~C).load(i+SIMDSIZE*3UL,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a3 * b1;
+ xmm4 = xmm4 - a4 * b1;
+ xmm5 = xmm5 - a1 * b2;
+ xmm6 = xmm6 - a2 * b2;
+ xmm7 = xmm7 - a3 * b2;
+ xmm8 = xmm8 - a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE , j , xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j , xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i+SIMDSIZE , j+1UL, xmm6 );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, xmm7 );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, xmm8 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 - A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 - A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a1 * b2;
+ xmm4 = xmm4 - a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i+SIMDSIZE, j+1UL, xmm4 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 - a1 * set( B(k,j ) );
+ xmm2 = xmm2 - a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+1UL, xmm2 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 - A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1( (~C)(i,j ) );
+ ElementType value2( (~C)(i,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 -= A(i,k) * B(k,j );
+ value2 -= A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) = value1;
+ (~C)(i,j+1UL) = value2;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value -= A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose dense matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (large matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large transpose dense matrix-dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i ,j2) );
+ SIMDType xmm4( (~C).load(i ,j3) );
+ SIMDType xmm5( (~C).load(i+1UL,j ) );
+ SIMDType xmm6( (~C).load(i+1UL,j1) );
+ SIMDType xmm7( (~C).load(i+1UL,j2) );
+ SIMDType xmm8( (~C).load(i+1UL,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a1 * b3;
+ xmm4 = xmm4 - a1 * b4;
+ xmm5 = xmm5 - a2 * b1;
+ xmm6 = xmm6 - a2 * b2;
+ xmm7 = xmm7 - a2 * b3;
+ xmm8 = xmm8 - a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i , j2, xmm3 );
+ (~C).store( i , j3, xmm4 );
+ (~C).store( i+1UL, j , xmm5 );
+ (~C).store( i+1UL, j1, xmm6 );
+ (~C).store( i+1UL, j2, xmm7 );
+ (~C).store( i+1UL, j3, xmm8 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+ SIMDType xmm3( (~C).load(i,j2) );
+ SIMDType xmm4( (~C).load(i,j3) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j1);
+ xmm3 = xmm3 - a1 * B.load(k,j2);
+ xmm4 = xmm4 - a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ (~C).store( i, j2, xmm3 );
+ (~C).store( i, j3, xmm4 );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+ SIMDType xmm5( (~C).load(i+2UL,j ) );
+ SIMDType xmm6( (~C).load(i+2UL,j1) );
+ SIMDType xmm7( (~C).load(i+3UL,j ) );
+ SIMDType xmm8( (~C).load(i+3UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a2 * b1;
+ xmm4 = xmm4 - a2 * b2;
+ xmm5 = xmm5 - a3 * b1;
+ xmm6 = xmm6 - a3 * b2;
+ xmm7 = xmm7 - a4 * b1;
+ xmm8 = xmm8 - a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ (~C).store( i+2UL, j , xmm5 );
+ (~C).store( i+2UL, j1, xmm6 );
+ (~C).store( i+3UL, j , xmm7 );
+ (~C).store( i+3UL, j1, xmm8 );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i ,j1) );
+ SIMDType xmm3( (~C).load(i+1UL,j ) );
+ SIMDType xmm4( (~C).load(i+1UL,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a1 * b2;
+ xmm3 = xmm3 - a2 * b1;
+ xmm4 = xmm4 - a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i , j1, xmm2 );
+ (~C).store( i+1UL, j , xmm3 );
+ (~C).store( i+1UL, j1, xmm4 );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j1) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j );
+ xmm2 = xmm2 - a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j1, xmm2 );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 - a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value -= A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (large matrices)***
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large transpose dense matrix-dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i2,j ) );
+ SIMDType xmm4( (~C).load(i3,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i1,j+1UL) );
+ SIMDType xmm7( (~C).load(i2,j+1UL) );
+ SIMDType xmm8( (~C).load(i3,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a3 * b1;
+ xmm4 = xmm4 - a4 * b1;
+ xmm5 = xmm5 - a1 * b2;
+ xmm6 = xmm6 - a2 * b2;
+ xmm7 = xmm7 - a3 * b2;
+ xmm8 = xmm8 - a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i2, j , xmm3 );
+ (~C).store( i3, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i1, j+1UL, xmm6 );
+ (~C).store( i2, j+1UL, xmm7 );
+ (~C).store( i3, j+1UL, xmm8 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+ SIMDType xmm3( (~C).load(i2,j) );
+ SIMDType xmm4( (~C).load(i3,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i1,k) * b1;
+ xmm3 = xmm3 - A.load(i2,k) * b1;
+ xmm4 = xmm4 - A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ (~C).store( i2, j, xmm3 );
+ (~C).store( i3, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+ SIMDType xmm5( (~C).load(i ,j+2UL) );
+ SIMDType xmm6( (~C).load(i1,j+2UL) );
+ SIMDType xmm7( (~C).load(i ,j+3UL) );
+ SIMDType xmm8( (~C).load(i1,j+3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a1 * b2;
+ xmm4 = xmm4 - a2 * b2;
+ xmm5 = xmm5 - a1 * b3;
+ xmm6 = xmm6 - a2 * b3;
+ xmm7 = xmm7 - a1 * b4;
+ xmm8 = xmm8 - a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ (~C).store( i , j+2UL, xmm5 );
+ (~C).store( i1, j+2UL, xmm6 );
+ (~C).store( i , j+3UL, xmm7 );
+ (~C).store( i1, j+3UL, xmm8 );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a1 * b2;
+ xmm4 = xmm4 - a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value -= A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense matrices (default)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense matrix-dense matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // large transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subraction assignment to dense matrices******************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based subraction assignment of a transpose dense matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ subAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ subAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(-1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-dense matrix multiplication to a dense
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( rhs.lhs_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-dense matrix multiplication to a sparse
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-dense matrix multiplication expression to a sparse matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TDMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense matrix-dense matrix multiplication
+ // to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TDMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSCALARMULTEXPR SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Expression object for scaled transpose dense matrix-dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// This specialization of the DMatScalarMultExpr class represents the compile time expression
+// for scaled multiplications between a column-major dense matrix and a row-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar value
+class DMatScalarMultExpr< TDMatDMatMultExpr<MT1,MT2>, ST, true >
+ : public DenseMatrix< DMatScalarMultExpr< TDMatDMatMultExpr<MT1,MT2>, ST, true >, true >
+ , private MatScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef TDMatDMatMultExpr<MT1,MT2> MMM; //!< Type of the dense matrix multiplication expression.
+ typedef ResultType_<MMM> RES; //!< Result type of the dense matrix multiplication expression.
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the types of all three involved matrices and the scalar type are suited for a BLAS
+ kernel, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ !( IsBuiltin< ElementType_<T1> >::value && IsComplex<T4>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all four involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !( IsDiagonal<T2>::value && IsDiagonal<T3>::value ) &&
+ !( IsDiagonal<T2>::value && IsColumnMajorMatrix<T1>::value ) &&
+ !( IsDiagonal<T3>::value && IsRowMajorMatrix<T1>::value ) &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3>
+ , T4 >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatScalarMultExpr<MMM,ST,true> This; //!< Type of this DMatScalarMultExpr instance.
+ typedef MultTrait_<RES,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef const TDMatDMatMultExpr<MT1,MT2> LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !( IsDiagonal<MT1>::value && IsDiagonal<MT2>::value ) &&
+ MT1::simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable<ET1,ET2,ST>::value &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatScalarMultExpr class.
+ //
+ // \param matrix The left-hand side dense matrix of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DMatScalarMultExpr( const MMM& matrix, ST scalar )
+ : matrix_( matrix ) // Left-hand side dense matrix of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ResultType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ return matrix_(i,j) * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= matrix_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= matrix_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const {
+ return matrix_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const {
+ return matrix_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return matrix_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const {
+ return matrix_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return matrix_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const {
+ return matrix_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const {
+ RightOperand_<MMM> B( matrix_.rightOperand() );
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( rows() * columns() < TDMATDMATMULT_THRESHOLD ) ) &&
+ ( B.columns() > SMP_TDMATDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand matrix_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*!\brief Assignment of a scaled transpose dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*!\brief Selection of the kernel for an assignment of a scaled transpose dense matrix-dense
+ // matrix multiplication to a dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value && IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < TDMATDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( C, A, B, scalar );
+ else
+ selectBlasAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (general/general)****************************
+ /*!\brief Default assignment of a scaled general transpose dense matrix-general dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general transpose dense matrix-
+ // general dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ if( IsStrictlyTriangular<MT4>::value && kbegin == kend ) {
+ for( size_t j=0UL; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ continue;
+ }
+
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? kbegin+1UL : kbegin )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? kbegin : kbegin+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT4>::value && IsUpper<MT5>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ else if( IsStrictlyUpper<MT5>::value ) {
+ reset( (~C)(i,0UL) );
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) = A(i,kbegin) * B(kbegin,j);
+ }
+ if( IsLower<MT4>::value && IsLower<MT5>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ else if( IsStrictlyLower<MT5>::value ) {
+ reset( (~C)(i,N-1UL) );
+ }
+ }
+
+ for( size_t k=kbegin+1UL; k<kend; ++k )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? k-1UL : k )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ if( IsLower<MT5>::value ) {
+ (~C)(i,jend) = A(i,k) * B(k,jend);
+ }
+ }
+
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT4>::value || IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT4>::value || IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) *= scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (general/general)*************************
+ /*!\brief Default assignment of a scaled general transpose dense matrix-general dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general transpose dense matrix-
+ // general dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ if( IsStrictlyTriangular<MT5>::value && kbegin == kend ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ continue;
+ }
+
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? kbegin+1UL : kbegin )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? kbegin : kbegin+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value && IsLower<MT5>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ else if( IsStrictlyLower<MT4>::value ) {
+ reset( (~C)(0UL,j) );
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) = A(i,kbegin) * B(kbegin,j);
+ }
+ if( IsUpper<MT4>::value && IsUpper<MT5>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ else if( IsStrictlyUpper<MT4>::value ) {
+ reset( (~C)(M-1UL,j) );
+ }
+ }
+
+ for( size_t k=kbegin+1UL; k<kend; ++k )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? k-1UL : k )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) += A(i,k) * B(k,j);
+ }
+ if( IsUpper<MT4>::value ) {
+ (~C)(iend,j) = A(iend,k) * B(k,j);
+ }
+ }
+
+ {
+ const size_t ibegin( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT4>::value || IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT4>::value || IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) *= scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (general/diagonal)***************************
+ /*!\brief Default assignment of a scaled general transpose dense matrix-diagonal dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general transpose dense matrix-
+ // diagonal dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT4>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ if( IsUpper<MT4>::value ) {
+ for( size_t j=jj; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) = A(i,j) * B(j,j) * scalar;
+ }
+ if( IsLower<MT4>::value ) {
+ for( size_t j=jpos; j<jend; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (general/diagonal)************************
+ /*!\brief Default assignment of a scaled general transpose dense matrix-diagonal dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general transpose dense matrix-
+ // diagonal dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ (~C)(i,j) = A(i,j) * B(j,j) * scalar;
+ }
+ if( IsUpper<MT4>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to row-major dense matrices (diagonal/general)***************************
+ /*!\brief Default assignment of a scaled diagonal transpose dense matrix-general dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal transpose dense matrix-
+ // general dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ if( IsUpper<MT5>::value ) {
+ for( size_t j=0UL; j<jbegin; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t j=jbegin; j<jend; ++j ) {
+ (~C)(i,j) = A(i,i) * B(i,j) * scalar;
+ }
+ if( IsLower<MT5>::value ) {
+ for( size_t j=jend; j<N; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to column-major dense matrices (diagonal/general)************************
+ /*!\brief Default assignment of a scaled diagonal transpose dense matrix-general dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal transpose dense matrix-
+ // general dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyLower<MT5>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyUpper<MT5>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ if( IsLower<MT5>::value ) {
+ for( size_t i=ii; i<ibegin; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) = A(i,i) * B(i,j) * scalar;
+ }
+ if( IsUpper<MT5>::value ) {
+ for( size_t i=ipos; i<iend; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/diagonal)************************************
+ /*!\brief Default assignment of a scaled diagonal transpose dense matrix-diagonal dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal transpose dense matrix-
+ // diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) = A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*!\brief Default assignment of a small scaled transpose dense matrix-dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (small matrices)******************
+ /*!\brief Vectorized default assignment of a small scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 * factor );
+ (~C).store( i, j+SIMDSIZE*4UL, xmm5 * factor );
+ (~C).store( i, j+SIMDSIZE*5UL, xmm6 * factor );
+ (~C).store( i, j+SIMDSIZE*6UL, xmm7 * factor );
+ (~C).store( i, j+SIMDSIZE*7UL, xmm8 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE , xmm2 * factor );
+ (~C).store( i , j+SIMDSIZE*2UL, xmm3 * factor );
+ (~C).store( i , j+SIMDSIZE*3UL, xmm4 * factor );
+ (~C).store( i+1UL, j , xmm5 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE , xmm6 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, xmm7 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, xmm8 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE, xmm2 * factor );
+ (~C).store( i+1UL, j , xmm3 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE, xmm4 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE, xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, xmm1 * factor );
+ (~C).store( i+1UL, j, xmm2 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) = value1 * scalar;
+ (~C)(i+1UL,j) = value2 * scalar;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (small matrices)***************
+ /*!\brief Vectorized default assignment of a small scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication expression to a column-major dense matrix. This kernel
+ // is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 * factor );
+ (~C).store( i+SIMDSIZE*4UL, j, xmm5 * factor );
+ (~C).store( i+SIMDSIZE*5UL, j, xmm6 * factor );
+ (~C).store( i+SIMDSIZE*6UL, j, xmm7 * factor );
+ (~C).store( i+SIMDSIZE*7UL, j, xmm8 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j , xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j , xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j , xmm4 * factor );
+ (~C).store( i , j+1UL, xmm5 * factor );
+ (~C).store( i+SIMDSIZE , j+1UL, xmm6 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, xmm7 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, xmm8 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j , xmm2 * factor );
+ (~C).store( i , j+1UL, xmm3 * factor );
+ (~C).store( i+SIMDSIZE, j+1UL, xmm4 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j, xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , xmm1 * factor );
+ (~C).store( i, j+1UL, xmm2 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) = value1 * scalar;
+ (~C)(i,j+1UL) = value2 * scalar;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*!\brief Default assignment of a large scaled transpose dense matrix-dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (large matrices)******************
+ /*!\brief Vectorized default assignment of a large scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ reset( (~C)(i,j) );
+ }
+ }
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i , j2, (~C).load(i ,j2) + xmm3 * factor );
+ (~C).store( i , j3, (~C).load(i ,j3) + xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm5 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm6 * factor );
+ (~C).store( i+1UL, j2, (~C).load(i+1UL,j2) + xmm7 * factor );
+ (~C).store( i+1UL, j3, (~C).load(i+1UL,j3) + xmm8 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) + xmm2 * factor );
+ (~C).store( i, j2, (~C).load(i,j2) + xmm3 * factor );
+ (~C).store( i, j3, (~C).load(i,j3) + xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm4 * factor );
+ (~C).store( i+2UL, j , (~C).load(i+2UL,j ) + xmm5 * factor );
+ (~C).store( i+2UL, j1, (~C).load(i+2UL,j1) + xmm6 * factor );
+ (~C).store( i+3UL, j , (~C).load(i+3UL,j ) + xmm7 * factor );
+ (~C).store( i+3UL, j1, (~C).load(i+3UL,j1) + xmm8 * factor );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm4 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) + xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (large matrices)***************
+ /*!\brief Vectorized default assignment of a large scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication expression to a column-major dense matrix. This kernel
+ // is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i2, j , (~C).load(i2,j ) + xmm3 * factor );
+ (~C).store( i3, j , (~C).load(i3,j ) + xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm5 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm6 * factor );
+ (~C).store( i2, j+1UL, (~C).load(i2,j+1UL) + xmm7 * factor );
+ (~C).store( i3, j+1UL, (~C).load(i3,j+1UL) + xmm8 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) + xmm2 * factor );
+ (~C).store( i2, j, (~C).load(i2,j) + xmm3 * factor );
+ (~C).store( i3, j, (~C).load(i3,j) + xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm4 * factor );
+ (~C).store( i , j+2UL, (~C).load(i ,j+2UL) + xmm5 * factor );
+ (~C).store( i1, j+2UL, (~C).load(i1,j+2UL) + xmm6 * factor );
+ (~C).store( i , j+3UL, (~C).load(i ,j+3UL) + xmm7 * factor );
+ (~C).store( i1, j+3UL, (~C).load(i1,j+3UL) + xmm8 * factor );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm4 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) + xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices (default)*******************************************
+ /*!\brief Default assignment of a scaled transpose dense matrix-dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large scaled
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices*****************************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based assignment of a scaled transpose dense matrix-dense matrix multiplication
+ // (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ assign( C, B );
+ trmm( C, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ assign( C, A );
+ trmm( C, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ }
+ else {
+ gemm( C, A, B, ET(scalar), ET(0) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*!\brief Assignment of a scaled transpose dense matrix-dense matrix multiplication to a sparse
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*!\brief Addition assignment of a scaled transpose dense matrix-dense matrix multiplication
+ // to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectAddAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*!\brief Selection of the kernel for an addition assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value && IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < TDMATDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( C, A, B, scalar );
+ else
+ selectBlasAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/general)*****************************
+ /*!\brief Default addition assignment of a scaled general transpose dense matrix-general dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general transpose dense
+ // matrix-general dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const ResultType tmp( serial( A * B * scalar ) );
+ addAssign( C, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (general/diagonal)******************
+ /*!\brief Default addition assignment of a scaled general transpose dense matrix-diagonal dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general transpose dense
+ // matrix-diagonal dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT4>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) += A(i,j) * B(j,j) * scalar;
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (general/diagonal)***************
+ /*!\brief Default addition assignment of a scaled general transpose dense matrix-diagonal dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general transpose dense
+ // matrix-diagonal dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) += A(i ,j) * B(j,j) * scalar;
+ (~C)(i+1UL,j) += A(i+1UL,j) * B(j,j) * scalar;
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) += A(ipos,j) * B(j,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to row-major dense matrices (diagonal/general)******************
+ /*!\brief Default addition assignment of a scaled diagonal transpose dense matrix-general dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal transpose
+ // dense matrix-general dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) += A(i,i) * B(i,j ) * scalar;
+ (~C)(i,j+1UL) += A(i,i) * B(i,j+1UL) * scalar;
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) += A(i,i) * B(i,jpos) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to column-major dense matrices (diagonal/general)***************
+ /*!\brief Default addition assignment of a scaled diagonal transpose dense matrix-general dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal transpose
+ // dense matrix-general dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyLower<MT5>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyUpper<MT5>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) += A(i,i) * B(i,j) * scalar;
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/diagonal)***************************
+ /*!\brief Default addition assignment of a scaled diagonal transpose dense matrix-diagonal
+ // dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal transpose
+ // dense matrix-diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) += A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*!\brief Default addition assignment of a small scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (small matrices)*********
+ /*!\brief Vectorized default addition assignment of a small scaled transpose dense matrix-dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , (~C).load(i,j+SIMDSIZE ) + xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, (~C).load(i,j+SIMDSIZE*2UL) + xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, (~C).load(i,j+SIMDSIZE*3UL) + xmm4 * factor );
+ (~C).store( i, j+SIMDSIZE*4UL, (~C).load(i,j+SIMDSIZE*4UL) + xmm5 * factor );
+ (~C).store( i, j+SIMDSIZE*5UL, (~C).load(i,j+SIMDSIZE*5UL) + xmm6 * factor );
+ (~C).store( i, j+SIMDSIZE*6UL, (~C).load(i,j+SIMDSIZE*6UL) + xmm7 * factor );
+ (~C).store( i, j+SIMDSIZE*7UL, (~C).load(i,j+SIMDSIZE*7UL) + xmm8 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE , (~C).load(i ,j+SIMDSIZE ) + xmm2 * factor );
+ (~C).store( i , j+SIMDSIZE*2UL, (~C).load(i ,j+SIMDSIZE*2UL) + xmm3 * factor );
+ (~C).store( i , j+SIMDSIZE*3UL, (~C).load(i ,j+SIMDSIZE*3UL) + xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm5 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE , (~C).load(i+1UL,j+SIMDSIZE ) + xmm6 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, (~C).load(i+1UL,j+SIMDSIZE*2UL) + xmm7 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, (~C).load(i+1UL,j+SIMDSIZE*3UL) + xmm8 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , (~C).load(i,j+SIMDSIZE ) + xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, (~C).load(i,j+SIMDSIZE*2UL) + xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, (~C).load(i,j+SIMDSIZE*3UL) + xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE, (~C).load(i ,j+SIMDSIZE) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE, (~C).load(i+1UL,j+SIMDSIZE) + xmm4 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE, (~C).load(i,j+SIMDSIZE) + xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i+1UL, j, (~C).load(i+1UL,j) + xmm2 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) += value1 * scalar;
+ (~C)(i+1UL,j) += value2 * scalar;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (small matrices)******
+ /*!\brief Vectorized default addition assignment of a small scaled transpose dense matrix-dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, (~C).load(i+SIMDSIZE ,j) + xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, (~C).load(i+SIMDSIZE*2UL,j) + xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, (~C).load(i+SIMDSIZE*3UL,j) + xmm4 * factor );
+ (~C).store( i+SIMDSIZE*4UL, j, (~C).load(i+SIMDSIZE*4UL,j) + xmm5 * factor );
+ (~C).store( i+SIMDSIZE*5UL, j, (~C).load(i+SIMDSIZE*5UL,j) + xmm6 * factor );
+ (~C).store( i+SIMDSIZE*6UL, j, (~C).load(i+SIMDSIZE*6UL,j) + xmm7 * factor );
+ (~C).store( i+SIMDSIZE*7UL, j, (~C).load(i+SIMDSIZE*7UL,j) + xmm8 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j , (~C).load(i+SIMDSIZE ,j ) + xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j , (~C).load(i+SIMDSIZE*2UL,j ) + xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j , (~C).load(i+SIMDSIZE*3UL,j ) + xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm5 * factor );
+ (~C).store( i+SIMDSIZE , j+1UL, (~C).load(i+SIMDSIZE ,j+1UL) + xmm6 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, (~C).load(i+SIMDSIZE*2UL,j+1UL) + xmm7 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, (~C).load(i+SIMDSIZE*3UL,j+1UL) + xmm8 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, (~C).load(i+SIMDSIZE ,j) + xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, (~C).load(i+SIMDSIZE*2UL,j) + xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, (~C).load(i+SIMDSIZE*3UL,j) + xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j , (~C).load(i+SIMDSIZE,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i+SIMDSIZE, j+1UL, (~C).load(i+SIMDSIZE,j+1UL) + xmm4 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j, (~C).load(i+SIMDSIZE,j) + xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j+1UL, (~C).load(i,j+1UL) + xmm2 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) += value1 * scalar;
+ (~C)(i,j+1UL) += value2 * scalar;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*!\brief Default addition assignment of a large scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (large matrices)*********
+ /*!\brief Vectorized default addition assignment of a large scaled transpose dense matrix-dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i , j2, (~C).load(i ,j2) + xmm3 * factor );
+ (~C).store( i , j3, (~C).load(i ,j3) + xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm5 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm6 * factor );
+ (~C).store( i+1UL, j2, (~C).load(i+1UL,j2) + xmm7 * factor );
+ (~C).store( i+1UL, j3, (~C).load(i+1UL,j3) + xmm8 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) + xmm2 * factor );
+ (~C).store( i, j2, (~C).load(i,j2) + xmm3 * factor );
+ (~C).store( i, j3, (~C).load(i,j3) + xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm4 * factor );
+ (~C).store( i+2UL, j , (~C).load(i+2UL,j ) + xmm5 * factor );
+ (~C).store( i+2UL, j1, (~C).load(i+2UL,j1) + xmm6 * factor );
+ (~C).store( i+3UL, j , (~C).load(i+3UL,j ) + xmm7 * factor );
+ (~C).store( i+3UL, j1, (~C).load(i+3UL,j1) + xmm8 * factor );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) + xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) + xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) + xmm4 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) + xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (large matrices)******
+ /*!\brief Vectorized default addition assignment of a large scaled transpose dense matrix-dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i2, j , (~C).load(i2,j ) + xmm3 * factor );
+ (~C).store( i3, j , (~C).load(i3,j ) + xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm5 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm6 * factor );
+ (~C).store( i2, j+1UL, (~C).load(i2,j+1UL) + xmm7 * factor );
+ (~C).store( i3, j+1UL, (~C).load(i3,j+1UL) + xmm8 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) + xmm2 * factor );
+ (~C).store( i2, j, (~C).load(i2,j) + xmm3 * factor );
+ (~C).store( i3, j, (~C).load(i3,j) + xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm4 * factor );
+ (~C).store( i , j+2UL, (~C).load(i ,j+2UL) + xmm5 * factor );
+ (~C).store( i1, j+2UL, (~C).load(i1,j+2UL) + xmm6 * factor );
+ (~C).store( i , j+3UL, (~C).load(i ,j+3UL) + xmm7 * factor );
+ (~C).store( i1, j+3UL, (~C).load(i1,j+3UL) + xmm8 * factor );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm4 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) + xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices (default)**********************************
+ /*!\brief Default addition assignment of a scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // scaled transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices********************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based addition assignment of a scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ addAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ addAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*!\brief Subtraction assignment of a scaled transpose dense matrix-dense matrix multiplication
+ // to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectSubAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*!\brief Selection of the kernel for a subtraction assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value && IsDiagonal<MT5>::value ) ||
+ ( C.rows() * C.columns() < TDMATDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( C, A, B, scalar );
+ else
+ selectBlasSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const ResultType tmp( serial( A * B * scalar ) );
+ subAssign( C, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (general/diagonal)***************
+ /*!\brief Default subtraction assignment of a scaled general transpose dense matrix-diagonal
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general transpose
+ // dense matrix-diagonal dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT4>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), jj ) )
+ :( jj ) );
+ const size_t jpos( ( IsLower<MT4>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), jend ) )
+ :( jend ) );
+
+ for( size_t j=jbegin; j<jpos; ++j ) {
+ (~C)(i,j) -= A(i,j) * B(j,j) * scalar;
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (general/diagonal)************
+ /*!\brief Default subtraction assignment of a scaled general transpose dense matrix-diagonal
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general transpose
+ // dense matrix-diagonal dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ (~C)(i ,j) -= A(i ,j) * B(j,j) * scalar;
+ (~C)(i+1UL,j) -= A(i+1UL,j) * B(j,j) * scalar;
+ }
+ if( ipos < iend ) {
+ (~C)(ipos,j) -= A(ipos,j) * B(j,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to row-major dense matrices (diagonal/general)***************
+ /*!\brief Default subtraction assignment of a scaled diagonal transpose dense matrix-general
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal transpose
+ // dense matrix-general dense matrix multiplication expression to a row-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ (~C)(i,j ) -= A(i,i) * B(i,j ) * scalar;
+ (~C)(i,j+1UL) -= A(i,i) * B(i,j+1UL) * scalar;
+ }
+ if( jpos < jend ) {
+ (~C)(i,jpos) -= A(i,i) * B(i,jpos) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to column-major dense matrices (diagonal/general)************
+ /*!\brief Default subtraction assignment of a scaled diagonal transpose dense matrix-general
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal transpose
+ // dense matrix-general dense matrix multiplication expression to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<N; jj+=block ) {
+ const size_t jend( min( N, jj+block ) );
+ for( size_t ii=0UL; ii<M; ii+=block ) {
+ const size_t iend( min( M, ii+block ) );
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyLower<MT5>::value ? j+1UL : j ), ii ) )
+ :( ii ) );
+ const size_t ipos( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyUpper<MT5>::value ? j : j+1UL ), iend ) )
+ :( iend ) );
+
+ for( size_t i=ibegin; i<ipos; ++i ) {
+ (~C)(i,j) -= A(i,i) * B(i,j) * scalar;
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/diagonal)************************
+ /*!\brief Default subtraction assignment of a scaled diagonal transpose dense matrix-diagonal
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal transpose
+ // dense matrix-diagonal dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) -= A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*!\brief Default subtraction assignment of a small scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (small matrices)******
+ /*!\brief Vectorized default subtraction assignment of a small scaled transpose dense matrix-
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL ) {
+ for( size_t i=0UL; i<M; ++i )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i : i+1UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + a1 * B.load(k,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + a1 * B.load(k,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + a1 * B.load(k,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + a1 * B.load(k,j+SIMDSIZE*7UL);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , (~C).load(i,j+SIMDSIZE ) - xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, (~C).load(i,j+SIMDSIZE*2UL) - xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, (~C).load(i,j+SIMDSIZE*3UL) - xmm4 * factor );
+ (~C).store( i, j+SIMDSIZE*4UL, (~C).load(i,j+SIMDSIZE*4UL) - xmm5 * factor );
+ (~C).store( i, j+SIMDSIZE*5UL, (~C).load(i,j+SIMDSIZE*5UL) - xmm6 * factor );
+ (~C).store( i, j+SIMDSIZE*6UL, (~C).load(i,j+SIMDSIZE*6UL) - xmm7 * factor );
+ (~C).store( i, j+SIMDSIZE*7UL, (~C).load(i,j+SIMDSIZE*7UL) - xmm8 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE ) );
+ const SIMDType b3( B.load(k,j+SIMDSIZE*2UL) );
+ const SIMDType b4( B.load(k,j+SIMDSIZE*3UL) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE , (~C).load(i ,j+SIMDSIZE ) - xmm2 * factor );
+ (~C).store( i , j+SIMDSIZE*2UL, (~C).load(i ,j+SIMDSIZE*2UL) - xmm3 * factor );
+ (~C).store( i , j+SIMDSIZE*3UL, (~C).load(i ,j+SIMDSIZE*3UL) - xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm5 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE , (~C).load(i+1UL,j+SIMDSIZE ) - xmm6 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*2UL, (~C).load(i+1UL,j+SIMDSIZE*2UL) - xmm7 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE*3UL, (~C).load(i+1UL,j+SIMDSIZE*3UL) - xmm8 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE );
+ xmm3 = xmm3 + a1 * B.load(k,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + a1 * B.load(k,j+SIMDSIZE*3UL);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE , (~C).load(i,j+SIMDSIZE ) - xmm2 * factor );
+ (~C).store( i, j+SIMDSIZE*2UL, (~C).load(i,j+SIMDSIZE*2UL) - xmm3 * factor );
+ (~C).store( i, j+SIMDSIZE*3UL, (~C).load(i,j+SIMDSIZE*3UL) - xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( ( IsUpper<MT5>::value )
+ ?( min( ( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) )
+ :( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL ) )
+ :( IsUpper<MT5>::value ? min( j+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j+SIMDSIZE) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j+SIMDSIZE, (~C).load(i ,j+SIMDSIZE) - xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm3 * factor );
+ (~C).store( i+1UL, j+SIMDSIZE, (~C).load(i+1UL,j+SIMDSIZE) - xmm4 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j+SIMDSIZE);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j+SIMDSIZE, (~C).load(i,j+SIMDSIZE) - xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( B.load(k,j) );
+ xmm1 = xmm1 + set( A(i ,k) ) * b1;
+ xmm2 = xmm2 + set( A(i+1UL,k) ) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i+1UL, j, (~C).load(i+1UL,j) - xmm2 * factor );
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + set( A(i,k) ) * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) - xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ size_t i( 0UL );
+
+ for( ; (i+2UL) <= M; i+=2UL )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? i+1UL : i+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i ,k) * B(k,j);
+ value2 += A(i+1UL,k) * B(k,j);
+ }
+
+ (~C)(i ,j) -= value1 * scalar;
+ (~C)(i+1UL,j) -= value2 * scalar;
+ }
+
+ if( i < M )
+ {
+ const size_t kbegin( ( IsUpper<MT4>::value )
+ ?( ( IsLower<MT5>::value )
+ ?( max( ( IsStrictlyUpper<MT4>::value ? i+1UL : i ), j ) )
+ :( IsStrictlyUpper<MT4>::value ? i+1UL : i ) )
+ :( IsLower<MT5>::value ? j : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) -= value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (small matrices)***
+ /*!\brief Vectorized default subtraction assignment of a small scaled transpose dense matrix-
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, (~C).load(i+SIMDSIZE ,j) - xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, (~C).load(i+SIMDSIZE*2UL,j) - xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, (~C).load(i+SIMDSIZE*3UL,j) - xmm4 * factor );
+ (~C).store( i+SIMDSIZE*4UL, j, (~C).load(i+SIMDSIZE*4UL,j) - xmm5 * factor );
+ (~C).store( i+SIMDSIZE*5UL, j, (~C).load(i+SIMDSIZE*5UL,j) - xmm6 * factor );
+ (~C).store( i+SIMDSIZE*6UL, j, (~C).load(i+SIMDSIZE*6UL,j) - xmm7 * factor );
+ (~C).store( i+SIMDSIZE*7UL, j, (~C).load(i+SIMDSIZE*7UL,j) - xmm8 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j , (~C).load(i+SIMDSIZE ,j ) - xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j , (~C).load(i+SIMDSIZE*2UL,j ) - xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j , (~C).load(i+SIMDSIZE*3UL,j ) - xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm5 * factor );
+ (~C).store( i+SIMDSIZE , j+1UL, (~C).load(i+SIMDSIZE ,j+1UL) - xmm6 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, (~C).load(i+SIMDSIZE*2UL,j+1UL) - xmm7 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, (~C).load(i+SIMDSIZE*3UL,j+1UL) - xmm8 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, (~C).load(i+SIMDSIZE ,j) - xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, (~C).load(i+SIMDSIZE*2UL,j) - xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, (~C).load(i+SIMDSIZE*3UL,j) - xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j , (~C).load(i+SIMDSIZE,j ) - xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm3 * factor );
+ (~C).store( i+SIMDSIZE, j+1UL, (~C).load(i+SIMDSIZE,j+1UL) - xmm4 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j, (~C).load(i+SIMDSIZE,j) - xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j+1UL, (~C).load(i,j+1UL) - xmm2 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, (~C).load(i,j) - xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) -= value1 * scalar;
+ (~C)(i,j+1UL) -= value2 * scalar;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) -= value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*!\brief Default subtraction assignment of a large scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (large matrices)******
+ /*!\brief Vectorized default subtraction assignment of a large scaled transpose dense matrix-
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t jj=0UL; jj<N; jj+=DMATDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+DMATDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t ii=0UL; ii<M; ii+=DMATDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+DMATDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ for( size_t kk=0UL; kk<K; kk+=DMATDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+DMATDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t j( jj );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+ const size_t j2( j+SIMDSIZE*2UL );
+ const size_t j3( j+SIMDSIZE*3UL );
+
+ size_t i( ii );
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ const SIMDType b3( B.load(k,j2) );
+ const SIMDType b4( B.load(k,j3) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a1 * b3;
+ xmm4 = xmm4 + a1 * b4;
+ xmm5 = xmm5 + a2 * b1;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a2 * b3;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) - xmm2 * factor );
+ (~C).store( i , j2, (~C).load(i ,j2) - xmm3 * factor );
+ (~C).store( i , j3, (~C).load(i ,j3) - xmm4 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm5 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) - xmm6 * factor );
+ (~C).store( i+1UL, j2, (~C).load(i+1UL,j2) - xmm7 * factor );
+ (~C).store( i+1UL, j3, (~C).load(i+1UL,j3) - xmm8 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ xmm3 = xmm3 + a1 * B.load(k,j2);
+ xmm4 = xmm4 + a1 * B.load(k,j3);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) - xmm2 * factor );
+ (~C).store( i, j2, (~C).load(i,j2) - xmm3 * factor );
+ (~C).store( i, j3, (~C).load(i,j3) - xmm4 * factor );
+ }
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t j1( j+SIMDSIZE );
+
+ size_t i( ii );
+
+ for( ; (i+4UL) <= iend; i+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+4UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType a3( set( A(i+2UL,k) ) );
+ const SIMDType a4( set( A(i+3UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a3 * b1;
+ xmm6 = xmm6 + a3 * b2;
+ xmm7 = xmm7 + a4 * b1;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) - xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) - xmm4 * factor );
+ (~C).store( i+2UL, j , (~C).load(i+2UL,j ) - xmm5 * factor );
+ (~C).store( i+2UL, j1, (~C).load(i+2UL,j1) - xmm6 * factor );
+ (~C).store( i+3UL, j , (~C).load(i+3UL,j ) - xmm7 * factor );
+ (~C).store( i+3UL, j1, (~C).load(i+3UL,j1) - xmm8 * factor );
+ }
+
+ for( ; (i+2UL) <= iend; i+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+2UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i ,k) ) );
+ const SIMDType a2( set( A(i+1UL,k) ) );
+ const SIMDType b1( B.load(k,j ) );
+ const SIMDType b2( B.load(k,j1) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a1 * b2;
+ xmm3 = xmm3 + a2 * b1;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i , j1, (~C).load(i ,j1) - xmm2 * factor );
+ (~C).store( i+1UL, j , (~C).load(i+1UL,j ) - xmm3 * factor );
+ (~C).store( i+1UL, j1, (~C).load(i+1UL,j1) - xmm4 * factor );
+ }
+
+ if( i < iend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j );
+ xmm2 = xmm2 + a1 * B.load(k,j1);
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j1, (~C).load(i,j1) - xmm2 * factor );
+ }
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( set( A(i,k) ) );
+ xmm1 = xmm1 + a1 * B.load(k,j);
+ }
+
+ (~C).store( i, j, (~C).load(i,j) - xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ for( size_t i=ii; i<iend; ++i )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( i+1UL ):( ktmp ),
+ ( IsUpper<MT5>::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) -= value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (large matrices)***
+ /*!\brief Vectorized default subtraction assignment of a large scaled transpose dense matrix-
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE, N ) );
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) - xmm2 * factor );
+ (~C).store( i2, j , (~C).load(i2,j ) - xmm3 * factor );
+ (~C).store( i3, j , (~C).load(i3,j ) - xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm5 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) - xmm6 * factor );
+ (~C).store( i2, j+1UL, (~C).load(i2,j+1UL) - xmm7 * factor );
+ (~C).store( i3, j+1UL, (~C).load(i3,j+1UL) - xmm8 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) - xmm2 * factor );
+ (~C).store( i2, j, (~C).load(i2,j) - xmm3 * factor );
+ (~C).store( i3, j, (~C).load(i3,j) - xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) - xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) - xmm4 * factor );
+ (~C).store( i , j+2UL, (~C).load(i ,j+2UL) - xmm5 * factor );
+ (~C).store( i1, j+2UL, (~C).load(i1,j+2UL) - xmm6 * factor );
+ (~C).store( i , j+3UL, (~C).load(i ,j+3UL) - xmm7 * factor );
+ (~C).store( i1, j+3UL, (~C).load(i1,j+3UL) - xmm8 * factor );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) - xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) - xmm4 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) - xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, (~C).load(i,j) - xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) -= value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense matrices (default)*******************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // scaled transpose dense matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subraction assignment to dense matrices******************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based subraction assignment of a scaled transpose dense matrix-dense matrix
+ // multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ subAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ subAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(-scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*!\brief SMP assignment of a scaled transpose dense matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*!\brief SMP assignment of a scaled transpose dense matrix-dense matrix multiplication to a
+ // sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // matrix-dense matrix multiplication expression to a sparse matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*!\brief SMP addition assignment of a scaled transpose dense matrix-dense matrix multiplication
+ // to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a scaled
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*!\brief SMP subtraction assignment of a scaled transpose dense matrix-dense matrix
+ // multiplication to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a scaled
+ // transpose dense matrix-dense matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MMM );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MMM );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major dense matrix and a
+// row-major dense matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side matrix for the multiplication.
+// \param rhs The right-hand side matrix for the multiplication.
+// \return The resulting matrix.
+//
+// This operator represents the multiplication of a column-major dense matrix and a row-major
+// dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,columnMajor> A, C;
+ blaze::DynamicMatrix<double,rowMajor> B;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current number of columns of \a lhs and the current number of rows of \a rhs
+// don't match, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const TDMatDMatMultExpr<T1,T2>
+ operator*( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TDMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TDMatDMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TDMatDMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< TDMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsAligned<MT1>, IsAligned<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TDMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TDMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TDMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TDMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TDMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TDMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatDVecMultExprTrait< TDMatDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TDMatDVecMultExprTrait_< MT1, DMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatSVecMultExprTrait< TDMatDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TDMatDVecMultExprTrait_< MT1, DMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecTDMatMultExprTrait< VT, TDMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecDMatMultExprTrait_< TDVecTDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecTDMatMultExprTrait< VT, TDMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecDMatMultExprTrait_< TSVecTDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TDMatDMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TDMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TDMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDMatDVecMultExpr.h b/src/cpu/blaze/math/expressions/TDMatDVecMultExpr.h
new file mode 100644
index 00000000..94103d02
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDMatDVecMultExpr.h
@@ -0,0 +1,4829 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDMatDVecMultExpr.h
+// \brief Header file for the transpose dense matrix/dense vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDMATDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDMATDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/gemv.h>
+#include <blaze/math/blas/trmv.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/math/expressions/VecScalarMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDMATDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense matrix-dense vector multiplications.
+// \ingroup dense_vector_expression
+//
+// The TDMatDVecMultExpr class represents the compile time expression for multiplications
+// between column-major dense matrices and dense vectors.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename VT > // Type of the right-hand side dense vector
+class TDMatDVecMultExpr : public DenseVector< TDMatDVecMultExpr<MT,VT>, false >
+ , private MatVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side dense vector expression.
+ typedef ElementType_<MRT> MET; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the right-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
+ IsBLASCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateMatrix || evaluateVector ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the matrix type and the two involved vector types are suited for a BLAS kernel,
+ the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the matrix type and the two involved vector types are suited for a vectorized
+ computation of the matrix/vector multiplication, the nested \a value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDMatDVecMultExpr<MT,VT> This; //!< Type of this TDMatDVecMultExpr instance.
+ typedef MultTrait_<MRT,VRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ MT::simdEnabled && VT::simdEnabled &&
+ HasSIMDAdd<MET,VET>::value &&
+ HasSIMDMult<MET,VET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDMatDVecMultExpr class.
+ //
+ // \param mat The left-hand side matrix operand of the multiplication expression.
+ // \param vec The right-hand side vector operand of the multiplication expression.
+ */
+ explicit inline TDMatDVecMultExpr( const MT& mat, const VT& vec ) noexcept
+ : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
+ , vec_( vec ) // Right-hand side dense vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return mat_(index,index) * vec_[index];
+ }
+ else if( IsLower<MT>::value && ( index + 8UL < mat_.rows() ) )
+ {
+ const size_t n( IsStrictlyLower<MT>::value ? index : index+1UL );
+ return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n );
+ }
+ else if( IsUpper<MT>::value && ( index > 8UL ) )
+ {
+ const size_t begin( IsStrictlyUpper<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.columns() - begin );
+ return subvector( row( mat_, index ), begin, n ) * subvector( vec_, begin, n );
+ }
+ else
+ {
+ return row( mat_, index ) * vec_;
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose dense matrix operand.
+ //
+ // \return The left-hand side transpose dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return mat_.isAligned() && vec_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( mat_.rows() * mat_.columns() < TDMATDVECMULT_THRESHOLD ) ) &&
+ ( size() > SMP_TDMATDVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand mat_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand vec_; //!< Right-hand side dense vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+ else if( rhs.mat_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ TDMatDVecMultExpr::selectAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors (kernel selection)**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a transpose dense matrix-dense vector
+ // multiplication to a dense vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDMATDVECMULT_THRESHOLD ) )
+ selectSmallAssignKernel( y, A, x );
+ else
+ selectBlasAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose dense matrix-dense
+ // vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ if( IsStrictlyLower<MT1>::value ) {
+ reset( y[0] );
+ }
+
+ if( !IsUpper<MT1>::value )
+ {
+ for( size_t i=( IsStrictlyLower<MT1>::value ? 1UL : 0UL ); i<M; ++i ) {
+ y[i] = A(i,0UL) * x[0UL];
+ }
+ }
+
+ for( size_t j=( IsUpper<MT1>::value && !IsStrictlyUpper<MT1>::value ? 0UL : 1UL ); j<N; ++j )
+ {
+ if( IsDiagonal<MT1>::value )
+ {
+ y[j] = A(j,j) * x[j];
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j-1UL : j )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ }
+ if( ipos < iend ) {
+ y[ipos] += A(ipos,j) * x[j];
+ }
+ if( IsUpper<MT1>::value ) {
+ y[iend] = A(iend,j) * x[j];
+ }
+ }
+ }
+
+ if( IsStrictlyUpper<MT1>::value ) {
+ reset( y[M-1UL] );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (small matrices)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the transpose dense
+ // matrix-dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ y.store( i+SIMDSIZE*3UL, xmm4 );
+ y.store( i+SIMDSIZE*4UL, xmm5 );
+ y.store( i+SIMDSIZE*5UL, xmm6 );
+ y.store( i+SIMDSIZE*6UL, xmm7 );
+ y.store( i+SIMDSIZE*7UL, xmm8 );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ y.store( i+SIMDSIZE*3UL, xmm4 );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE, xmm2 );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, xmm1 );
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+1UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] = value;
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (large matrices)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the transpose dense
+ // matrix-dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t iblock( 32768UL / sizeof( ElementType ) );
+ const size_t jblock( ( N < iblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( iblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ reset( y );
+
+ for( size_t ii=0U; ii<M; ii+=iblock ) {
+ for( size_t jj=0UL; jj<N; jj+=jblock )
+ {
+ const size_t jend( min( jj+jblock, N ) );
+ const size_t itmp( min( ii+iblock, M ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT1>::value ? jend-1UL : jend ) ) )
+ :( itmp ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ( IsLower<MT1>::value )
+ ?( max( ii, ( IsStrictlyLower<MT1>::value ? jj+1UL : jj ) & size_t(-SIMDSIZE) ) )
+ :( ii ) );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3 );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4 );
+ y.store( i+SIMDSIZE*4UL, y.load(i+SIMDSIZE*4UL) + xmm5 );
+ y.store( i+SIMDSIZE*5UL, y.load(i+SIMDSIZE*5UL) + xmm6 );
+ y.store( i+SIMDSIZE*6UL, y.load(i+SIMDSIZE*6UL) + xmm7 );
+ y.store( i+SIMDSIZE*7UL, y.load(i+SIMDSIZE*7UL) + xmm8 );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3 );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4 );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3 );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1 );
+ y.store( i+SIMDSIZE, y.load(i+SIMDSIZE) + xmm2 );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, y.load(i) + xmm1 );
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ ElementType value = ElementType();
+
+ for( size_t j=jj; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] += value;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors (default)********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectLargeAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors******************************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based assignment of a transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-dense vector multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ assign( y, x );
+ trmv( y, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ }
+ else {
+ gemv( y, A, x, ET(1), ET(0) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-dense vector multiplication to a sparse vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // dense vector multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ TDMatDVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors (kernel selection)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a transpose dense matrix-dense
+ // vector multiplication to a dense vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDMATDVECMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( y, A, x );
+ else
+ selectBlasAddAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose dense
+ // matrix-dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ if( IsDiagonal<MT1>::value )
+ {
+ y[j] += A(j,j) * x[j];
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ }
+ if( ipos < iend ) {
+ y[ipos] += A(ipos,j) * x[j];
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (small matrices)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultAddAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (small matrices)********************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the transpose
+ // dense matrix-dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i ) );
+ SIMDType xmm2( y.load(i+SIMDSIZE ) );
+ SIMDType xmm3( y.load(i+SIMDSIZE*2UL) );
+ SIMDType xmm4( y.load(i+SIMDSIZE*3UL) );
+ SIMDType xmm5( y.load(i+SIMDSIZE*4UL) );
+ SIMDType xmm6( y.load(i+SIMDSIZE*5UL) );
+ SIMDType xmm7( y.load(i+SIMDSIZE*6UL) );
+ SIMDType xmm8( y.load(i+SIMDSIZE*7UL) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ y.store( i+SIMDSIZE*3UL, xmm4 );
+ y.store( i+SIMDSIZE*4UL, xmm5 );
+ y.store( i+SIMDSIZE*5UL, xmm6 );
+ y.store( i+SIMDSIZE*6UL, xmm7 );
+ y.store( i+SIMDSIZE*7UL, xmm8 );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i ) );
+ SIMDType xmm2( y.load(i+SIMDSIZE ) );
+ SIMDType xmm3( y.load(i+SIMDSIZE*2UL) );
+ SIMDType xmm4( y.load(i+SIMDSIZE*3UL) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ y.store( i+SIMDSIZE*3UL, xmm4 );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i ) );
+ SIMDType xmm2( y.load(i+SIMDSIZE ) );
+ SIMDType xmm3( y.load(i+SIMDSIZE*2UL) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i ) );
+ SIMDType xmm2( y.load(i+SIMDSIZE) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE, xmm2 );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, xmm1 );
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+1UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] += value;
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (large matrices)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultAddAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (large matrices)********************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the transpose
+ // dense matrix-dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t iblock( 32768UL / sizeof( ElementType ) );
+ const size_t jblock( ( N < iblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( iblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ for( size_t ii=0U; ii<M; ii+=iblock ) {
+ for( size_t jj=0UL; jj<N; jj+=jblock )
+ {
+ const size_t jend( min( jj+jblock, N ) );
+ const size_t itmp( min( ii+iblock, M ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT1>::value ? jend-1UL : jend ) ) )
+ :( itmp ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ( IsLower<MT1>::value )
+ ?( max( ii, ( IsStrictlyLower<MT1>::value ? jj+1UL : jj ) & size_t(-SIMDSIZE) ) )
+ :( ii ) );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3 );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4 );
+ y.store( i+SIMDSIZE*4UL, y.load(i+SIMDSIZE*4UL) + xmm5 );
+ y.store( i+SIMDSIZE*5UL, y.load(i+SIMDSIZE*5UL) + xmm6 );
+ y.store( i+SIMDSIZE*6UL, y.load(i+SIMDSIZE*6UL) + xmm7 );
+ y.store( i+SIMDSIZE*7UL, y.load(i+SIMDSIZE*7UL) + xmm8 );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3 );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4 );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3 );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1 );
+ y.store( i+SIMDSIZE, y.load(i+SIMDSIZE) + xmm2 );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, y.load(i) + xmm1 );
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ ElementType value = ElementType();
+
+ for( size_t j=jj; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] += value;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors (default)***********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectLargeAddAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors*********************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based addition assignment of a transpose matrix-vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-dense vector multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ addAssign( y, tmp );
+ }
+ else {
+ gemv( y, A, x, ET(1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ TDMatDVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors (kernel selection)**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a transpose dense matrix-
+ // dense vector multiplication to a dense vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDMATDVECMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( y, A, x );
+ else
+ selectBlasSubAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose dense
+ // matrix-dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ if( IsDiagonal<MT1>::value )
+ {
+ y[j] -= A(j,j) * x[j];
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ y[i ] -= A(i ,j) * x[j];
+ y[i+1UL] -= A(i+1UL,j) * x[j];
+ }
+ if( ipos < iend ) {
+ y[ipos] -= A(ipos,j) * x[j];
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (small matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultSubAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (small matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small transpose dense matrix-dense
+ // vector multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // transpose dense matrix-dense vector multiplication. This kernel is optimized for small
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectSmallSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i ) );
+ SIMDType xmm2( y.load(i+SIMDSIZE ) );
+ SIMDType xmm3( y.load(i+SIMDSIZE*2UL) );
+ SIMDType xmm4( y.load(i+SIMDSIZE*3UL) );
+ SIMDType xmm5( y.load(i+SIMDSIZE*4UL) );
+ SIMDType xmm6( y.load(i+SIMDSIZE*5UL) );
+ SIMDType xmm7( y.load(i+SIMDSIZE*6UL) );
+ SIMDType xmm8( y.load(i+SIMDSIZE*7UL) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 - A.load(i ,j) * x1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 - A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 - A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 - A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 - A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 - A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 - A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ y.store( i+SIMDSIZE*3UL, xmm4 );
+ y.store( i+SIMDSIZE*4UL, xmm5 );
+ y.store( i+SIMDSIZE*5UL, xmm6 );
+ y.store( i+SIMDSIZE*6UL, xmm7 );
+ y.store( i+SIMDSIZE*7UL, xmm8 );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i ) );
+ SIMDType xmm2( y.load(i+SIMDSIZE ) );
+ SIMDType xmm3( y.load(i+SIMDSIZE*2UL) );
+ SIMDType xmm4( y.load(i+SIMDSIZE*3UL) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 - A.load(i ,j) * x1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 - A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 - A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ y.store( i+SIMDSIZE*3UL, xmm4 );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i ) );
+ SIMDType xmm2( y.load(i+SIMDSIZE ) );
+ SIMDType xmm3( y.load(i+SIMDSIZE*2UL) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 - A.load(i ,j) * x1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 - A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE , xmm2 );
+ y.store( i+SIMDSIZE*2UL, xmm3 );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i ) );
+ SIMDType xmm2( y.load(i+SIMDSIZE) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 - A.load(i ,j) * x1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , xmm1 );
+ y.store( i+SIMDSIZE, xmm2 );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(i) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ xmm1 = xmm1 - A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, xmm1 );
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+1UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] -= value;
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (large matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectDefaultSubAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (large matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large transpose dense matrix-dense
+ // vector multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // transpose dense matrix-dense vector multiplication. This kernel is optimized for large
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2> >
+ selectLargeSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t iblock( 32768UL / sizeof( ElementType ) );
+ const size_t jblock( ( N < iblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( iblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ for( size_t ii=0U; ii<M; ii+=iblock ) {
+ for( size_t jj=0UL; jj<N; jj+=jblock )
+ {
+ const size_t jend( min( jj+jblock, N ) );
+ const size_t itmp( min( ii+iblock, M ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT1>::value ? jend-1UL : jend ) ) )
+ :( itmp ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ( IsLower<MT1>::value )
+ ?( max( ii, ( IsStrictlyLower<MT1>::value ? jj+1UL : jj ) & size_t(-SIMDSIZE) ) )
+ :( ii ) );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3 );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) - xmm4 );
+ y.store( i+SIMDSIZE*4UL, y.load(i+SIMDSIZE*4UL) - xmm5 );
+ y.store( i+SIMDSIZE*5UL, y.load(i+SIMDSIZE*5UL) - xmm6 );
+ y.store( i+SIMDSIZE*6UL, y.load(i+SIMDSIZE*6UL) - xmm7 );
+ y.store( i+SIMDSIZE*7UL, y.load(i+SIMDSIZE*7UL) - xmm8 );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3 );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) - xmm4 );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1 );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2 );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3 );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1 );
+ y.store( i+SIMDSIZE, y.load(i+SIMDSIZE) - xmm2 );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, y.load(i) - xmm1 );
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ ElementType value = ElementType();
+
+ for( size_t j=jj; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] -= value;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors (default)********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ selectLargeSubAssignKernel( y, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors******************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based subtraction assignment of a transpose matrix-vector multiplication
+ // (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-dense vector multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2> >
+ selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ subAssign( y, tmp );
+ }
+ else {
+ gemv( y, A, x, ET(-1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a transpose dense matrix-dense vector multiplication to
+ // a dense vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a transpose dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a transpose dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+ else if( rhs.mat_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-dense vector multiplication to a sparse
+ // vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-dense vector multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense matrix-dense vector multiplication
+ // to a dense vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a transpose dense matrix-dense vector multiplication
+ // to a dense vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose dense matrix-dense vector multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a transpose dense matrix-dense vector multiplication to
+ // a dense vector (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a transpose
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,false>& lhs, const TDMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR( MT, VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSCALARMULTEXPR SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Expression object for scaled transpose dense matrix-dense vector multiplications.
+// \ingroup dense_vector_expression
+//
+// This specialization of the DVecScalarMultExpr class represents the compile time expression
+// for scaled multiplications between a column-major dense matrix and a non-transpose dense
+// vector.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename VT // Type of the right-hand side dense vector
+ , typename ST > // Type of the side scalar value
+class DVecScalarMultExpr< TDMatDVecMultExpr<MT,VT>, ST, false >
+ : public DenseVector< DVecScalarMultExpr< TDMatDVecMultExpr<MT,VT>, ST, false >, false >
+ , private VecScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef TDMatDVecMultExpr<MT,VT> MVM; //!< Type of the transpose dense matrix-dense vector multiplication expression.
+ typedef ResultType_<MVM> RES; //!< Result type of the dense matrix-dense vector multiplication expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side dense vector expression.
+ typedef ElementType_<MRT> MET; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the right-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
+ IsBLASCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateMatrix || evaluateVector ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the matrix type, the two involved vector types, and the scalar type are suited
+ for a BLAS kernel, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ !( IsBuiltin< ElementType_<T1> >::value && IsComplex<T4>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types, the matrix type, and the scalar type are suited
+ for a vectorized computation of the scaled vector/matrix multiplication, the nested
+ \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3>
+ , T4 >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecScalarMultExpr<MVM,ST,false> This; //!< Type of this DVecScalarMultExpr instance.
+ typedef MultTrait_<RES,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef const TDMatDVecMultExpr<MT,VT> LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+
+ //! Type for the assignment of the dense matrix operand of the left-hand side expression.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the dense vector operand of the left-hand side expression.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ MT::simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable<MET,VET,ST>::value &&
+ HasSIMDAdd<MET,VET>::value &&
+ HasSIMDMult<MET,VET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecScalarMultExpr class.
+ //
+ // \param vector The left-hand side dense vector of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DVecScalarMultExpr( const MVM& vector, ST scalar )
+ : vector_( vector ) // Left-hand side dense vector of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
+ return vector_[index] * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= vector_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const {
+ return vector_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return vector_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const {
+ return vector_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const {
+ LeftOperand_<MVM> A( vector_.leftOperand() );
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDMATDVECMULT_THRESHOLD ) ) &&
+ ( size() > SMP_TDMATDVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vector_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*!\brief Assignment of a scaled transpose dense matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectAssignKernel( ~lhs, A, x, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors (kernel selection)**********************************************
+ /*!\brief Selection of the kernel for an assignment of a scaled transpose dense matrix-dense
+ // vector multiplication to a dense vector (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDMATDVECMULT_THRESHOLD ) )
+ selectSmallAssignKernel( y, A, x, scalar );
+ else
+ selectBlasAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*!\brief Default assignment of a scaled transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor
+ // \return void
+ //
+ // This function implements the default assignment kernel for the scaled transpose dense
+ // matrix-dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ if( IsStrictlyLower<MT1>::value ) {
+ reset( y[0] );
+ }
+
+ if( !IsUpper<MT1>::value )
+ {
+ for( size_t i=( IsStrictlyLower<MT1>::value ? 1UL : 0UL ); i<M; ++i ) {
+ y[i] = A(i,0UL) * x[0UL];
+ }
+ }
+
+ for( size_t j=( IsUpper<MT1>::value && !IsStrictlyUpper<MT1>::value ? 0UL : 1UL ); j<N; ++j )
+ {
+ if( IsDiagonal<MT1>::value )
+ {
+ y[j] = A(j,j) * x[j] * scalar;
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j-1UL : j )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ y[i ] += A(i ,j) * x[j];
+ y[i+1UL] += A(i+1UL,j) * x[j];
+ }
+ if( ipos < iend ) {
+ y[ipos] += A(ipos,j) * x[j];
+ }
+ if( IsUpper<MT1>::value ) {
+ y[iend] = A(iend,j) * x[j];
+ }
+ }
+ }
+
+ if( IsStrictlyUpper<MT1>::value ) {
+ reset( y[M-1UL] );
+ }
+
+ if( !IsDiagonal<MT1>::value )
+ {
+ const size_t iend( IsStrictlyUpper<MT1>::value ? M-1UL : M );
+ for( size_t i=( IsStrictlyLower<MT1>::value ? 1UL : 0UL ); i<iend; ++i ) {
+ y[i] *= scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*!\brief Default assignment of a small scaled transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (small matrices)*****************************
+ /*!\brief Vectorized default assignment of a small scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the scaled transpose
+ // dense matrix-dense vector multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , xmm1*factor );
+ y.store( i+SIMDSIZE , xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, xmm4*factor );
+ y.store( i+SIMDSIZE*4UL, xmm5*factor );
+ y.store( i+SIMDSIZE*5UL, xmm6*factor );
+ y.store( i+SIMDSIZE*6UL, xmm7*factor );
+ y.store( i+SIMDSIZE*7UL, xmm8*factor );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , xmm1*factor );
+ y.store( i+SIMDSIZE , xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, xmm4*factor );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , xmm1*factor );
+ y.store( i+SIMDSIZE , xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, xmm3*factor );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , xmm1*factor );
+ y.store( i+SIMDSIZE, xmm2*factor );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i,j) * x1;
+ }
+
+ y.store( i, xmm1*factor );
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+1UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] = value * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*!\brief Default assignment of a large scaled transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (large matrices)*****************************
+ /*!\brief Vectorized default assignment of a large scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the scaled transpose
+ // dense matrix-dense vector multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t iblock( 32768UL / sizeof( ElementType ) );
+ const size_t jblock( ( N < iblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( iblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ const SIMDType factor( set( scalar ) );
+
+ reset( y );
+
+ for( size_t ii=0U; ii<M; ii+=iblock ) {
+ for( size_t jj=0UL; jj<N; jj+=jblock )
+ {
+ const size_t jend( min( jj+jblock, N ) );
+ const size_t itmp( min( ii+iblock, M ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT1>::value ? jend-1UL : jend ) ) )
+ :( itmp ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ( IsLower<MT1>::value )
+ ?( max( ii, ( IsStrictlyLower<MT1>::value ? jj+1UL : jj ) & size_t(-SIMDSIZE) ) )
+ :( ii ) );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4*factor );
+ y.store( i+SIMDSIZE*4UL, y.load(i+SIMDSIZE*4UL) + xmm5*factor );
+ y.store( i+SIMDSIZE*5UL, y.load(i+SIMDSIZE*5UL) + xmm6*factor );
+ y.store( i+SIMDSIZE*6UL, y.load(i+SIMDSIZE*6UL) + xmm7*factor );
+ y.store( i+SIMDSIZE*7UL, y.load(i+SIMDSIZE*7UL) + xmm8*factor );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4*factor );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE, y.load(i+SIMDSIZE) + xmm2*factor );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, y.load(i) + xmm1*factor );
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ ElementType value = ElementType();
+
+ for( size_t j=jj; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] += value * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors (default)********************************************
+ /*!\brief Default assignment of a scaled transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large scaled
+ // transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectLargeAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors******************************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based assignment of a scaled transpose dense matrix-dense vector multiplication
+ // (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-dense vector multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ assign( y, scalar * x );
+ trmv( y, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ }
+ else {
+ gemv( y, A, x, ET(scalar), ET(0) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*!\brief Assignment of a scaled transpose dense matrix-dense vector multiplication to a sparse
+ // vector (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // matrix-dense vector multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*!\brief Addition assignment of a scaled transpose dense matrix-dense vector multiplication
+ // to a dense vector (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectAddAssignKernel( ~lhs, A, x, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors (kernel selection)*************************************
+ /*!\brief Selection of the kernel for an addition assignment of a scaled transpose dense
+ // matrix-dense vector multiplication to a dense vector (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDMATDVECMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( y, A, x, scalar );
+ else
+ selectBlasAddAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*!\brief Default addition assignment of a scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the scaled transpose
+ // dense matrix-dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ y.addAssign( A * x * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (small matrices)*******************************
+ /*!\brief Default addition assignment of a small scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (small matrices)********************
+ /*!\brief Vectorized default addition assignment of a small scaled transpose dense matrix-dense
+ // vector multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the scaled
+ // transpose dense matrix-dense vector multiplication. This kernel is optimized for small
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4*factor );
+ y.store( i+SIMDSIZE*4UL, y.load(i+SIMDSIZE*4UL) + xmm5*factor );
+ y.store( i+SIMDSIZE*5UL, y.load(i+SIMDSIZE*5UL) + xmm6*factor );
+ y.store( i+SIMDSIZE*6UL, y.load(i+SIMDSIZE*6UL) + xmm7*factor );
+ y.store( i+SIMDSIZE*7UL, y.load(i+SIMDSIZE*7UL) + xmm8*factor );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4*factor );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE, y.load(i+SIMDSIZE) + xmm2*factor );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, y.load(i) + xmm1*factor );
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+1UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] += value * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (large matrices)*******************************
+ /*!\brief Default addition assignment of a large scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (large matrices)********************
+ /*!\brief Vectorized default addition assignment of a large scaled transpose dense matrix-dense
+ // vector multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the scaled
+ // transpose dense matrix-dense vector multiplication. This kernel is optimized for large
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t iblock( 32768UL / sizeof( ElementType ) );
+ const size_t jblock( ( N < iblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( iblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t ii=0U; ii<M; ii+=iblock ) {
+ for( size_t jj=0UL; jj<N; jj+=jblock )
+ {
+ const size_t jend( min( jj+jblock, N ) );
+ const size_t itmp( min( ii+iblock, M ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT1>::value ? jend-1UL : jend ) ) )
+ :( itmp ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ( IsLower<MT1>::value )
+ ?( max( ii, ( IsStrictlyLower<MT1>::value ? jj+1UL : jj ) & size_t(-SIMDSIZE) ) )
+ :( ii ) );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4*factor );
+ y.store( i+SIMDSIZE*4UL, y.load(i+SIMDSIZE*4UL) + xmm5*factor );
+ y.store( i+SIMDSIZE*5UL, y.load(i+SIMDSIZE*5UL) + xmm6*factor );
+ y.store( i+SIMDSIZE*6UL, y.load(i+SIMDSIZE*6UL) + xmm7*factor );
+ y.store( i+SIMDSIZE*7UL, y.load(i+SIMDSIZE*7UL) + xmm8*factor );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) + xmm4*factor );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) + xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) + xmm3*factor );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , y.load(i ) + xmm1*factor );
+ y.store( i+SIMDSIZE, y.load(i+SIMDSIZE) + xmm2*factor );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, y.load(i) + xmm1*factor );
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ ElementType value = ElementType();
+
+ for( size_t j=jj; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] += value * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors (default)***********************************
+ /*!\brief Default addition assignment of a scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // scaled transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectLargeAddAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors*********************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based addition assignment of a scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-dense vector multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( scalar * x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ addAssign( y, tmp );
+ }
+ else {
+ gemv( y, A, x, ET(scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*!\brief Subtraction assignment of a scaled transpose dense matrix-dense vector multiplication
+ // to a dense vector (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a scaled
+ // dense transpose matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectSubAssignKernel( ~lhs, A, x, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors (kernel selection)**********************************
+ /*!\brief Selection of the kernel for a subtraction assignment of a scaled transpose dense
+ // matrix-dense vector multiplication to a dense vector (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDMATDVECMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( y, A, x, scalar );
+ else
+ selectBlasSubAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the scaled transpose
+ // dense matrix-dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ y.subAssign( A * x * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (small matrices)****************************
+ /*!\brief Default subtraction assignment of a small scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (small matrices)*****************
+ /*!\brief Vectorized default subtraction assignment of a small scaled transpose dense matrix-
+ // dense vector multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // scaled transpose dense matrix-dense vector multiplication. This kernel is optimized for
+ // small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectSmallSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) - xmm4*factor );
+ y.store( i+SIMDSIZE*4UL, y.load(i+SIMDSIZE*4UL) - xmm5*factor );
+ y.store( i+SIMDSIZE*5UL, y.load(i+SIMDSIZE*5UL) - xmm6*factor );
+ y.store( i+SIMDSIZE*6UL, y.load(i+SIMDSIZE*6UL) - xmm7*factor );
+ y.store( i+SIMDSIZE*7UL, y.load(i+SIMDSIZE*7UL) - xmm8*factor );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) - xmm4*factor );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3*factor );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1*factor );
+ y.store( i+SIMDSIZE, y.load(i+SIMDSIZE) - xmm2*factor );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ SIMDType xmm1;
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, y.load(i) - xmm1*factor );
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( i+1UL, N ) - ( IsStrictlyLower<MT1>::value ? 1UL : 0UL ) )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] -= value * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (large matrices)****************************
+ /*!\brief Default subtraction assignment of a large scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (large matrices)*****************
+ /*!\brief Vectorized default subtraction assignment of a large scaled transpose dense matrix-
+ // dense vector multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // scaled transpose dense matrix-dense vector multiplication. This kernel is optimized for
+ // large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >
+ selectLargeSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ const size_t iblock( 32768UL / sizeof( ElementType ) );
+ const size_t jblock( ( N < iblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( iblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t ii=0U; ii<M; ii+=iblock ) {
+ for( size_t jj=0UL; jj<N; jj+=jblock )
+ {
+ const size_t jend( min( jj+jblock, N ) );
+ const size_t itmp( min( ii+iblock, M ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT1>::value ? jend-1UL : jend ) ) )
+ :( itmp ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ( IsLower<MT1>::value )
+ ?( max( ii, ( IsStrictlyLower<MT1>::value ? jj+1UL : jj ) & size_t(-SIMDSIZE) ) )
+ :( ii ) );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,j) * x1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,j) * x1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,j) * x1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) - xmm4*factor );
+ y.store( i+SIMDSIZE*4UL, y.load(i+SIMDSIZE*4UL) - xmm5*factor );
+ y.store( i+SIMDSIZE*5UL, y.load(i+SIMDSIZE*5UL) - xmm6*factor );
+ y.store( i+SIMDSIZE*6UL, y.load(i+SIMDSIZE*6UL) - xmm7*factor );
+ y.store( i+SIMDSIZE*7UL, y.load(i+SIMDSIZE*7UL) - xmm8*factor );
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3*factor );
+ y.store( i+SIMDSIZE*3UL, y.load(i+SIMDSIZE*3UL) - xmm4*factor );
+ }
+
+ for( ; (i+SIMDSIZE*2UL) < ipos; i+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,j) * x1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1*factor );
+ y.store( i+SIMDSIZE , y.load(i+SIMDSIZE ) - xmm2*factor );
+ y.store( i+SIMDSIZE*2UL, y.load(i+SIMDSIZE*2UL) - xmm3*factor );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ const SIMDType x1( set( x[j] ) );
+ xmm1 = xmm1 + A.load(i ,j) * x1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,j) * x1;
+ }
+
+ y.store( i , y.load(i ) - xmm1*factor );
+ y.store( i+SIMDSIZE, y.load(i+SIMDSIZE) - xmm2*factor );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t j=jj; j<jend; ++j ) {
+ xmm1 = xmm1 + A.load(i,j) * set( x[j] );
+ }
+
+ y.store( i, y.load(i) - xmm1*factor );
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ ElementType value = ElementType();
+
+ for( size_t j=jj; j<jend; ++j ) {
+ value += A(i,j) * x[j];
+ }
+
+ y[i] -= value * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors (default)********************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // scaled transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ selectLargeSubAssignKernel( y, A, x, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors******************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based subtraction assignment of a scaled transpose dense matrix-dense vector
+ // multiplication (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-dense vector multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 // Type of the right-hand side vector operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,MT1,VT2,ST2> >
+ selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( scalar * x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ subAssign( y, tmp );
+ }
+ else {
+ gemv( y, A, x, ET(-scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*!\brief Multiplication assignment of a scaled transpose dense matrix-dense vector
+ // multiplication to a dense vector (\f$ \vec{y}*=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a scaled
+ // transpose dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*!\brief Division assignment of a scaled transpose dense matrix-dense vector multiplication to
+ // a dense vector (\f$ \vec{y}/=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a scaled transpose
+ // dense matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*!\brief SMP assignment of a scaled transpose dense matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT x( right ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, A * x * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*!\brief SMP assignment of a scaled transpose dense matrix-dense vector multiplication to a
+ // sparse vector (\f$ \vec{y}=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense matrix-dense vector multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*!\brief SMP addition assignment of a scaled transpose dense matrix-dense vector multiplication
+ // to a dense vector (\f$ \vec{y}+=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a scaled
+ // transpose dense matrix-dense vector multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT x( right ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, A * x * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*!\brief SMP subtraction assignment of a scaled transpose dense matrix-dense vector
+ // multiplication to a dense vector (\f$ \vec{y}-=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a scaled
+ // dense transpose matrix-dense vector multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<MVM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<MVM> right( rhs.vector_.rightOperand() );
+
+ if( left.rows() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT x( right ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, A * x * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*!\brief SMP multiplication assignment of a scaled transpose dense matrix-dense vector
+ // multiplication to a dense vector (\f$ \vec{y}*=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // scaled transpose dense matrix-dense vector multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be
+ // selected by the compiler in case the expression specific parallel evaluation strategy
+ // is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*!\brief SMP division assignment of a scaled transpose dense matrix-dense vector multiplication
+ // to a dense vector (\f$ \vec{y}/=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a scaled
+ // transpose dense matrix-dense vector multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( MVM );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( MVM );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major dense matrix and a dense
+// vector (\f$ \vec{y}=A*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side column-major dense matrix for the multiplication.
+// \param vec The right-hand side dense vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator represents the multiplication between a column-major dense matrix and a dense
+// vector:
+
+ \code
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ blaze::DynamicMatrix<double,columnMajor> A;
+ blaze::DynamicVector<double,columnVector> x, y;
+ // ... Resizing and initialization
+ y = A * x;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both the
+// dense matrix type \a T1 and the dense vector type \a T2 as well as the two element types
+// \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of columns
+// of the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense vector
+inline const DisableIf_< IsMatMatMultExpr<T1>, TDMatDVecMultExpr<T1,T2> >
+ operator*( const DenseMatrix<T1,true>& mat, const DenseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return TDMatDVecMultExpr<T1,T2>( ~mat, ~vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct Size< TDMatDVecMultExpr<MT,VT> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct IsAligned< TDMatDVecMultExpr<MT,VT> >
+ : public BoolConstant< And< IsAligned<MT>, IsAligned<VT> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, bool AF >
+struct SubvectorExprTrait< TDMatDVecMultExpr<MT,VT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>
+ , SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDMatSMatAddExpr.h b/src/cpu/blaze/math/expressions/TDMatSMatAddExpr.h
new file mode 100644
index 00000000..96683072
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDMatSMatAddExpr.h
@@ -0,0 +1,1082 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDMatSMatAddExpr.h
+// \brief Header file for the transpose dense matrix/sparse matrix addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDMATSMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDMATSMATADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for dense matrix-sparse matrix additions.
+// \ingroup dense_matrix_expression
+//
+// The TDMatSMatAddExpr class represents the compile time expression for additions between
+// a column-major dense matrix and a row-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TDMatSMatAddExpr : public DenseMatrix< TDMatSMatAddExpr<MT1,MT2>, true >
+ , private MatMatAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDMatSMatAddExpr<MT1,MT2> This; //!< Type of this TDMatSMatAddExpr instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDMatSMatAddExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the addition expression.
+ // \param rhs The right-hand side sparse matrix operand of the addition expression.
+ */
+ explicit inline TDMatSMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the addition expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) + rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose dense matrix operand.
+ //
+ // \return The left-hand side transpose dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && lhs_.canAlias( alias ) ) ||
+ ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the addition expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix addition expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const TDMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense matrix-sparse matrix addition to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense matrix-sparse matrix addition to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-sparse matrix addition to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense matrix-
+ // sparse matrix addition expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-sparse matrix addition to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense matrix-
+ // sparse matrix addition expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const TDMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense matrix-sparse matrix addition to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense matrix-sparse matrix addition expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense matrix-sparse matrix addition to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense matrix-sparse matrix addition expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a column-major dense matrix and a row-major
+// sparse matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix addition.
+// \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the addition of a column-major dense matrix and a row-major sparse
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,columnMajor> A;
+ blaze::CompressedMatrix<double,rowMajor> B;
+ blaze::DynamicMatrix<double,rowMajor> C;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+const TDMatSMatAddExpr<T1,T2>
+ operator+( const DenseMatrix<T1,true>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TDMatSMatAddExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of a row-major sparse matrix and a column-major
+// dense matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix addition.
+// \param rhs The right-hand side dense matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the addition of a row-major sparse matrix and a column-major dense
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A;
+ blaze::DynamicMatrix<double,columnMajor> B;
+ blaze::DynamicMatrix<double,rowMajor> C;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+const TDMatSMatAddExpr<T1,T2>
+ operator+( const SparseMatrix<T2,false>& lhs, const DenseMatrix<T1,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TDMatSMatAddExpr<T1,T2>( ~rhs, ~lhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a transpose dense matrix-sparse matrix
+// addition expression and a dense matrix (\f$ A=(B+C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side transpose dense matrix-sparse matrix addition.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a transpose
+// dense matrix-sparse matrix addition expression to a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< TDMatSMatAddExpr<T1,T2>, T3 >
+ operator+( const TDMatSMatAddExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() + (~rhs) ) + lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a transpose dense matrix-sparse matrix
+// addition expression and a dense matrix (\f$ A=(B+C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side transpose dense matrix-sparse matrix addition.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a transpose
+// dense matrix-sparse matrix addition expression and a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< TDMatSMatAddExpr<T1,T2>, T3 >
+ operator-( const TDMatSMatAddExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() - (~rhs) ) + lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TDMatSMatAddExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TDMatSMatAddExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< TDMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< TDMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TDMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TDMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >
+ , And< IsUniLower<MT2>, IsStrictlyLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TDMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TDMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TDMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >
+ , And< IsUniUpper<MT2>, IsStrictlyUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TDMatSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< TDMatSMatAddExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< TDMatDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< TDMatSMatAddExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatSMatAddExprTrait_< TDMatTDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< TDMatSMatAddExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatAddExprTrait_< TDMatDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< TDMatSMatAddExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatSMatAddExprTrait_< TDMatTDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TDMatSMatAddExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TDMatSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TDMatSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDMatSMatMultExpr.h b/src/cpu/blaze/math/expressions/TDMatSMatMultExpr.h
new file mode 100644
index 00000000..35dd39d9
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDMatSMatMultExpr.h
@@ -0,0 +1,2128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDMatSMatMultExpr.h
+// \brief Header file for the transpose dense matrix/sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SMatSVecMultExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDMATSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense matrix-sparse matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The TDMatSMatMultExpr class represents the compile time expression for multiplications between
+// a column-major dense matrix and a row-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TDMatSMatMultExpr : public DenseMatrix< TDMatSMatMultExpr<MT1,MT2>, true >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the right-hand side matrix operands of type \a T3 is
+ symmetric, \a value is set to 1 and an optimized evaluation strategy is selected.
+ Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsSymmetric<T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no SMP assignment is required and the element type of the target matrix has a
+ fixed size (i.e. is not resizable), the nested \value will be set to 1, otherwise it
+ will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !( IsColumnMajorMatrix<T1>::value && IsResizable<ET2>::value ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no SMP assignment is required and the element type of the target matrix is
+ resizable, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDMatSMatMultExpr<MT1,MT2> This; //!< Type of this TDMatSMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDMatSMatMultExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the multiplication expression.
+ // \param rhs The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline TDMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose dense matrix operand.
+ //
+ // \return The left-hand side transpose dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( columns() > SMP_TDMATSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a transpose dense matrix-sparse matrix
+ // multiplication to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
+ selectSmallAssignKernel( C, A, B );
+ else
+ selectLargeAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a transpose dense matrix-sparse matrix
+ // multiplication expression to a dense matrix. This assign function is used in case the
+ // element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ reset( C );
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ if( IsDiagonal<MT4>::value )
+ {
+ for( ; element!=end; ++element ) {
+ C(j,element->index()) = A(j,j) * element->value();
+ }
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( ; element!=end; ++element ) {
+ for( size_t i=ibegin; i<iend; ++i ) {
+ if( isDefault( C(i,element->index()) ) )
+ C(i,element->index()) = A(i,j) * element->value();
+ else
+ C(i,element->index()) += A(i,j) * element->value();
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small transpose dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices (small matrices)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a small transpose dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix multiplication expression to a dense matrix. This assign function is used in
+ // case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ reset( C );
+
+ size_t i( 0UL );
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ for( i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j1) += A(i ,j) * v1;
+ C(i+1UL,j1) += A(i+1UL,j) * v1;
+ C(i+2UL,j1) += A(i+2UL,j) * v1;
+ C(i+3UL,j1) += A(i+3UL,j) * v1;
+ C(i ,j2) += A(i ,j) * v2;
+ C(i+1UL,j2) += A(i+1UL,j) * v2;
+ C(i+2UL,j2) += A(i+2UL,j) * v2;
+ C(i+3UL,j2) += A(i+3UL,j) * v2;
+ C(i ,j3) += A(i ,j) * v3;
+ C(i+1UL,j3) += A(i+1UL,j) * v3;
+ C(i+2UL,j3) += A(i+2UL,j) * v3;
+ C(i+3UL,j3) += A(i+3UL,j) * v3;
+ C(i ,j4) += A(i ,j) * v4;
+ C(i+1UL,j4) += A(i+1UL,j) * v4;
+ C(i+2UL,j4) += A(i+2UL,j) * v4;
+ C(i+3UL,j4) += A(i+3UL,j) * v4;
+ }
+ for( ; i<iend; ++i ) {
+ C(i,j1) += A(i,j) * v1;
+ C(i,j2) += A(i,j) * v2;
+ C(i,j3) += A(i,j) * v3;
+ C(i,j4) += A(i,j) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ for( i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j1) += A(i ,j) * v1;
+ C(i+1UL,j1) += A(i+1UL,j) * v1;
+ C(i+2UL,j1) += A(i+2UL,j) * v1;
+ C(i+3UL,j1) += A(i+3UL,j) * v1;
+ }
+ for( ; i<iend; ++i ) {
+ C(i,j1) += A(i,j) * v1;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices (large matrices)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix multiplication expression to a dense matrix. This assign function is used in
+ // case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( C, A * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse matrix multiplication to a sparse matrix
+ // (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a transpose dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a transpose dense
+ // matrix-sparse matrix multiplication expression. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case the symmetry
+ // of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense matrix-sparse matrix multiplication to
+ // a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a transpose dense matrix-sparse
+ // matrix multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
+ selectSmallAddAssignKernel( C, A, B );
+ else
+ selectLargeAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense matrix-sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a transpose dense matrix-sparse
+ // matrix multiplication expression to a dense matrix. This assign function is use in case the
+ // element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ size_t i( 0UL );
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ if( IsDiagonal<MT4>::value )
+ {
+ for( ; element!=end; ++element ) {
+ C(j,element->index()) += A(j,j) * element->value();
+ }
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( ; element!=end; ++element ) {
+ for( i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,element->index()) += A(i ,j) * element->value();
+ C(i+1UL,element->index()) += A(i+1UL,j) * element->value();
+ C(i+2UL,element->index()) += A(i+2UL,j) * element->value();
+ C(i+3UL,element->index()) += A(i+3UL,j) * element->value();
+ }
+ for( ; i<iend; ++i ) {
+ C(i,element->index()) += A(i,j) * element->value();
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small transpose dense matrix-sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices (small matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a small transpose dense matrix-sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-sparse matrix multiplication expression to a dense matrix. This assign function is
+ // used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ size_t i( 0UL );
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ for( i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j1) += A(i ,j) * v1;
+ C(i+1UL,j1) += A(i+1UL,j) * v1;
+ C(i+2UL,j1) += A(i+2UL,j) * v1;
+ C(i+3UL,j1) += A(i+3UL,j) * v1;
+ C(i ,j2) += A(i ,j) * v2;
+ C(i+1UL,j2) += A(i+1UL,j) * v2;
+ C(i+2UL,j2) += A(i+2UL,j) * v2;
+ C(i+3UL,j2) += A(i+3UL,j) * v2;
+ C(i ,j3) += A(i ,j) * v3;
+ C(i+1UL,j3) += A(i+1UL,j) * v3;
+ C(i+2UL,j3) += A(i+2UL,j) * v3;
+ C(i+3UL,j3) += A(i+3UL,j) * v3;
+ C(i ,j4) += A(i ,j) * v4;
+ C(i+1UL,j4) += A(i+1UL,j) * v4;
+ C(i+2UL,j4) += A(i+2UL,j) * v4;
+ C(i+3UL,j4) += A(i+3UL,j) * v4;
+ }
+ for( ; i<iend; ++i ) {
+ C(i,j1) += A(i,j) * v1;
+ C(i,j2) += A(i,j) * v2;
+ C(i,j3) += A(i,j) * v3;
+ C(i,j4) += A(i,j) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ for( i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j1) += A(i ,j) * v1;
+ C(i+1UL,j1) += A(i+1UL,j) * v1;
+ C(i+2UL,j1) += A(i+2UL,j) * v1;
+ C(i+3UL,j1) += A(i+3UL,j) * v1;
+ }
+ for( ; i<iend; ++i ) {
+ C(i,j1) += A(i,j) * v1;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose dense matrix-sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices (large matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose dense matrix-sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-sparse matrix multiplication expression to a dense matrix. This assign function is
+ // used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( C, A * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a transpose dense matrix-sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a transpose
+ // dense matrix-sparse matrix multiplication expression. Due to the explicit application of the
+ // SFINAE principle this function can only be selected by the compiler in case the symmetry of
+ // either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense matrix-sparse matrix multiplication to a
+ // dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a transpose dense matrix-
+ // sparse matrix multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
+ selectSmallSubAssignKernel( C, A, B );
+ else
+ selectLargeSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense matrix-sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a transpose dense matrix-
+ // sparse matrix multiplication expression to a dense matrix. This assign function is used
+ // in case the element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ size_t i( 0UL );
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ if( IsDiagonal<MT4>::value )
+ {
+ for( ; element!=end; ++element ) {
+ C(j,element->index()) -= A(j,j) * element->value();
+ }
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( ; element!=end; ++element ) {
+ for( i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,element->index()) -= A(i ,j) * element->value();
+ C(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
+ C(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
+ C(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
+ }
+ for( ; i<iend; ++i ) {
+ C(i,element->index()) -= A(i,j) * element->value();
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small transpose dense matrix-sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices (small matrices)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a small transpose dense matrix-sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-sparse matrix multiplication expression to a dense matrix. This assign function
+ // is used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ size_t i( 0UL );
+
+ for( size_t j=0UL; j<B.rows(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ for( i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j1) -= A(i ,j) * v1;
+ C(i+1UL,j1) -= A(i+1UL,j) * v1;
+ C(i+2UL,j1) -= A(i+2UL,j) * v1;
+ C(i+3UL,j1) -= A(i+3UL,j) * v1;
+ C(i ,j2) -= A(i ,j) * v2;
+ C(i+1UL,j2) -= A(i+1UL,j) * v2;
+ C(i+2UL,j2) -= A(i+2UL,j) * v2;
+ C(i+3UL,j2) -= A(i+3UL,j) * v2;
+ C(i ,j3) -= A(i ,j) * v3;
+ C(i+1UL,j3) -= A(i+1UL,j) * v3;
+ C(i+2UL,j3) -= A(i+2UL,j) * v3;
+ C(i+3UL,j3) -= A(i+3UL,j) * v3;
+ C(i ,j4) -= A(i ,j) * v4;
+ C(i+1UL,j4) -= A(i+1UL,j) * v4;
+ C(i+2UL,j4) -= A(i+2UL,j) * v4;
+ C(i+3UL,j4) -= A(i+3UL,j) * v4;
+ }
+ for( ; i<iend; ++i ) {
+ C(i,j1) -= A(i,j) * v1;
+ C(i,j2) -= A(i,j) * v2;
+ C(i,j3) -= A(i,j) * v3;
+ C(i,j4) -= A(i,j) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ for( i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j1) -= A(i ,j) * v1;
+ C(i+1UL,j1) -= A(i+1UL,j) * v1;
+ C(i+2UL,j1) -= A(i+2UL,j) * v1;
+ C(i+3UL,j1) -= A(i+3UL,j) * v1;
+ }
+ for( ; i<iend; ++i ) {
+ C(i,j1) -= A(i,j) * v1;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose dense matrix-sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices (large matrices)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose dense matrix-sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-sparse matrix multiplication expression to a dense matrix. This assign function
+ // is used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( C, A * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a transpose dense matrix-sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // transpose dense matrix-sparse matrix multiplication expression. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix multiplication expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case either
+ // of the two matrix operands requires an intermediate evaluation and no symmetry can be
+ // exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-sparse matrix multiplication to a sparse
+ // matrix (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-sparse matrix multiplication expression to a sparse matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a transpose dense matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a transpose
+ // dense matrix-sparse matrix multiplication expression. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case the
+ // symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense matrix-sparse matrix multiplication to
+ // a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-sparse matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case either of the two matrix operands requires an intermediate evaluation and no symmetry
+ // can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a transpose dense matrix-sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of
+ // a transpose dense matrix-sparse matrix multiplication expression. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense matrix-sparse matrix multiplication
+ // to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-sparse matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case either of the two matrix operands requires an intermediate evaluation and no symmetry
+ // can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a transpose dense matrix-sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of
+ // a transpose dense matrix-sparse matrix multiplication expression. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major dense matrix and a
+// row-major sparse matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the multiplication.
+// \param rhs The right-hand side sparse matrix for the multiplication.
+// \return The resulting matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the multiplication of a column-major dense matrix and a row-major
+// sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,columnMajor> A, C;
+ blaze::CompressedMatrix<double,rowMajor> B;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const TDMatSMatMultExpr<T1,T2>
+ operator*( const DenseMatrix<T1,true>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TDMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TDMatSMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TDMatSMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< TDMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsAligned<MT1>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TDMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TDMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TDMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TDMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TDMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TDMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatDVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TDMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatSVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TDMatSVecMultExprTrait_< MT1, SMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecSMatMultExprTrait_< TSVecTDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TDMatSMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TDMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TDMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDMatSMatSubExpr.h b/src/cpu/blaze/math/expressions/TDMatSMatSubExpr.h
new file mode 100644
index 00000000..0532f2f0
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDMatSMatSubExpr.h
@@ -0,0 +1,1032 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDMatSMatSubExpr.h
+// \brief Header file for the transpose dense matrix/sparse matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDMATSMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDMATSMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense matrix-sparse matrix subtractions.
+// \ingroup dense_matrix_expression
+//
+// The TDMatSMatSubExpr class represents the compile time expression for subtractions between
+// a row-major dense matrix and a column-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TDMatSMatSubExpr : public DenseMatrix< TDMatSMatSubExpr<MT1,MT2>, true >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side dense matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDMatSMatSubExpr<MT1,MT2> This; //!< Type of this TDMatSMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDMatSMatSubExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the subtraction expression.
+ // \param rhs The right-hand side sparse matrix operand of the subtraction expression.
+ */
+ explicit inline TDMatSMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose dense matrix operand.
+ //
+ // \return The left-hand side transpose dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( IsExpression<MT1>::value && lhs_.canAlias( alias ) ) ||
+ ( rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ assign ( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse matrix subtraction expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const TDMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense matrix-sparse matrix subtraction to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense matrix-sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense matrix-
+ // sparse matrix subtraction expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( !IsExpression<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ else {
+ smpAssign ( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-sparse matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense matrix-
+ // sparse matrix subtraction expression to a sparse matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const TDMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense matrix-sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-sparse matrix subtraction expression to a dense matrix. Due to the explicit application
+ // of the SFINAE principle, this function can only be selected by the compiler in case the
+ // expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense matrix-sparse matrix subtraction to
+ // a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense matrix-sparse matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const TDMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a column-major dense matrix and a row-major
+// sparse matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the matrix subtraction.
+// \param rhs The right-hand side sparse matrix to be subtracted from the dense matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the subtraction of a column-major dense matrix and a row-major sparse
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,columnMajor> A;
+ blaze::CompressedMatrix<double,rowMajor> B;
+ blaze::DynamicMatrix<double,rowMajor> C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const TDMatSMatSubExpr<T1,T2>
+ operator-( const DenseMatrix<T1,true>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TDMatSMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a transpose dense matrix-sparse matrix
+// subtraction expression and a dense matrix (\f$ A=(B-C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side transpose dense matrix-sparse matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a transpose
+// dense matrix-sparse matrix subtraction expression to a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< TDMatSMatSubExpr<T1,T2>, T3 >
+ operator+( const TDMatSMatSubExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() + (~rhs) ) - lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a transpose dense matrix-sparse matrix
+// subtraction expression and a dense matrix (\f$ A=(B+C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side transpose dense matrix-sparse matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a transpose
+// dense matrix-sparse matrix subtraction expression and a dense matrix.
+*/
+template< typename T1 // Type of the dense matrix of the left-hand side expression
+ , typename T2 // Type of the sparse matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< TDMatSMatSubExpr<T1,T2>, T3 >
+ operator-( const TDMatSMatSubExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( lhs.leftOperand() - (~rhs) ) - lhs.rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TDMatSMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TDMatSMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< TDMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< TDMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TDMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TDMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TDMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TDMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TDMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TDMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< TDMatSMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatSubExprTrait_< TDMatDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< TDMatSMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatSMatSubExprTrait_< TDMatTDMatAddExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< TDMatSMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatSMatSubExprTrait_< TDMatDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< TDMatSMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TDMatSMatSubExprTrait_< TDMatTDMatSubExprTrait_<MT1,MT3>, MT2 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TDMatSMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TDMatSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TDMatSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDMatSVecMultExpr.h b/src/cpu/blaze/math/expressions/TDMatSVecMultExpr.h
new file mode 100644
index 00000000..5f4db80e
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDMatSVecMultExpr.h
@@ -0,0 +1,1819 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDMatSVecMultExpr.h
+// \brief Header file for the transpose dense matrix/sparse vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDMATSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDMATSVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense matrix-sparse vector multiplications.
+// \ingroup dense_vector_expression
+//
+// The TDMatSVecMultExpr class represents the compile time expression for multiplications
+// between column-major dense matrices and sparse vectors.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename VT > // Type of the right-hand side sparse vector
+class TDMatSVecMultExpr : public DenseVector< TDMatSVecMultExpr<MT,VT>, false >
+ , private MatVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side sparse vector expression.
+ typedef ElementType_<MRT> MET; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the right-hand side sparse vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateMatrix || evaluateVector ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the matrix type and the two involved vector types are suited for a vectorized
+ computation of the matrix/vector multiplication, the nested \value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case a vectorized computation of the matrix/vector multiplication is not possible, but
+ a loop-unrolled computation is feasible, the nested \value will be set to 1, otherwise it
+ will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = !UseVectorizedKernel<T1,T2,T3>::value &&
+ !IsDiagonal<T2>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !IsResizable<VET>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case neither a vectorized nor optimized computation is possible, the nested \value will
+ be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseVectorizedKernel<T1,T2,T3>::value &&
+ !UseOptimizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDMatSVecMultExpr<MT,VT> This; //!< Type of this TDMatSVecMultExpr instance.
+ typedef MultTrait_<MRT,VRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateVector, const VRT, CompositeType_<VT> > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ MT::simdEnabled &&
+ HasSIMDAdd<MET,VET>::value &&
+ HasSIMDMult<MET,VET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDMatSVecMultExpr class.
+ //
+ // \param mat The left-hand side dense matrix operand of the multiplication expression.
+ // \param vec The right-hand side sparse vector operand of the multiplication expression.
+ */
+ explicit inline TDMatSVecMultExpr( const MT& mat, const VT& vec ) noexcept
+ : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
+ , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return mat_(index,index) * vec_[index];
+ }
+ else if( IsLower<MT>::value )
+ {
+ const size_t n( IsStrictlyLower<MT>::value ? index : index+1UL );
+ return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n );
+ }
+ else if( IsUpper<MT>::value )
+ {
+ const size_t begin( IsStrictlyUpper<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.columns() - begin );
+ return subvector( row( mat_, index ), begin, n ) * subvector( vec_, begin, n );
+ }
+ else
+ {
+ return row( mat_, index ) * vec_;
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose dense matrix operand.
+ //
+ // \return The left-hand side transpose dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return mat_.isAliased( alias ) || vec_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return mat_.isAliased( alias ) || vec_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return mat_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_TDMATSVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand mat_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand vec_; //!< Right-hand side sparse vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse vector multiplication to a dense vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ TDMatSVecMultExpr::selectAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense matrix-sparse vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose dense matrix-
+ // sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<VT1,MT1,VT2> >
+ selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ size_t last( 0UL );
+
+ if( IsLower<MT1>::value ) {
+ const size_t iend( IsStrictlyLower<MT1>::value ? element->index()+1UL : element->index() );
+ for( size_t i=0UL; i<iend; ++i )
+ reset( y[i] );
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t index( element->index() );
+
+ if( IsDiagonal<MT1>::value )
+ {
+ for( size_t i=last; i<index; ++i )
+ reset( y[i] );
+
+ y[index] = A(index,index) * element->value();
+ last = index + 1UL;
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? index+1UL : index )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? index : index+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<last; ++i ) {
+ y[i] += A(i,index) * element->value();
+ }
+ for( size_t i=last; i<iend; ++i ) {
+ y[i] = A(i,index) * element->value();
+ }
+
+ last = iend;
+ }
+ }
+
+ if( IsUpper<MT1>::value ) {
+ for( size_t i=last; i<M; ++i )
+ reset( y[i] );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a transpose dense matrix-sparse vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the optimized assignment kernel for the transpose dense matrix-
+ // sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseOptimizedKernel<VT1,MT1,VT2> >
+ selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t jpos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ if( jpos > 3UL )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse vector index detected" );
+
+ for( size_t i=0UL; i<M; ++i ) {
+ y[i] = A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+ else
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+
+ for( size_t i=0UL; i<M; ++i ) {
+ y[i] = A(i,j1) * v1;
+ }
+ }
+
+ for( size_t j=(jpos>3UL)?(4UL):(1UL); (j+4UL)<=jpos; j+=4UL )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse vector index detected" );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j1+1UL : j1 )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j4 : j4+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j1+1UL : j1 )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j1 : j1+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ y[i] += A(i,j1) * v1;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized assignment to dense vectors******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized assignment of a transpose dense matrix-sparse vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the vectorized assignment kernel for the transpose dense matrix-
+ // sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<VT1,MT1,VT2> >
+ selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t jpos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ if( jpos > 3UL )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse vector index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ y.store( i, A.load(i,j1) * xmm1 + A.load(i,j2) * xmm2 + A.load(i,j3) * xmm3 + A.load(i,j4) * xmm4 );
+ }
+ for( ; remainder && i<M; ++i ) {
+ y[i] = A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+ else
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ y.store( i, A.load(i,j1) * xmm1 );
+ }
+ for( ; remainder && i<M; ++i ) {
+ y[i] = A(i,j1) * v1;
+ }
+ }
+
+ for( size_t j=(jpos>3UL)?(4UL):(1UL); (j+4UL)<=jpos; j+=4UL )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse vector index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j4 : j4+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ y.store( i, y.load(i) + A.load(i,j1) * xmm1 + A.load(i,j2) * xmm2 + A.load(i,j3) * xmm3 + A.load(i,j4) * xmm4 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j1 : j1+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ y.store( i, y.load(i) + A.load(i,j1) * xmm1 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ y[i] += A(i,j1) * v1;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-sparse vector multiplication to a sparse vector
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // sparse vector multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense matrix-sparse vector multiplication to a
+ // dense vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ TDMatSVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense matrix-sparse vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose dense
+ // matrix-sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<VT1,MT1,VT2> >
+ selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t index( element->index() );
+
+ if( IsDiagonal<MT1>::value )
+ {
+ y[index] += A(index,index) * element->value();
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? index+1UL : index )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? index : index+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ y[i] += A(i,index) * element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a transpose dense matrix-sparse vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the optimized addition assignment kernel for the transpose dense
+ // matrix-sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseOptimizedKernel<VT1,MT1,VT2> >
+ selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t jpos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=0UL; (j+4UL)<=jpos; j+=4UL )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse vector index detected" );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j1+1UL : j1 )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j4 : j4+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j1+1UL : j1 )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j1 : j1+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ y[i] += A(i,j1) * v1;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized addition assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized addition assignment of a transpose dense matrix-sparse vector
+ // multiplication (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the vectorized addition assignment kernel for the transpose dense
+ // matrix-sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<VT1,MT1,VT2> >
+ selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t jpos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=0UL; (j+4UL)<=jpos; j+=4UL )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse vector index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j4 : j4+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ y.store( i, y.load(i) + A.load(i,j1) * xmm1 + A.load(i,j2) * xmm2 + A.load(i,j3) * xmm3 + A.load(i,j4) * xmm4 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j1 : j1+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ y.store( i, y.load(i) + A.load(i,j1) * xmm1 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ y[i] += A(i,j1) * v1;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense matrix-sparse vector multiplication to
+ // a dense vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ TDMatSVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense matrix-sparse vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose dense
+ // matrix-sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseDefaultKernel<VT1,MT1,VT2> >
+ selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t index( element->index() );
+
+ if( IsDiagonal<MT1>::value )
+ {
+ y[index] -= A(index,index) * element->value();
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? index+1UL : index )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? index : index+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ y[i] -= A(i,index) * element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense vectors*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a transpose dense matrix-sparse vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the optimized subtraction assignment kernel for the transpose dense
+ // matrix-sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseOptimizedKernel<VT1,MT1,VT2> >
+ selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t jpos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=0UL; (j+4UL)<=jpos; j+=4UL )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse vector index detected" );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j1+1UL : j1 )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j4 : j4+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ y[i] -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j1+1UL : j1 )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j1 : j1+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ y[i] -= A(i,j1) * v1;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized subtraction assignment to dense vectors******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized subtraction assignment of a transpose dense matrix-sparse vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side dense matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the vectorized subtraction assignment kernel for the transpose
+ // dense matrix-sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline EnableIf_< UseVectorizedKernel<VT1,MT1,VT2> >
+ selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<RT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t M( A.rows() );
+
+ const bool remainder( !IsPadded<MT1>::value || !IsPadded<VT1>::value );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t jpos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t j=0UL; (j+4UL)<=jpos; j+=4UL )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse vector index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j4 : j4+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ y.store( i, y.load(i) - A.load(i,j1) * xmm1 - A.load(i,j2) * xmm2 - A.load(i,j3) * xmm3 - A.load(i,j4) * xmm4 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ y[i] -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const VET v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j1 : j1+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ y.store( i, y.load(i) - A.load(i,j1) * xmm1 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ y[i] -= A(i,j1) * v1;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a transpose dense matrix-sparse vector multiplication
+ // to a dense vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // dense matrix-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a transpose dense matrix-sparse vector multiplication to a
+ // dense vector (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a transpose dense
+ // matrix-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-sparse vector multiplication to a dense
+ // vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ smpAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-sparse vector multiplication to a sparse
+ // vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-sparse vector multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense matrix-sparse vector multiplication to
+ // a dense vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ smpAddAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense matrix-sparse vector multiplication
+ // to a dense vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side dense matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the dense matrix-sparse vector multiplication
+ smpSubAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a transpose dense matrix-sparse vector multiplication
+ // to a dense vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose dense matrix-sparse vector multiplication expression to a dense vector. Due
+ // to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a transpose dense matrix-sparse vector multiplication to
+ // a dense vector (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a transpose
+ // dense matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR( MT, VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major dense matrix and a
+// sparse vector (\f$ \vec{y}=A*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side column-major dense matrix for the multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator represents the multiplication between a column-major dense matrix and a sparse
+// vector:
+
+ \code
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ blaze::DynamicMatrix<double,columnMajor> A;
+ blaze::CompressedVector<double,columnVector> x;
+ blaze::DynamicVector<double,columnVector> y;
+ // ... Resizing and initialization
+ y = A * x;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both the
+// dense matrix type \a T1 and the sparse vector type \a T2 as well as the two element types
+// \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of columns
+// of the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const DisableIf_< IsMatMatMultExpr<T1>, TDMatSVecMultExpr<T1,T2> >
+ operator*( const DenseMatrix<T1,true>& mat, const SparseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return TDMatSVecMultExpr<T1,T2>( ~mat, ~vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct Size< TDMatSVecMultExpr<MT,VT> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct IsAligned< TDMatSVecMultExpr<MT,VT> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, bool AF >
+struct SubvectorExprTrait< TDMatSVecMultExpr<MT,VT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>
+ , SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDMatTDMatMultExpr.h b/src/cpu/blaze/math/expressions/TDMatTDMatMultExpr.h
new file mode 100644
index 00000000..764c9a7e
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDMatTDMatMultExpr.h
@@ -0,0 +1,8119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDMatTDMatMultExpr.h
+// \brief Header file for the transpose dense matrix/transpose dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDMATTDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDMATTDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/gemm.h>
+#include <blaze/math/blas/trmm.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/expressions/MatScalarMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyTriangular.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDMATTDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense matrix-transpose dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The TDMatTDMatMultExpr class represents the compile time expression for multiplications between
+// two column-major dense matrices.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class TDMatTDMatMultExpr : public DenseMatrix< TDMatTDMatMultExpr<MT1,MT2>, true >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the target matrix is row-major and either of the two
+ matrix operands is symmetric, \a value is set to 1 and an optimized evaluation
+ strategy is selected. Otherwise \a value is set to 0 and the default strategy is
+ chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsRowMajorMatrix<T1>::value &&
+ ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the types of all three involved matrices are suited for a BLAS kernel, the nested
+ \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDMatTDMatMultExpr<MT1,MT2> This; //!< Type of this TDMatTDMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT1>::value &&
+ MT1::simdEnabled && MT2::simdEnabled &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDMatTDMatMultExpr class.
+ //
+ // \param lhs The left-hand side operand of the multiplication expression.
+ // \param rhs The right-hand side operand of the multiplication expression.
+ */
+ explicit inline TDMatTDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose dense matrix operand.
+ //
+ // \return The left-hand side transpose dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned() && rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( rows() * columns() < TDMATTDMATMULT_THRESHOLD ) ) &&
+ ( columns() > SMP_TDMATTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-transpose dense matrix multiplication to a
+ // dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( rhs.lhs_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatTDMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a transpose dense matrix-transpose
+ // dense matrix multiplication to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value ) ||
+ ( C.rows() * C.columns() < TDMATTDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( C, A, B );
+ else
+ selectBlasAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (general/general)**************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general transpose dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general transpose dense matrix-general
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ if( IsStrictlyTriangular<MT5>::value && kbegin == kend ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ continue;
+ }
+
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? kbegin+1UL : kbegin )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? kbegin : kbegin+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value && IsLower<MT5>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ else if( IsStrictlyLower<MT4>::value ) {
+ reset( C(0UL,j) );
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) = A(i,kbegin) * B(kbegin,j);
+ }
+ if( IsUpper<MT4>::value && IsUpper<MT5>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ else if( IsStrictlyUpper<MT4>::value ) {
+ reset( C(M-1UL,j) );
+ }
+ }
+
+ for( size_t k=kbegin+1UL; k<kend; ++k )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? k-1UL : k )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) += A(i,k) * B(k,j);
+ }
+ if( IsUpper<MT4>::value ) {
+ C(iend,j) = A(iend,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (general/diagonal)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a general transpose dense matrix-diagonal transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a general transpose dense matrix-diagonal
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) = A(i,j) * B(j,j);
+ }
+ if( IsUpper<MT4>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/general)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal transpose dense matrix-general transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal transpose dense matrix-general
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) = A(i,i) * B(i,j);
+ }
+ if( IsUpper<MT4>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/diagonal)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a diagonal transpose dense matrix-diagonal transpose dense
+ // matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a diagonal transpose dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) = A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (small matrices)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a transpose dense matrix-
+ // transpose dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( ~C, A * tmp );
+ }
+ else if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( ~C, tmp * B );
+ }
+ else if( B.rows() * B.columns() <= A.rows() * A.columns() ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( ~C, A * tmp );
+ }
+ else {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( ~C, tmp * B );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (small matrices)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a transpose dense matrix-
+ // transpose dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ (~C).store( i+SIMDSIZE*4UL, j, xmm5 );
+ (~C).store( i+SIMDSIZE*5UL, j, xmm6 );
+ (~C).store( i+SIMDSIZE*6UL, j, xmm7 );
+ (~C).store( i+SIMDSIZE*7UL, j, xmm8 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE , j , xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j , xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i+SIMDSIZE , j+1UL, xmm6 );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, xmm7 );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, xmm8 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i+SIMDSIZE, j+1UL, xmm4 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+1UL, xmm2 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) = value1;
+ (~C)(i,j+1UL) = value2;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (large matrices)******************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a transpose dense matrix-
+ // transpose dense matrix multiplication expression to a row-major dense matrix. This kernel
+ // is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ selectSmallAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (large matrices)***************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a transpose dense matrix-
+ // transpose dense matrix multiplication expression to a column-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_JBLOCK_SIZE, N ) );
+
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i2,j ) );
+ SIMDType xmm4( (~C).load(i3,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i1,j+1UL) );
+ SIMDType xmm7( (~C).load(i2,j+1UL) );
+ SIMDType xmm8( (~C).load(i3,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i2, j , xmm3 );
+ (~C).store( i3, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i1, j+1UL, xmm6 );
+ (~C).store( i2, j+1UL, xmm7 );
+ (~C).store( i3, j+1UL, xmm8 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+ SIMDType xmm3( (~C).load(i2,j) );
+ SIMDType xmm4( (~C).load(i3,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ (~C).store( i2, j, xmm3 );
+ (~C).store( i3, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+ SIMDType xmm5( (~C).load(i ,j+2UL) );
+ SIMDType xmm6( (~C).load(i1,j+2UL) );
+ SIMDType xmm7( (~C).load(i ,j+3UL) );
+ SIMDType xmm8( (~C).load(i1,j+3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ (~C).store( i , j+2UL, xmm5 );
+ (~C).store( i1, j+2UL, xmm6 );
+ (~C).store( i , j+3UL, xmm7 );
+ (~C).store( i1, j+3UL, xmm8 );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices (default)*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices*****************************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ assign( C, B );
+ trmm( C, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ assign( C, A );
+ trmm( C, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ }
+ else {
+ gemm( C, A, B, ET(1), ET(0) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-transpose dense matrix multiplication to a
+ // sparse matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // transpose dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to row-major matrices**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication to a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a row-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,false>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a transpose dense matrix-
+ // transpose dense matrix multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value ) ||
+ ( C.rows() * C.columns() < TDMATTDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( C, A, B );
+ else
+ selectBlasAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/general)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general transpose dense matrix-general transpose
+ // dense matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general transpose dense matrix-
+ // general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ for( size_t k=kbegin; k<kend; ++k )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? k : k+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) += A(i ,k) * B(k,j);
+ C(i+1UL,j) += A(i+1UL,k) * B(k,j);
+ }
+ if( ipos < iend ) {
+ C(ipos,j) += A(ipos,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/diagonal)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a general transpose dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a general transpose dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) += A(i ,j) * B(j,j);
+ C(i+1UL,j) += A(i+1UL,j) * B(j,j);
+ }
+ if( ipos < iend ) {
+ C(ipos,j) += A(ipos,j) * B(j,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/general)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal transpose dense matrix-general transpose
+ // dense matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal transpose dense
+ // matrix-general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) += A(i ,i ) * B(i ,j);
+ C(i+1UL,j) += A(i+1UL,i+1UL) * B(i+1UL,j);
+ }
+ if( ipos < iend ) {
+ C(ipos,j) += A(ipos,ipos) * B(ipos,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/diagonal)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a diagonal transpose dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a diagonal transpose dense
+ // matrix-diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) += A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (small matrices)*********
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( ~C, A * tmp );
+ }
+ else if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( ~C, tmp * B );
+ }
+ else if( B.rows() * B.columns() <= A.rows() * A.columns() ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( ~C, A * tmp );
+ }
+ else {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( ~C, tmp * B );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (small matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j) );
+ SIMDType xmm5( (~C).load(i+SIMDSIZE*4UL,j) );
+ SIMDType xmm6( (~C).load(i+SIMDSIZE*5UL,j) );
+ SIMDType xmm7( (~C).load(i+SIMDSIZE*6UL,j) );
+ SIMDType xmm8( (~C).load(i+SIMDSIZE*7UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ (~C).store( i+SIMDSIZE*4UL, j, xmm5 );
+ (~C).store( i+SIMDSIZE*5UL, j, xmm6 );
+ (~C).store( i+SIMDSIZE*6UL, j, xmm7 );
+ (~C).store( i+SIMDSIZE*7UL, j, xmm8 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j ) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j ) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i+SIMDSIZE ,j+1UL) );
+ SIMDType xmm7( (~C).load(i+SIMDSIZE*2UL,j+1UL) );
+ SIMDType xmm8( (~C).load(i+SIMDSIZE*3UL,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE , j , xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j , xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i+SIMDSIZE , j+1UL, xmm6 );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, xmm7 );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, xmm8 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i+SIMDSIZE, j+1UL, xmm4 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+1UL, xmm2 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1( (~C)(i,j ) );
+ ElementType value2( (~C)(i,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) = value1;
+ (~C)(i,j+1UL) = value2;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (large matrices)*********
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ selectSmallAddAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (large matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_JBLOCK_SIZE, N ) );
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i2,j ) );
+ SIMDType xmm4( (~C).load(i3,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i1,j+1UL) );
+ SIMDType xmm7( (~C).load(i2,j+1UL) );
+ SIMDType xmm8( (~C).load(i3,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i2, j , xmm3 );
+ (~C).store( i3, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i1, j+1UL, xmm6 );
+ (~C).store( i2, j+1UL, xmm7 );
+ (~C).store( i3, j+1UL, xmm8 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+ SIMDType xmm3( (~C).load(i2,j) );
+ SIMDType xmm4( (~C).load(i3,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ (~C).store( i2, j, xmm3 );
+ (~C).store( i3, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+ SIMDType xmm5( (~C).load(i ,j+2UL) );
+ SIMDType xmm6( (~C).load(i1,j+2UL) );
+ SIMDType xmm7( (~C).load(i ,j+3UL) );
+ SIMDType xmm8( (~C).load(i1,j+3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ (~C).store( i , j+2UL, xmm5 );
+ (~C).store( i1, j+2UL, xmm6 );
+ (~C).store( i , j+3UL, xmm7 );
+ (~C).store( i1, j+3UL, xmm8 );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices (default)**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices********************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based addition assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ addAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ addAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to row-major matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a transpose
+ // dense matrix-transpose dense matrix multiplication expression to a row-major matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,false>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a transpose dense matrix-
+ // transpose dense matrix multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ if( ( IsDiagonal<MT4>::value ) ||
+ ( C.rows() * C.columns() < TDMATTDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( C, A, B );
+ else
+ selectBlasSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/general)**************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general transpose dense matrix-general transpose
+ // dense matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general transpose dense
+ // matrix-general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ for( size_t k=kbegin; k<kend; ++k )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? k : k+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) -= A(i ,k) * B(k,j);
+ C(i+1UL,j) -= A(i+1UL,k) * B(k,j);
+ }
+ if( ipos < iend ) {
+ C(ipos,j) -= A(ipos,k) * B(k,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/diagonal)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a general transpose dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a general transpose dense
+ // matrix-diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) -= A(i ,j) * B(j,j);
+ C(i+1UL,j) -= A(i+1UL,j) * B(j,j);
+ }
+ if( ipos < iend ) {
+ C(ipos,j) -= A(ipos,j) * B(j,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/general)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal transpose dense matrix-general transpose
+ // dense matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal transpose dense
+ // matrix-general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) -= A(i ,i ) * B(i ,j);
+ C(i+1UL,j) -= A(i+1UL,i+1UL) * B(i+1UL,j);
+ }
+ if( ipos < iend ) {
+ C(ipos,j) -= A(ipos,ipos) * B(ipos,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/diagonal)************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a diagonal transpose dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a diagonal transpose dense
+ // matrix-diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) -= A(i,i) * B(i,i);
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (small matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( ~C, A * tmp );
+ }
+ else if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( ~C, tmp * B );
+ }
+ else if( B.rows() * B.columns() <= A.rows() * A.columns() ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( ~C, A * tmp );
+ }
+ else {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( ~C, tmp * B );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (small matrices)***
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j) );
+ SIMDType xmm5( (~C).load(i+SIMDSIZE*4UL,j) );
+ SIMDType xmm6( (~C).load(i+SIMDSIZE*5UL,j) );
+ SIMDType xmm7( (~C).load(i+SIMDSIZE*6UL,j) );
+ SIMDType xmm8( (~C).load(i+SIMDSIZE*7UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 - A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 - A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 - A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 - A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 - A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 - A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ (~C).store( i+SIMDSIZE*4UL, j, xmm5 );
+ (~C).store( i+SIMDSIZE*5UL, j, xmm6 );
+ (~C).store( i+SIMDSIZE*6UL, j, xmm7 );
+ (~C).store( i+SIMDSIZE*7UL, j, xmm8 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j ) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j ) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i+SIMDSIZE ,j+1UL) );
+ SIMDType xmm7( (~C).load(i+SIMDSIZE*2UL,j+1UL) );
+ SIMDType xmm8( (~C).load(i+SIMDSIZE*3UL,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a3 * b1;
+ xmm4 = xmm4 - a4 * b1;
+ xmm5 = xmm5 - a1 * b2;
+ xmm6 = xmm6 - a2 * b2;
+ xmm7 = xmm7 - a3 * b2;
+ xmm8 = xmm8 - a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE , j , xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j , xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i+SIMDSIZE , j+1UL, xmm6 );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, xmm7 );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, xmm8 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE ,j) );
+ SIMDType xmm3( (~C).load(i+SIMDSIZE*2UL,j) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE*3UL,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 - A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 - A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE , j, xmm2 );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i+SIMDSIZE,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a1 * b2;
+ xmm4 = xmm4 - a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i+SIMDSIZE, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i+SIMDSIZE, j+1UL, xmm4 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i+SIMDSIZE,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i+SIMDSIZE, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1( (~C).load(i,j ) );
+ SIMDType xmm2( (~C).load(i,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 - a1 * set( B(k,j ) );
+ xmm2 = xmm2 - a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , xmm1 );
+ (~C).store( i, j+1UL, xmm2 );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 - A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1( (~C)(i,j ) );
+ ElementType value2( (~C)(i,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 -= A(i,k) * B(k,j );
+ value2 -= A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) = value1;
+ (~C)(i,j+1UL) = value2;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value -= A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (large matrices)******
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix. This
+ // kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
+ {
+ selectSmallSubAssignKernel( ~C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (large matrices)***
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT5>::value );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_JBLOCK_SIZE, N ) );
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i2,j ) );
+ SIMDType xmm4( (~C).load(i3,j ) );
+ SIMDType xmm5( (~C).load(i ,j+1UL) );
+ SIMDType xmm6( (~C).load(i1,j+1UL) );
+ SIMDType xmm7( (~C).load(i2,j+1UL) );
+ SIMDType xmm8( (~C).load(i3,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a3 * b1;
+ xmm4 = xmm4 - a4 * b1;
+ xmm5 = xmm5 - a1 * b2;
+ xmm6 = xmm6 - a2 * b2;
+ xmm7 = xmm7 - a3 * b2;
+ xmm8 = xmm8 - a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i2, j , xmm3 );
+ (~C).store( i3, j , xmm4 );
+ (~C).store( i , j+1UL, xmm5 );
+ (~C).store( i1, j+1UL, xmm6 );
+ (~C).store( i2, j+1UL, xmm7 );
+ (~C).store( i3, j+1UL, xmm8 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+ SIMDType xmm3( (~C).load(i2,j) );
+ SIMDType xmm4( (~C).load(i3,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i1,k) * b1;
+ xmm3 = xmm3 - A.load(i2,k) * b1;
+ xmm4 = xmm4 - A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ (~C).store( i2, j, xmm3 );
+ (~C).store( i3, j, xmm4 );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+ SIMDType xmm5( (~C).load(i ,j+2UL) );
+ SIMDType xmm6( (~C).load(i1,j+2UL) );
+ SIMDType xmm7( (~C).load(i ,j+3UL) );
+ SIMDType xmm8( (~C).load(i1,j+3UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a1 * b2;
+ xmm4 = xmm4 - a2 * b2;
+ xmm5 = xmm5 - a1 * b3;
+ xmm6 = xmm6 - a2 * b3;
+ xmm7 = xmm7 - a1 * b4;
+ xmm8 = xmm8 - a2 * b4;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ (~C).store( i , j+2UL, xmm5 );
+ (~C).store( i1, j+2UL, xmm6 );
+ (~C).store( i , j+3UL, xmm7 );
+ (~C).store( i1, j+3UL, xmm8 );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j ) );
+ SIMDType xmm2( (~C).load(i1,j ) );
+ SIMDType xmm3( (~C).load(i ,j+1UL) );
+ SIMDType xmm4( (~C).load(i1,j+1UL) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 - a1 * b1;
+ xmm2 = xmm2 - a2 * b1;
+ xmm3 = xmm3 - a1 * b2;
+ xmm4 = xmm4 - a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 );
+ (~C).store( i1, j , xmm2 );
+ (~C).store( i , j+1UL, xmm3 );
+ (~C).store( i1, j+1UL, xmm4 );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i ,j) );
+ SIMDType xmm2( (~C).load(i1,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i ,k) * b1;
+ xmm2 = xmm2 - A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 );
+ (~C).store( i1, j, xmm2 );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1( (~C).load(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 - A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, xmm1 );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value( (~C)(i,j) );
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value -= A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense matrices (default)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectLargeSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subraction assignment to dense matrices******************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based subraction assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function performs the transpose dense matrix-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ subAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(1) );
+ subAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(-1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to row-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a transpose dense matrix-transpose dense
+ // matrix multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // transpose dense matrix-transpose dense matrix multiplication expression to a row-major
+ // matrix. Due to the explicit application of the SFINAE principle this function can only
+ // be selected by the compiler in case the symmetry of either of the two matrix operands
+ // can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,false>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-transpose dense matrix multiplication to a
+ // dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( rhs.lhs_.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-transpose dense matrix multiplication
+ // to a sparse matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-transpose dense matrix multiplication expression to a sparse matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to row-major matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication to a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a transpose
+ // dense matrix-transpose dense matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,false>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to row-major matrices*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a transpose dense matrix-transpose dense
+ // matrix multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // transpose dense matrix-transpose dense matrix multiplication expression to a row-major
+ // matrix. Due to the explicit application of the SFINAE principle this function can only be
+ // selected by the compiler in case the symmetry of either of the two matrix operands can be
+ // exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,false>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense
+ // matrix. Due to the explicit application of the SFINAE principle, this function can
+ // only be selected by the compiler in case either of the two matrix operands requires
+ // an intermediate evaluation and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || rhs.lhs_.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to row-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a transpose dense matrix-transpose dense
+ // matrix multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // transpose dense matrix-transpose dense matrix multiplication expression to a row-major
+ // matrix. Due to the explicit application of the SFINAE principle this function can only be
+ // selected by the compiler in case the symmetry of either of the two matrix operands can be
+ // exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,false>& lhs, const TDMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DMATSCALARMULTEXPR SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Expression object for scaled transpose dense matrix-transpose dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// This specialization of the DMatScalarMultExpr class represents the compile time expression
+// for scaled multiplications between two column-major dense matrices.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar value
+class DMatScalarMultExpr< TDMatTDMatMultExpr<MT1,MT2>, ST, true >
+ : public DenseMatrix< DMatScalarMultExpr< TDMatTDMatMultExpr<MT1,MT2>, ST, true >, true >
+ , private MatScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef TDMatTDMatMultExpr<MT1,MT2> MMM; //!< Type of the dense matrix multiplication expression.
+ typedef ResultType_<MMM> RES; //!< Result type of the dense matrix multiplication expression.
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the target matrix is row-major and either of the two
+ matrix operands is symmetric, \a value is set to 1 and an optimized evaluation
+ strategy is selected. Otherwise \a value is set to 0 and the default strategy is
+ chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsRowMajorMatrix<T1>::value &&
+ ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the types of all three involved matrices and the scalar type are suited for a BLAS
+ kernel, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T2>::value && !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ !( IsBuiltin< ElementType_<T1> >::value && IsComplex<T4>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all four involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3>
+ , T4 >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T2> >::value &&
+ HasSIMDMult< ElementType_<T3>, ElementType_<T3> >::value };
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DMatScalarMultExpr<MMM,ST,true> This; //!< Type of this DMatScalarMultExpr instance.
+ typedef MultTrait_<RES,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef const TDMatTDMatMultExpr<MT1,MT2> LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT1>::value &&
+ MT1::simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable<ET1,ET2,ST>::value &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DMatScalarMultExpr class.
+ //
+ // \param matrix The left-hand side dense matrix of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DMatScalarMultExpr( const MMM& matrix, ST scalar )
+ : matrix_( matrix ) // Left-hand side dense matrix of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < matrix_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < matrix_.columns(), "Invalid column access index" );
+ return matrix_(i,j) * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= matrix_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= matrix_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const {
+ return matrix_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const {
+ return matrix_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense matrix operand.
+ //
+ // \return The left-hand side dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return matrix_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const {
+ return matrix_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return matrix_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const {
+ return matrix_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const {
+ RightOperand_<MMM> B( matrix_.rightOperand() );
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( rows() * columns() < TDMATTDMATMULT_THRESHOLD ) ) &&
+ ( B.columns() > SMP_TDMATTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand matrix_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*!\brief Assignment of a scaled transpose dense matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*!\brief Selection of the kernel for an assignment of a scaled transpose dense matrix-
+ // transpose dense matrix multiplication to a dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value ) ||
+ ( C.rows() * C.columns() < TDMATTDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( C, A, B, scalar );
+ else
+ selectBlasAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (general/general)**************************************
+ /*!\brief Default assignment of a scaled general transpose dense matrix-general transpose
+ // dense matrix multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general transpose dense matrix-
+ // general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( K ) );
+ BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
+
+ if( IsStrictlyTriangular<MT5>::value && kbegin == kend ) {
+ for( size_t i=0UL; i<M; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ continue;
+ }
+
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? kbegin+1UL : kbegin )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? kbegin : kbegin+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value && IsLower<MT5>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ else if( IsStrictlyLower<MT4>::value ) {
+ reset( C(0UL,j) );
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) = A(i,kbegin) * B(kbegin,j);
+ }
+ if( IsUpper<MT4>::value && IsUpper<MT5>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ else if( IsStrictlyUpper<MT4>::value ) {
+ reset( C(M-1UL,j) );
+ }
+ }
+
+ for( size_t k=kbegin+1UL; k<kend; ++k )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? k+1UL : k )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? k-1UL : k )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) += A(i,k) * B(k,j);
+ }
+ if( IsUpper<MT4>::value ) {
+ C(iend,j) = A(iend,k) * B(k,j);
+ }
+ }
+
+ {
+ const size_t ibegin( ( IsLower<MT4>::value && IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT4>::value || IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value && IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT4>::value || IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) *= scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (general/diagonal)*************************************
+ /*!\brief Default assignment of a scaled general transpose dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled general transpose dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) = A(i,j) * B(j,j) * scalar;
+ }
+ if( IsUpper<MT4>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/general)*************************************
+ /*!\brief Default assignment of a scaled diagonal transpose dense matrix-general transpose
+ // dense matrix multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal transpose dense matrix-
+ // general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ if( IsLower<MT4>::value ) {
+ for( size_t i=0UL; i<ibegin; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ for( size_t i=ibegin; i<iend; ++i ) {
+ C(i,j) = A(i,i) * B(i,j) * scalar;
+ }
+ if( IsUpper<MT4>::value ) {
+ for( size_t i=iend; i<M; ++i ) {
+ reset( C(i,j) );
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (diagonal/diagonal)************************************
+ /*!\brief Default assignment of a scaled diagonal transpose dense matrix-diagonal transpose
+ // dense matrix multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment of a scaled diagonal transpose dense matrix-
+ // diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ reset( C );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) = A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*!\brief Default assignment of a small scaled transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (small matrices)******************
+ /*!\brief Vectorized default assignment of a small scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled transpose dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( ~C, A * tmp * scalar );
+ }
+ else if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( ~C, tmp * B * scalar );
+ }
+ else if( B.rows() * B.columns() <= A.rows() * A.columns() ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ assign( ~C, A * tmp * scalar );
+ }
+ else {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( ~C, tmp * B * scalar );
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (small matrices)***************
+ /*!\brief Vectorized default assignment of a small scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled transpose dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 * factor );
+ (~C).store( i+SIMDSIZE*4UL, j, xmm5 * factor );
+ (~C).store( i+SIMDSIZE*5UL, j, xmm6 * factor );
+ (~C).store( i+SIMDSIZE*6UL, j, xmm7 * factor );
+ (~C).store( i+SIMDSIZE*7UL, j, xmm8 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j , xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j , xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j , xmm4 * factor );
+ (~C).store( i , j+1UL, xmm5 * factor );
+ (~C).store( i+SIMDSIZE , j+1UL, xmm6 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, xmm7 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, xmm8 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j , xmm2 * factor );
+ (~C).store( i , j+1UL, xmm3 * factor );
+ (~C).store( i+SIMDSIZE, j+1UL, xmm4 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j, xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , xmm1 * factor );
+ (~C).store( i, j+1UL, xmm2 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) = value1 * scalar;
+ (~C)(i,j+1UL) = value2 * scalar;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) = value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*!\brief Default assignment of a large scaled transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to row-major dense matrices (large matrices)******************
+ /*!\brief Vectorized default assignment of a large scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled transpose dense
+ // matrix-transpose dense matrix multiplication expression to a row-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectSmallAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to column-major dense matrices (large matrices)***************
+ /*!\brief Vectorized default assignment of a large scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment of a scaled transpose dense
+ // matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_JBLOCK_SIZE, N ) );
+
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ reset( (~C)(i,j) );
+ }
+ }
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i2, j , (~C).load(i2,j ) + xmm3 * factor );
+ (~C).store( i3, j , (~C).load(i3,j ) + xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm5 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm6 * factor );
+ (~C).store( i2, j+1UL, (~C).load(i2,j+1UL) + xmm7 * factor );
+ (~C).store( i3, j+1UL, (~C).load(i3,j+1UL) + xmm8 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) + xmm2 * factor );
+ (~C).store( i2, j, (~C).load(i2,j) + xmm3 * factor );
+ (~C).store( i3, j, (~C).load(i3,j) + xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm4 * factor );
+ (~C).store( i , j+2UL, (~C).load(i ,j+2UL) + xmm5 * factor );
+ (~C).store( i1, j+2UL, (~C).load(i1,j+2UL) + xmm6 * factor );
+ (~C).store( i , j+3UL, (~C).load(i ,j+3UL) + xmm7 * factor );
+ (~C).store( i1, j+3UL, (~C).load(i1,j+3UL) + xmm8 * factor );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm4 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) + xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices (default)*******************************************
+ /*!\brief Default assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense matrices*****************************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ assign( C, B );
+ trmm( C, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ assign( C, A );
+ trmm( C, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ }
+ else {
+ gemm( C, A, B, ET(scalar), ET(0) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*!\brief Assignment of a scaled transpose dense matrix-transpose dense matrix multiplication
+ // to a sparse matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // matrix-transpose dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Restructuring assignment to row-major matrices**********************************************
+ /*!\brief Restructuring assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication to a row-major matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a row-major matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,false>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ assign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ assign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ assign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*!\brief Addition assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectAddAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*!\brief Selection of the kernel for an addition assignment of a scaled transpose dense
+ // matrix-transpose dense matrix multiplication to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value ) ||
+ ( C.rows() * C.columns() < TDMATTDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( C, A, B, scalar );
+ else
+ selectBlasAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/general)*****************************
+ /*!\brief Default addition assignment of a scaled general transpose dense matrix-general
+ // transpose dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general transpose
+ // dense matrix-general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const ResultType tmp( serial( A * B * scalar ) );
+ addAssign( C, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (general/diagonal)****************************
+ /*!\brief Default addition assignment of a scaled general transpose dense matrix-diagonal
+ // transpose dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled general transpose
+ // dense matrix-diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) += A(i ,j) * B(j,j) * scalar;
+ C(i+1UL,j) += A(i+1UL,j) * B(j,j) * scalar;
+ }
+ if( ipos < iend ) {
+ C(ipos,j) += A(ipos,j) * B(j,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/general)****************************
+ /*!\brief Default addition assignment of a scaled diagonal transpose dense matrix-general
+ // transpose dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal transpose
+ // dense matrix-general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) += A(i ,i ) * B(i ,j) * scalar;
+ C(i+1UL,j) += A(i+1UL,i+1UL) * B(i+1UL,j) * scalar;
+ }
+ if( ipos < iend ) {
+ C(ipos,j) += A(ipos,ipos) * B(ipos,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (diagonal/diagonal)***************************
+ /*!\brief Default addition assignment of a scaled diagonal transpose dense matrix-diagonal
+ // transpose dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment of a scaled diagonal transpose
+ // dense matrix-diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) += A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*!\brief Default addition assignment of a small scaled transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (small matrices)*********
+ /*!\brief Vectorized default addition assignment of a small scaled transpose dense matrix-
+ // transpose dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a row-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( ~C, A * tmp * scalar );
+ }
+ else if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( ~C, tmp * B * scalar );
+ }
+ else if( B.rows() * B.columns() <= A.rows() * A.columns() ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ addAssign( ~C, A * tmp * scalar );
+ }
+ else {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( ~C, tmp * B * scalar );
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (small matrices)******
+ /*!\brief Vectorized default addition assignment of a small scaled transpose dense matrix-
+ // transpose dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, (~C).load(i+SIMDSIZE ,j) + xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, (~C).load(i+SIMDSIZE*2UL,j) + xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, (~C).load(i+SIMDSIZE*3UL,j) + xmm4 * factor );
+ (~C).store( i+SIMDSIZE*4UL, j, (~C).load(i+SIMDSIZE*4UL,j) + xmm5 * factor );
+ (~C).store( i+SIMDSIZE*5UL, j, (~C).load(i+SIMDSIZE*5UL,j) + xmm6 * factor );
+ (~C).store( i+SIMDSIZE*6UL, j, (~C).load(i+SIMDSIZE*6UL,j) + xmm7 * factor );
+ (~C).store( i+SIMDSIZE*7UL, j, (~C).load(i+SIMDSIZE*7UL,j) + xmm8 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j , (~C).load(i+SIMDSIZE ,j ) + xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j , (~C).load(i+SIMDSIZE*2UL,j ) + xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j , (~C).load(i+SIMDSIZE*3UL,j ) + xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm5 * factor );
+ (~C).store( i+SIMDSIZE , j+1UL, (~C).load(i+SIMDSIZE ,j+1UL) + xmm6 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, (~C).load(i+SIMDSIZE*2UL,j+1UL) + xmm7 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, (~C).load(i+SIMDSIZE*3UL,j+1UL) + xmm8 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, (~C).load(i+SIMDSIZE ,j) + xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, (~C).load(i+SIMDSIZE*2UL,j) + xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, (~C).load(i+SIMDSIZE*3UL,j) + xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j , (~C).load(i+SIMDSIZE,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i+SIMDSIZE, j+1UL, (~C).load(i+SIMDSIZE,j+1UL) + xmm4 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j, (~C).load(i+SIMDSIZE,j) + xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) + xmm1 * factor );
+ (~C).store( i, j+1UL, (~C).load(i,j+1UL) + xmm2 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) += value1 * scalar;
+ (~C)(i,j+1UL) += value2 * scalar;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*!\brief Default addition assignment of a large scaled transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to row-major dense matrices (large matrices)*********
+ /*!\brief Vectorized default addition assignment of a large scaled transpose dense matrix-
+ // transpose dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a row-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectSmallAddAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to column-major dense matrices (large matrices)******
+ /*!\brief Vectorized default addition assignment of a large scaled transpose dense matrix-
+ // transpose dense matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_JBLOCK_SIZE, N ) );
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i2, j , (~C).load(i2,j ) + xmm3 * factor );
+ (~C).store( i3, j , (~C).load(i3,j ) + xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm5 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm6 * factor );
+ (~C).store( i2, j+1UL, (~C).load(i2,j+1UL) + xmm7 * factor );
+ (~C).store( i3, j+1UL, (~C).load(i3,j+1UL) + xmm8 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) + xmm2 * factor );
+ (~C).store( i2, j, (~C).load(i2,j) + xmm3 * factor );
+ (~C).store( i3, j, (~C).load(i3,j) + xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm4 * factor );
+ (~C).store( i , j+2UL, (~C).load(i ,j+2UL) + xmm5 * factor );
+ (~C).store( i1, j+2UL, (~C).load(i1,j+2UL) + xmm6 * factor );
+ (~C).store( i , j+3UL, (~C).load(i ,j+3UL) + xmm7 * factor );
+ (~C).store( i1, j+3UL, (~C).load(i1,j+3UL) + xmm8 * factor );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) + xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) + xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) + xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) + xmm4 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) + xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) + xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, (~C).load(i,j) + xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) += value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices (default)**********************************
+ /*!\brief Default addition assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // scaled transpose dense matrix-transpose dense matrix multiplication expression to a dense
+ // matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeAddAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense matrices********************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based addition assignment of a scaled transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ addAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ addAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to row-major matrices*************************************
+ /*!\brief Restructuring addition assignment of a scaled transpose dense matrix-transpose dense
+ // matrix multiplication to a row-major matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a row-major
+ // matrix. Due to the explicit application of the SFINAE principle this function can only be
+ // selected by the compiler in case the symmetry of either of the two matrix operands can be
+ // exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,false>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ addAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ addAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ addAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*!\brief Subtraction assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ DMatScalarMultExpr::selectSubAssignKernel( ~lhs, A, B, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*!\brief Selection of the kernel for a subtraction assignment of a scaled transpose dense
+ // matrix-transpose dense matrix multiplication to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT4>::value ) ||
+ ( C.rows() * C.columns() < TDMATTDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( C, A, B, scalar );
+ else
+ selectBlasSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/general)**************************
+ /*!\brief Default subtraction assignment of a scaled general transpose dense matrix-general
+ // transpose dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general transpose
+ // dense matrix-general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const ResultType tmp( serial( A * B * scalar ) );
+ subAssign( C, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (general/diagonal)*************************
+ /*!\brief Default subtraction assignment of a scaled general transpose dense matrix-diagonal
+ // transpose dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled general transpose
+ // dense matrix-diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< Not< IsDiagonal<MT4> >, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) -= A(i ,j) * B(j,j) * scalar;
+ C(i+1UL,j) -= A(i+1UL,j) * B(j,j) * scalar;
+ }
+ if( ipos < iend ) {
+ C(ipos,j) -= A(ipos,j) * B(j,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/general)*************************
+ /*!\brief Default subtraction assignment of a scaled diagonal transpose dense matrix-general
+ // transpose dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal transpose
+ // dense matrix-general transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, Not< IsDiagonal<MT5> > > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT5>::value )
+ ?( IsStrictlyLower<MT5>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-2) ) );
+
+ for( size_t i=ibegin; i<ipos; i+=2UL ) {
+ C(i ,j) -= A(i ,i ) * B(i ,j) * scalar;
+ C(i+1UL,j) -= A(i+1UL,i+1UL) * B(i+1UL,j) * scalar;
+ }
+ if( ipos < iend ) {
+ C(ipos,j) -= A(ipos,ipos) * B(ipos,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (diagonal/diagonal)************************
+ /*!\brief Default subtraction assignment of a scaled diagonal transpose dense matrix-diagonal
+ // transpose dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a scaled diagonal transpose
+ // dense matrix-diagonal transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< And< IsDiagonal<MT4>, IsDiagonal<MT5> > >
+ selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ C(i,i) -= A(i,i) * B(i,i) * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*!\brief Default subtraction assignment of a small scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (small matrices)******
+ /*!\brief Default subtraction assignment of a small scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a row-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT4 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT5 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT5> );
+
+ if( IsResizable<MT4>::value && !IsResizable<MT5>::value ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( ~C, A * tmp * scalar );
+ }
+ else if( !IsResizable<MT4>::value && IsResizable<MT5>::value ) {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( ~C, tmp * B * scalar );
+ }
+ else if( B.rows() * B.columns() <= A.rows() * A.columns() ) {
+ const OppositeType_<MT5> tmp( serial( B ) );
+ subAssign( ~C, A * tmp * scalar );
+ }
+ else {
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( ~C, tmp * B * scalar );
+ }
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (small matrices)***
+ /*!\brief Default subtraction assignment of a small scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for small matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectSmallSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const size_t ipos( remainder ? ( M & size_t(-SIMDSIZE) ) : M );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( M - ( M % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*7UL) < ipos; i+=SIMDSIZE*8UL ) {
+ for( size_t j=0UL; j<N; ++j )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper<MT5>::value ? j : j+1UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j : j+1UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*8UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ xmm5 = xmm5 + A.load(i+SIMDSIZE*4UL,k) * b1;
+ xmm6 = xmm6 + A.load(i+SIMDSIZE*5UL,k) * b1;
+ xmm7 = xmm7 + A.load(i+SIMDSIZE*6UL,k) * b1;
+ xmm8 = xmm8 + A.load(i+SIMDSIZE*7UL,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, (~C).load(i+SIMDSIZE ,j) - xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, (~C).load(i+SIMDSIZE*2UL,j) - xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, (~C).load(i+SIMDSIZE*3UL,j) - xmm4 * factor );
+ (~C).store( i+SIMDSIZE*4UL, j, (~C).load(i+SIMDSIZE*4UL,j) - xmm5 * factor );
+ (~C).store( i+SIMDSIZE*5UL, j, (~C).load(i+SIMDSIZE*5UL,j) - xmm6 * factor );
+ (~C).store( i+SIMDSIZE*6UL, j, (~C).load(i+SIMDSIZE*6UL,j) - xmm7 * factor );
+ (~C).store( i+SIMDSIZE*7UL, j, (~C).load(i+SIMDSIZE*7UL,j) - xmm8 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*4UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE ,k) );
+ const SIMDType a3( A.load(i+SIMDSIZE*2UL,k) );
+ const SIMDType a4( A.load(i+SIMDSIZE*3UL,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j , (~C).load(i+SIMDSIZE ,j ) - xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j , (~C).load(i+SIMDSIZE*2UL,j ) - xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j , (~C).load(i+SIMDSIZE*3UL,j ) - xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm5 * factor );
+ (~C).store( i+SIMDSIZE , j+1UL, (~C).load(i+SIMDSIZE ,j+1UL) - xmm6 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j+1UL, (~C).load(i+SIMDSIZE*2UL,j+1UL) - xmm7 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j+1UL, (~C).load(i+SIMDSIZE*3UL,j+1UL) - xmm8 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE ,k) * b1;
+ xmm3 = xmm3 + A.load(i+SIMDSIZE*2UL,k) * b1;
+ xmm4 = xmm4 + A.load(i+SIMDSIZE*3UL,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE , j, (~C).load(i+SIMDSIZE ,j) - xmm2 * factor );
+ (~C).store( i+SIMDSIZE*2UL, j, (~C).load(i+SIMDSIZE*2UL,j) - xmm3 * factor );
+ (~C).store( i+SIMDSIZE*3UL, j, (~C).load(i+SIMDSIZE*3UL,j) - xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( ( IsLower<MT4>::value )
+ ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) ) )
+ :( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL ) )
+ :( IsLower<MT4>::value ? min( i+SIMDSIZE*2UL, K ) : K ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i+SIMDSIZE,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j , (~C).load(i+SIMDSIZE,j ) - xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm3 * factor );
+ (~C).store( i+SIMDSIZE, j+1UL, (~C).load(i+SIMDSIZE,j+1UL) - xmm4 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i+SIMDSIZE,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i+SIMDSIZE, j, (~C).load(i+SIMDSIZE,j) - xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i,k) );
+ xmm1 = xmm1 + a1 * set( B(k,j ) );
+ xmm2 = xmm2 + a1 * set( B(k,j+1UL) );
+ }
+
+ (~C).store( i, j , (~C).load(i,j ) - xmm1 * factor );
+ (~C).store( i, j+1UL, (~C).load(i,j+1UL) - xmm2 * factor );
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ xmm1 = xmm1 + A.load(i,k) * set( B(k,j) );
+ }
+
+ (~C).store( i, j, (~C).load(i,j) - xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<M; ++i )
+ {
+ size_t j( 0UL );
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+ const size_t kend( ( IsUpper<MT5>::value )
+ ?( IsStrictlyUpper<MT5>::value ? j+1UL : j+2UL )
+ :( K ) );
+
+ ElementType value1 = ElementType();
+ ElementType value2 = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value1 += A(i,k) * B(k,j );
+ value2 += A(i,k) * B(k,j+1UL);
+ }
+
+ (~C)(i,j ) -= value1 * scalar;
+ (~C)(i,j+1UL) -= value2 * scalar;
+ }
+
+ if( j < N )
+ {
+ const size_t kbegin( ( IsLower<MT5>::value )
+ ?( ( IsUpper<MT4>::value )
+ ?( max( i, ( IsStrictlyLower<MT5>::value ? j+1UL : j ) ) )
+ :( IsStrictlyLower<MT5>::value ? j+1UL : j ) )
+ :( IsUpper<MT4>::value ? i : 0UL ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<K; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) -= value * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*!\brief Default subtraction assignment of a large scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to row-major dense matrices (large matrices)******
+ /*!\brief Default subtraction assignment of a large scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a row-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectSmallSubAssignKernel( ~C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to column-major dense matrices (large matrices)***
+ /*!\brief Default subtraction assignment of a large scaled transpose dense matrix-transpose
+ // dense matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a column-major dense matrix.
+ // This kernel is optimized for large matrices.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<MT3,MT4,MT5,ST2> >
+ selectLargeSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( B.columns() );
+ const size_t K( A.columns() );
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ const SIMDType factor( set( scalar ) );
+
+ for( size_t ii=0UL; ii<M; ii+=TDMATTDMATMULT_IBLOCK_SIZE )
+ {
+ const size_t iend( min( ii+TDMATTDMATMULT_IBLOCK_SIZE, M ) );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % SIMDSIZE ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t jj=0UL; jj<N; jj+=TDMATTDMATMULT_JBLOCK_SIZE )
+ {
+ const size_t jend( min( jj+TDMATTDMATMULT_JBLOCK_SIZE, N ) );
+
+ for( size_t kk=0UL; kk<K; kk+=TDMATTDMATMULT_KBLOCK_SIZE )
+ {
+ const size_t ktmp( min( kk+TDMATTDMATMULT_KBLOCK_SIZE, K ) );
+
+ size_t i( ii );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+
+ size_t j( jj );
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType a3( A.load(i2,k) );
+ const SIMDType a4( A.load(i3,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a3 * b1;
+ xmm4 = xmm4 + a4 * b1;
+ xmm5 = xmm5 + a1 * b2;
+ xmm6 = xmm6 + a2 * b2;
+ xmm7 = xmm7 + a3 * b2;
+ xmm8 = xmm8 + a4 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) - xmm2 * factor );
+ (~C).store( i2, j , (~C).load(i2,j ) - xmm3 * factor );
+ (~C).store( i3, j , (~C).load(i3,j ) - xmm4 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm5 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) - xmm6 * factor );
+ (~C).store( i2, j+1UL, (~C).load(i2,j+1UL) - xmm7 * factor );
+ (~C).store( i3, j+1UL, (~C).load(i3,j+1UL) - xmm8 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ xmm3 = xmm3 + A.load(i2,k) * b1;
+ xmm4 = xmm4 + A.load(i3,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) - xmm2 * factor );
+ (~C).store( i2, j, (~C).load(i2,j) - xmm3 * factor );
+ (~C).store( i3, j, (~C).load(i3,j) - xmm4 * factor );
+ }
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL )
+ {
+ const size_t i1( i+SIMDSIZE );
+
+ size_t j( jj );
+
+ for( ; (j+4UL) <= jend; j+=4UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+4UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ const SIMDType b3( set( B(k,j+2UL) ) );
+ const SIMDType b4( set( B(k,j+3UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ xmm5 = xmm5 + a1 * b3;
+ xmm6 = xmm6 + a2 * b3;
+ xmm7 = xmm7 + a1 * b4;
+ xmm8 = xmm8 + a2 * b4;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) - xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) - xmm4 * factor );
+ (~C).store( i , j+2UL, (~C).load(i ,j+2UL) - xmm5 * factor );
+ (~C).store( i1, j+2UL, (~C).load(i1,j+2UL) - xmm6 * factor );
+ (~C).store( i , j+3UL, (~C).load(i ,j+3UL) - xmm7 * factor );
+ (~C).store( i1, j+3UL, (~C).load(i1,j+3UL) - xmm8 * factor );
+ }
+
+ for( ; (j+2UL) <= jend; j+=2UL )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+2UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType a1( A.load(i ,k) );
+ const SIMDType a2( A.load(i1,k) );
+ const SIMDType b1( set( B(k,j ) ) );
+ const SIMDType b2( set( B(k,j+1UL) ) );
+ xmm1 = xmm1 + a1 * b1;
+ xmm2 = xmm2 + a2 * b1;
+ xmm3 = xmm3 + a1 * b2;
+ xmm4 = xmm4 + a2 * b2;
+ }
+
+ (~C).store( i , j , (~C).load(i ,j ) - xmm1 * factor );
+ (~C).store( i1, j , (~C).load(i1,j ) - xmm2 * factor );
+ (~C).store( i , j+1UL, (~C).load(i ,j+1UL) - xmm3 * factor );
+ (~C).store( i1, j+1UL, (~C).load(i1,j+1UL) - xmm4 * factor );
+ }
+
+ if( j < jend )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i ,k) * b1;
+ xmm2 = xmm2 + A.load(i1,k) * b1;
+ }
+
+ (~C).store( i , j, (~C).load(i ,j) - xmm1 * factor );
+ (~C).store( i1, j, (~C).load(i1,j) - xmm2 * factor );
+ }
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ SIMDType xmm1;
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ const SIMDType b1( set( B(k,j) ) );
+ xmm1 = xmm1 + A.load(i,k) * b1;
+ }
+
+ (~C).store( i, j, (~C).load(i,j) - xmm1 * factor );
+ }
+ }
+
+ for( ; remainder && i<iend; ++i )
+ {
+ for( size_t j=jj; j<jend; ++j )
+ {
+ const size_t kbegin( max( ( IsUpper<MT4>::value )?( max( i, kk ) ):( kk ),
+ ( IsLower<MT5>::value )?( max( j, kk ) ):( kk ) ) );
+ const size_t kend ( min( ( IsLower<MT4>::value )?( min( i+1UL, ktmp ) ):( ktmp ),
+ ( IsUpper<MT5>::value )?( j+1UL ):( ktmp ) ) );
+
+ ElementType value = ElementType();
+
+ for( size_t k=kbegin; k<kend; ++k ) {
+ value += A(i,k) * B(k,j);
+ }
+
+ (~C)(i,j) -= value * scalar;
+ }
+ }
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense matrices (default)*******************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // scaled transpose dense matrix-transpose dense matrix multiplication expression to a dense
+ // matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ selectLargeSubAssignKernel( C, A, B, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subraction assignment to dense matrices******************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based subraction assignment of a scaled transpose dense matrix-transpose dense
+ // matrix multiplication (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense matrix-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<MT3,MT4,MT5,ST2> >
+ selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar )
+ {
+ typedef ElementType_<MT3> ET;
+
+ if( IsTriangular<MT4>::value ) {
+ ResultType_<MT3> tmp( serial( B ) );
+ trmm( tmp, A, CblasLeft, ( IsLower<MT4>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ subAssign( C, tmp );
+ }
+ else if( IsTriangular<MT5>::value ) {
+ ResultType_<MT3> tmp( serial( A ) );
+ trmm( tmp, B, CblasRight, ( IsLower<MT5>::value )?( CblasLower ):( CblasUpper ), ET(scalar) );
+ subAssign( C, tmp );
+ }
+ else {
+ gemm( C, A, B, ET(-scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to row-major matrices**********************************
+ /*!\brief Restructuring subtraction assignment of a scaled transpose dense matrix-transpose
+ // dense matrix multiplication to a row-major matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a row-major matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,false>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ subAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ subAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ subAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*!\brief SMP assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL ) {
+ return;
+ }
+ else if( left.columns() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*!\brief SMP assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication to a sparse matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense matrix-transpose dense matrix multiplication expression to a sparse matrix. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to row-major matrices******************************************
+ /*!\brief Restructuring SMP assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication to a row-major matrix (\f$ C=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a scaled
+ // transpose dense matrix-dense matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,false>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ smpAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ smpAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*!\brief SMP addition assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to row-major matrices*********************************
+ /*!\brief Restructuring SMP addition assignment of a scaled transpose dense matrix-transpose
+ // dense matrix multiplication to a row-major matrix (\f$ C+=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // scaled transpose dense matrix-transpose dense matrix multiplication expression to a
+ // row-major matrix. Due to the explicit application of the SFINAE principle this operator
+ // can only be selected by the compiler in case the symmetry of either of the two matrix
+ // operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,false>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAddAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ smpAddAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ smpAddAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*!\brief SMP subtraction assignment of a scaled transpose dense matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a scaled
+ // transpose dense matrix-transpose dense matrix multiplication expression to a dense matrix.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( (~lhs).rows() == 0UL || (~lhs).columns() == 0UL || left.columns() == 0UL ) {
+ return;
+ }
+
+ LT A( left ); // Evaluation of the left-hand side dense matrix operand
+ RT B( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == left.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == right.columns() , "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to row-major matrices******************************
+ /*!\brief Restructuring SMP subtraction assignment of a scaled transpose dense matrix-transpose
+ // dense matrix multiplication to a row-major matrix (\f$ C-=s*A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of
+ // a scaled transpose dense matrix-transpose dense matrix multiplication expression to a
+ // row-major matrix. Due to the explicit application of the SFINAE principle this operator
+ // can only be selected by the compiler in case the symmetry of either of the two matrix
+ // operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,false>& lhs, const DMatScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LeftOperand_<MMM> left ( rhs.matrix_.leftOperand() );
+ RightOperand_<MMM> right( rhs.matrix_.rightOperand() );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpSubAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ );
+ else if( IsSymmetric<MT1>::value )
+ smpSubAssign( ~lhs, trans( left ) * right * rhs.scalar_ );
+ else
+ smpSubAssign( ~lhs, left * trans( right ) * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MMM );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MMM );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of two column-major dense matrices
+// (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side matrix for the multiplication.
+// \param rhs The right-hand side matrix for the multiplication.
+// \return The resulting matrix.
+//
+// This operator represents the multiplication of two column-major dense matrices:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,columnMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current number of columns of \a lhs and the current number of rows of \a rhs
+// don't match, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const TDMatTDMatMultExpr<T1,T2>
+ operator*( const DenseMatrix<T1,true>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TDMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TDMatTDMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TDMatTDMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< TDMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsAligned<MT1>, IsAligned<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TDMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TDMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TDMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TDMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TDMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TDMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatDVecMultExprTrait< TDMatTDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TDMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatSVecMultExprTrait< TDMatTDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TDMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecTDMatMultExprTrait< VT, TDMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTDMatMultExprTrait_< TDVecTDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecTDMatMultExprTrait< VT, TDMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTDMatMultExprTrait_< TSVecTDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TDMatTDMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TDMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TDMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDMatTSMatMultExpr.h b/src/cpu/blaze/math/expressions/TDMatTSMatMultExpr.h
new file mode 100644
index 00000000..1db99c88
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDMatTSMatMultExpr.h
@@ -0,0 +1,2024 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDMatTSMatMultExpr.h
+// \brief Header file for the transpose dense matrix/transpose sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDMATTSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDMATTSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDMATTSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense matrix-transpose sparse matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The TDMatTSMatMultExpr class represents the compile time expression for multiplications between
+// a column-major dense matrix and a column-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TDMatTSMatMultExpr : public DenseMatrix< TDMatTSMatMultExpr<MT1,MT2>, true >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side dense matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side dense matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case all three involved data types are suited for a vectorized computation of the
+ matrix multiplication, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T2>::value &&
+ T1::simdEnabled && T2::simdEnabled &&
+ IsColumnMajorMatrix<T1>::value &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case a vectorized computation of the matrix multiplication is not possible, but a
+ loop-unrolled computation is feasible, the nested \value will be set to 1, otherwise
+ it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !UseVectorizedKernel<T1,T2,T3>::value &&
+ !IsDiagonal<T2>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !IsResizable<ET2>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case neither a vectorized nor optimized computation is possible, the nested \value will
+ be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseVectorizedKernel<T1,T2,T3>::value &&
+ !UseOptimizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDMatTSMatMultExpr<MT1,MT2> This; //!< Type of this TDMatTSMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT1>::value &&
+ MT1::simdEnabled &&
+ HasSIMDAdd<ET1,ET2>::value &&
+ HasSIMDMult<ET1,ET2>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDMatTSMatMultExpr class.
+ //
+ // \param lhs The left-hand side dense matrix operand of the multiplication expression.
+ // \param rhs The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline TDMatTSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose dense matrix operand.
+ //
+ // \return The left-hand side transpose dense matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return lhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( columns() > SMP_TDMATTSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side dense matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-transpose sparse matrix multiplication to a
+ // dense matrix (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // transpose sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense matrix-transpose sparse matrix multiplication
+ // to dense matrices (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose dense matrix-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( Or< IsColumnMajorMatrix<MT3>, IsDiagonal<MT4> >::value ? A.rows() : 64UL );
+
+ reset( C );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t itmp( min( ii+block, A.rows() ) );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+
+ if( IsDiagonal<MT4>::value )
+ {
+ C(j1,j) = A(j1,j1) * element->value();
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ if( isDefault( C(i,j) ) )
+ C(i,j) = A(i,j1) * element->value();
+ else
+ C(i,j) += A(i,j1) * element->value();
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a transpose dense matrix-transpose sparse matrix multiplication
+ // to dense matrices (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the optimized assignment kernel for the transpose dense matrix-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 64UL );
+
+ reset( C );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t itmp( min( ii+block, A.rows() ) );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ const ConstIterator end( B.end(j) );
+ ConstIterator element( B.begin(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j4 : j4+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
+ C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
+ }
+ for( size_t i=ipos; i<iend; ++i ) {
+ C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j) += A(i ,j1) * v1;
+ C(i+1UL,j) += A(i+1UL,j1) * v1;
+ C(i+2UL,j) += A(i+2UL,j1) * v1;
+ C(i+3UL,j) += A(i+3UL,j1) * v1;
+ }
+ for( size_t i=ipos; i<iend; ++i ) {
+ C(i,j) += A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized assignment to column-major dense matrices****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to column-major dense matrices (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized column-major assignment kernel for the transpose dense
+ // matrix-transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<MT3,MT4,MT5> >
+ selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ reset( C );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ const ConstIterator end( B.end(j) );
+ ConstIterator element( B.begin(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j4 : j4+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) + A.load(i,j1) * xmm1 + A.load(i,j2) * xmm2 + A.load(i,j3) * xmm3 + A.load(i,j4) * xmm4 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) + A.load(i,j1) * xmm1 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ C(i,j) += A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense matrix-transpose sparse matrix multiplication to a
+ // sparse matrix (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense matrix-
+ // transpose sparse matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense matrix-transpose sparse matrix multiplication
+ // to a dense matrix (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // matrix-transpose sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to dense matrices (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose dense
+ // matrix-transpose sparse matrix multiplication to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( Or< IsColumnMajorMatrix<MT3>, IsDiagonal<MT4> >::value ? A.rows() : 64UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t itmp( min( ii+block, A.rows() ) );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+
+ if( IsDiagonal<MT4>::value )
+ {
+ C(j1,j) += A(j1,j1) * element->value();
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j) += A(i ,j1) * element->value();
+ C(i+1UL,j) += A(i+1UL,j1) * element->value();
+ C(i+2UL,j) += A(i+2UL,j1) * element->value();
+ C(i+3UL,j) += A(i+3UL,j1) * element->value();
+ }
+ for( size_t i=ipos; i<iend; ++i ) {
+ C(i,j) += A(i,j1) * element->value();
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to dense matrices (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the optimized addition assignment kernel for the transpose dense
+ // matrix-transpose sparse matrix multiplication to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 64UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t itmp( min( ii+block, A.rows() ) );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ const ConstIterator end( B.end(j) );
+ ConstIterator element( B.begin(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j4 : j4+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
+ C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
+ }
+ for( size_t i=ipos; i<iend; ++i ) {
+ C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j) += A(i ,j1) * v1;
+ C(i+1UL,j) += A(i+1UL,j1) * v1;
+ C(i+2UL,j) += A(i+2UL,j1) * v1;
+ C(i+3UL,j) += A(i+3UL,j1) * v1;
+ }
+ for( size_t i=ipos; i<iend; ++i ) {
+ C(i,j) += A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized addition assignment to column-major dense matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized addition assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to column-major dense matrices (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized addition assignment kernel for the transpose dense
+ // matrix-transpose sparse matrix multiplication to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<MT3,MT4,MT5> >
+ selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ const ConstIterator end( B.end(j) );
+ ConstIterator element( B.begin(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j4 : j4+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) + A.load(i,j1) * xmm1 + A.load(i,j2) * xmm2 + A.load(i,j3) * xmm3 + A.load(i,j4) * xmm4 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) + A.load(i,j1) * xmm1 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ C(i,j) += A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to a dense matrix (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense matrix-transpose sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TDMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to matrices (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose dense
+ // matrix-transpose sparse matrix multiplication to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( Or< IsColumnMajorMatrix<MT3>, IsDiagonal<MT4> >::value ? A.rows() : 64UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t itmp( min( ii+block, A.rows() ) );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ ConstIterator element( B.begin(j) );
+ const ConstIterator end( B.end(j) );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+
+ if( IsDiagonal<MT4>::value )
+ {
+ C(j1,j) -= A(j1,j1) * element->value();
+ }
+ else
+ {
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j) -= A(i ,j1) * element->value();
+ C(i+1UL,j) -= A(i+1UL,j1) * element->value();
+ C(i+2UL,j) -= A(i+2UL,j1) * element->value();
+ C(i+3UL,j) -= A(i+3UL,j1) * element->value();
+ }
+ for( size_t i=ipos; i<iend; ++i ) {
+ C(i,j) -= A(i,j1) * element->value();
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to matrices (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the optimized subtraction assignment kernel for the transpose dense
+ // matrix-transpose sparse matrix multiplication to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 64UL );
+
+ for( size_t ii=0UL; ii<A.rows(); ii+=block )
+ {
+ const size_t itmp( min( ii+block, A.rows() ) );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ const ConstIterator end( B.end(j) );
+ ConstIterator element( B.begin(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j4 : j4+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
+ C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
+ C(i+2UL,j) -= A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
+ C(i+3UL,j) -= A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
+ }
+ for( size_t i=ipos; i<iend; ++i ) {
+ C(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( max( ii, ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) ) )
+ :( ii ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( min( itmp, ( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL ) ) )
+ :( itmp ) );
+
+ if( IsTriangular<MT4>::value && ibegin >= iend )
+ continue;
+
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t inum( iend - ibegin );
+ const size_t ipos( ibegin + ( inum & size_t(-4) ) );
+ BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=ibegin; i<ipos; i+=4UL ) {
+ C(i ,j) -= A(i ,j1) * v1;
+ C(i+1UL,j) -= A(i+1UL,j1) * v1;
+ C(i+2UL,j) -= A(i+2UL,j1) * v1;
+ C(i+3UL,j) -= A(i+3UL,j1) * v1;
+ }
+ for( size_t i=ipos; i<iend; ++i ) {
+ C(i,j) -= A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized subtraction assignment to column-major dense matrices****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized subtraction assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to column-major matrices (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side dense matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized subtraction assignment kernel for the transpose dense
+ // matrix-transpose sparse matrix multiplication to a column-major dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<MT3,MT4,MT5> >
+ selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT5> ConstIterator;
+
+ const bool remainder( !IsPadded<MT3>::value || !IsPadded<MT4>::value );
+
+ for( size_t j=0UL; j<B.columns(); ++j )
+ {
+ const ConstIterator end( B.end(j) );
+ ConstIterator element( B.begin(j) );
+
+ const size_t nonzeros( B.nonZeros(j) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+ ++element;
+ const size_t j2( element->index() );
+ const ET2 v2( element->value() );
+ ++element;
+ const size_t j3( element->index() );
+ const ET2 v3( element->value() );
+ ++element;
+ const size_t j4( element->index() );
+ const ET2 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j4 : j4+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) - A.load(i,j1) * xmm1 - A.load(i,j2) * xmm2 - A.load(i,j3) * xmm3 - A.load(i,j4) * xmm4 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ C(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
+ }
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t j1( element->index() );
+ const ET2 v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t ibegin( ( IsLower<MT4>::value )
+ ?( ( IsStrictlyLower<MT4>::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT4>::value )
+ ?( IsStrictlyUpper<MT4>::value ? j1 : j1+1UL )
+ :( A.rows() ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ C.store( i, j, C.load(i,j) - A.load(i,j1) * xmm1 );
+ }
+ for( ; remainder && i<iend; ++i ) {
+ C(i,j) -= A(i,j1) * v1;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-transpose sparse matrix multiplication
+ // to a dense matrix (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-transpose sparse matrix multiplication expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense matrix-transpose sparse matrix multiplication
+ // to a sparse matrix (\f$ A=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // matrix-transpose sparse matrix multiplication expression to a sparse matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to a dense matrix (\f$ A+=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense matrix-transpose sparse matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense matrix-transpose sparse matrix
+ // multiplication to a dense matrix (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense matrix-transpose sparse matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major dense matrix and a
+// column-major sparse matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side dense matrix for the multiplication.
+// \param rhs The right-hand side sparse matrix for the multiplication.
+// \return The resulting matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the multiplication of a column-major dense matrix and a column-major
+// sparse matrix:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::DynamicMatrix<double,columnMajor> A, C;
+ blaze::CompressedMatrix<double,columnMajor> B;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const TDMatTSMatMultExpr<T1,T2>
+ operator*( const DenseMatrix<T1,true>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TDMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TDMatTSMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TDMatTSMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< TDMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsAligned<MT1>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TDMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TDMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TDMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TDMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TDMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TDMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatDVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TDMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatSVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TDMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTSMatMultExprTrait_< TDVecTDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTSMatMultExprTrait_< TSVecTDMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TDMatTSMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TDMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TDMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDVecDMatMultExpr.h b/src/cpu/blaze/math/expressions/TDVecDMatMultExpr.h
new file mode 100644
index 00000000..ebe8efc6
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDVecDMatMultExpr.h
@@ -0,0 +1,4864 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDVecDMatMultExpr.h
+// \brief Header file for the transpose dense vector/dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDVECDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDVECDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/gemv.h>
+#include <blaze/math/blas/trmv.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/math/expressions/VecScalarMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDVECDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense vector-dense matrix multiplications.
+// \ingroup dense_vector_expression
+//
+// The TDVecDMatMultExpr class represents the compile time expression for multiplications
+// between transpose dense vectors and dense matrices.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename MT > // Type of the right-hand side dense matrix
+class TDVecDMatMultExpr : public DenseVector< TDVecDMatMultExpr<VT,MT>, true >
+ , private TVecMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the left-hand side dense vector epxression.
+ typedef ElementType_<MRT> MET; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
+ IsBLASCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the vector or the matrix operand requires an intermediate
+ evaluation, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateVector || evaluateMatrix ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types and the matrix type are suited for a BLAS kernel,
+ the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types and the matrix type are suited for a vectorized
+ computation of the vector/matrix multiplication, the nested \a value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDVecDMatMultExpr<VT,MT> This; //!< Type of this TDVecDMatMultExpr instance.
+ typedef MultTrait_<VRT,MRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ VT::simdEnabled && MT::simdEnabled &&
+ HasSIMDAdd<VET,MET>::value &&
+ HasSIMDMult<VET,MET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDVecDMatMultExpr class.
+ //
+ // \param vec The left-hand side vector operand of the multiplication expression.
+ // \param mat The right-hand side matrix operand of the multiplication expression.
+ */
+ explicit inline TDVecDMatMultExpr( const VT& vec, const MT& mat ) noexcept
+ : vec_( vec ) // Left-hand side dense vector of the multiplication expression
+ , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return vec_[index] * mat_(index,index);
+ }
+ else if( IsLower<MT>::value && ( index > 8UL ) )
+ {
+ const size_t begin( IsStrictlyLower<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.rows() - begin );
+ return subvector( vec_, begin, n ) * subvector( column( mat_, index ), begin, n );
+ }
+ else if( IsUpper<MT>::value && ( index + 8UL < mat_.rows() ) )
+ {
+ const size_t n( IsStrictlyUpper<MT>::value ? index : index+1UL );
+ return subvector( vec_, 0UL, n ) * subvector( column( mat_, index ), 0UL, n );
+ }
+ else
+ {
+ return vec_ * column( mat_, index );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return vec_.isAligned() && mat_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( mat_.rows() * mat_.columns() < TDVECDMATMULT_THRESHOLD ) ) &&
+ ( size() > SMP_TDVECDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vec_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand mat_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense vector-dense matrix multiplication to a transpose
+ // dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense vector-
+ // dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+ else if( rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecDMatMultExpr::selectAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors (kernel selection)**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a transpose dense vector-dense matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( y, x, A );
+ else
+ selectBlasAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose dense vector-
+ // dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ if( IsStrictlyUpper<MT1>::value ) {
+ reset( y[0] );
+ }
+
+ if( !IsLower<MT1>::value )
+ {
+ const size_t jbegin( IsStrictlyUpper<MT1>::value ? 1UL : 0UL );
+ for( size_t j=jbegin; j<N; ++j ) {
+ y[j] = x[0UL] * A(0UL,j);
+ }
+ }
+
+ for( size_t i=( IsLower<MT1>::value && !IsStrictlyLower<MT1>::value ? 0UL : 1UL ); i<M; ++i )
+ {
+ if( IsDiagonal<MT1>::value )
+ {
+ y[i] = x[i] * A(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i-1UL : i )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ }
+ if( jpos < jend ) {
+ y[jpos] += x[i] * A(i,jpos);
+ }
+ if( IsLower<MT1>::value ) {
+ y[jend] = x[i] * A(i,jend);
+ }
+ }
+ }
+
+ if( IsStrictlyLower<MT1>::value ) {
+ reset( y[N-1UL] );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (small matrices)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the transpose dense
+ // vector-dense matrix multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ y.store( j+SIMDSIZE*3UL, xmm4 );
+ y.store( j+SIMDSIZE*4UL, xmm5 );
+ y.store( j+SIMDSIZE*5UL, xmm6 );
+ y.store( j+SIMDSIZE*6UL, xmm7 );
+ y.store( j+SIMDSIZE*7UL, xmm8 );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ y.store( j+SIMDSIZE*3UL, xmm4 );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE, xmm2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, xmm1 );
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+1UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] = value;
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (large matrices)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the transpose dense
+ // vector-dense matrix multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jblock( 32768UL / sizeof( ElementType ) );
+ const size_t iblock( ( N < jblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( jblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ reset( y );
+
+ for( size_t jj=0U; jj<N; jj+=jblock ) {
+ for( size_t ii=0UL; ii<M; ii+=iblock )
+ {
+ const size_t iend( min( ii+iblock, M ) );
+ const size_t jtmp( min( jj+jblock, N ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT1>::value ? iend-1UL : iend ) ) )
+ :( jtmp ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( ( IsUpper<MT1>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT1>::value ? ii+1UL : ii ) & size_t(-SIMDSIZE) ) )
+ :( jj ) );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3 );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4 );
+ y.store( j+SIMDSIZE*4UL, y.load(j+SIMDSIZE*4UL) + xmm5 );
+ y.store( j+SIMDSIZE*5UL, y.load(j+SIMDSIZE*5UL) + xmm6 );
+ y.store( j+SIMDSIZE*6UL, y.load(j+SIMDSIZE*6UL) + xmm7 );
+ y.store( j+SIMDSIZE*7UL, y.load(j+SIMDSIZE*7UL) + xmm8 );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3 );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4 );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , y.load(j ) + xmm1 );
+ y.store( j+SIMDSIZE, y.load(j+SIMDSIZE) + xmm2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, y.load(j) + xmm1 );
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ ElementType value = ElementType();
+
+ for( size_t i=ii; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] += value;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors (default)********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectLargeAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors******************************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based assignment of a transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function performs the transpose dense vector-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ assign( y, x );
+ trmv( y, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ }
+ else {
+ gemv( y, x, A, ET(1), ET(0) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense vector-dense matrix multiplication to a transpose
+ // sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense vector-
+ // dense matrix multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense vector-dense matrix multiplication to a
+ // transpose dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecDMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors (kernel selection)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a transpose dense vector-dense
+ // matrix multiplication to a dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( y, x, A );
+ else
+ selectBlasAddAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose dense
+ // vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ if( IsDiagonal<MT1>::value )
+ {
+ y[i] += x[i] * A(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ }
+ if( jpos < jend ) {
+ y[jpos] += x[i] * A(i,jpos);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (small matrices)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultAddAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (small matrices)********************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the transpose
+ // dense vector-dense matrix multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j ) );
+ SIMDType xmm2( y.load(j+SIMDSIZE ) );
+ SIMDType xmm3( y.load(j+SIMDSIZE*2UL) );
+ SIMDType xmm4( y.load(j+SIMDSIZE*3UL) );
+ SIMDType xmm5( y.load(j+SIMDSIZE*4UL) );
+ SIMDType xmm6( y.load(j+SIMDSIZE*5UL) );
+ SIMDType xmm7( y.load(j+SIMDSIZE*6UL) );
+ SIMDType xmm8( y.load(j+SIMDSIZE*7UL) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ y.store( j+SIMDSIZE*3UL, xmm4 );
+ y.store( j+SIMDSIZE*4UL, xmm5 );
+ y.store( j+SIMDSIZE*5UL, xmm6 );
+ y.store( j+SIMDSIZE*6UL, xmm7 );
+ y.store( j+SIMDSIZE*7UL, xmm8 );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j ) );
+ SIMDType xmm2( y.load(j+SIMDSIZE ) );
+ SIMDType xmm3( y.load(j+SIMDSIZE*2UL) );
+ SIMDType xmm4( y.load(j+SIMDSIZE*3UL) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ y.store( j+SIMDSIZE*3UL, xmm4 );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j ) );
+ SIMDType xmm2( y.load(j+SIMDSIZE ) );
+ SIMDType xmm3( y.load(j+SIMDSIZE*2UL) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j ) );
+ SIMDType xmm2( y.load(j+SIMDSIZE) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE, xmm2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, xmm1 );
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+1UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] += value;
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (large matrices)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultAddAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (large matrices)********************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the transpose
+ // dense vector-dense matrix multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jblock( 32768UL / sizeof( ElementType ) );
+ const size_t iblock( ( N < jblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( jblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ for( size_t jj=0U; jj<N; jj+=jblock ) {
+ for( size_t ii=0UL; ii<M; ii+=iblock )
+ {
+ const size_t iend( min( ii+iblock, M ) );
+ const size_t jtmp( min( jj+jblock, N ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT1>::value ? iend-1UL : iend ) ) )
+ :( jtmp ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( ( IsUpper<MT1>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT1>::value ? ii+1UL : ii ) & size_t(-SIMDSIZE) ) )
+ :( jj ) );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3 );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4 );
+ y.store( j+SIMDSIZE*4UL, y.load(j+SIMDSIZE*4UL) + xmm5 );
+ y.store( j+SIMDSIZE*5UL, y.load(j+SIMDSIZE*5UL) + xmm6 );
+ y.store( j+SIMDSIZE*6UL, y.load(j+SIMDSIZE*6UL) + xmm7 );
+ y.store( j+SIMDSIZE*7UL, y.load(j+SIMDSIZE*7UL) + xmm8 );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3 );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4 );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , y.load(j ) + xmm1 );
+ y.store( j+SIMDSIZE, y.load(j+SIMDSIZE) + xmm2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, y.load(j) + xmm1 );
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ ElementType value = ElementType();
+
+ for( size_t i=ii; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] += value;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors (default)***********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectLargeAddAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors*********************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based addition assignment of a transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function performs the transpose dense vector-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ addAssign( y, tmp );
+ }
+ else {
+ gemv( y, x, A, ET(1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense vector-dense matrix multiplication to a
+ // transpose dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecDMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors (kernel selection)**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a transpose dense vector-
+ // dense matrix multiplication to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( y, x, A );
+ else
+ selectBlasSubAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose dense
+ // vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ for( size_t i=0UL; i<M; ++i )
+ {
+ if( IsDiagonal<MT1>::value )
+ {
+ y[i] -= x[i] * A(i,i);
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ y[j ] -= x[i] * A(i,j );
+ y[j+1UL] -= x[i] * A(i,j+1UL);
+ }
+ if( jpos < jend ) {
+ y[jpos] -= x[i] * A(i,jpos);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (small matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultSubAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (small matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small transpose dense vector-dense
+ // matrix multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // transpose dense vector-dense matrix multiplication. This kernel is optimized for small
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j ) );
+ SIMDType xmm2( y.load(j+SIMDSIZE ) );
+ SIMDType xmm3( y.load(j+SIMDSIZE*2UL) );
+ SIMDType xmm4( y.load(j+SIMDSIZE*3UL) );
+ SIMDType xmm5( y.load(j+SIMDSIZE*4UL) );
+ SIMDType xmm6( y.load(j+SIMDSIZE*5UL) );
+ SIMDType xmm7( y.load(j+SIMDSIZE*6UL) );
+ SIMDType xmm8( y.load(j+SIMDSIZE*7UL) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 - x1 * A.load(i,j );
+ xmm2 = xmm2 - x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 - x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 - x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 - x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 - x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 - x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 - x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ y.store( j+SIMDSIZE*3UL, xmm4 );
+ y.store( j+SIMDSIZE*4UL, xmm5 );
+ y.store( j+SIMDSIZE*5UL, xmm6 );
+ y.store( j+SIMDSIZE*6UL, xmm7 );
+ y.store( j+SIMDSIZE*7UL, xmm8 );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j ) );
+ SIMDType xmm2( y.load(j+SIMDSIZE ) );
+ SIMDType xmm3( y.load(j+SIMDSIZE*2UL) );
+ SIMDType xmm4( y.load(j+SIMDSIZE*3UL) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 - x1 * A.load(i,j );
+ xmm2 = xmm2 - x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 - x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 - x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ y.store( j+SIMDSIZE*3UL, xmm4 );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j ) );
+ SIMDType xmm2( y.load(j+SIMDSIZE ) );
+ SIMDType xmm3( y.load(j+SIMDSIZE*2UL) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 - x1 * A.load(i,j );
+ xmm2 = xmm2 - x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 - x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE , xmm2 );
+ y.store( j+SIMDSIZE*2UL, xmm3 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j ) );
+ SIMDType xmm2( y.load(j+SIMDSIZE) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 - x1 * A.load(i,j );
+ xmm2 = xmm2 - x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , xmm1 );
+ y.store( j+SIMDSIZE, xmm2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1( y.load(j) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ xmm1 = xmm1 - set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, xmm1 );
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+1UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] -= value;
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (large matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultSubAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (large matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large transpose dense vector-dense
+ // matrix multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // transpose dense vector-dense matrix multiplication. This kernel is optimized for large
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jblock( 32768UL / sizeof( ElementType ) );
+ const size_t iblock( ( N < jblock )?( 8UL ):( 4UL ) );
+
+ BLAZE_INTERNAL_ASSERT( ( jblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ for( size_t jj=0U; jj<N; jj+=jblock ) {
+ for( size_t ii=0UL; ii<M; ii+=iblock )
+ {
+ const size_t iend( min( ii+iblock, M ) );
+ const size_t jtmp( min( jj+jblock, N ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT1>::value ? iend-1UL : iend ) ) )
+ :( jtmp ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( ( IsUpper<MT1>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT1>::value ? ii+1UL : ii ) & size_t(-SIMDSIZE) ) )
+ :( jj ) );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3 );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) - xmm4 );
+ y.store( j+SIMDSIZE*4UL, y.load(j+SIMDSIZE*4UL) - xmm5 );
+ y.store( j+SIMDSIZE*5UL, y.load(j+SIMDSIZE*5UL) - xmm6 );
+ y.store( j+SIMDSIZE*6UL, y.load(j+SIMDSIZE*6UL) - xmm7 );
+ y.store( j+SIMDSIZE*7UL, y.load(j+SIMDSIZE*7UL) - xmm8 );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3 );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) - xmm4 );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1 );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2 );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3 );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , y.load(j ) - xmm1 );
+ y.store( j+SIMDSIZE, y.load(j+SIMDSIZE) - xmm2 );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, y.load(j) - xmm1 );
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ ElementType value = ElementType();
+
+ for( size_t i=ii; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] -= value;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors (default)********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectLargeSubAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors******************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based subtraction assignment of a transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function performs the transpose dense vector-dense matrix multiplication based on the
+ // according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ subAssign( y, tmp );
+ }
+ else {
+ gemv( y, x, A, ET(-1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a transpose dense vector-dense matrix multiplication to
+ // a transpose dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a transpose dense vector-dense matrix multiplication to a
+ // transpose dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a transpose dense
+ // vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense vector-dense matrix multiplication to a transpose
+ // dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+ else if( rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense vector-dense matrix multiplication to a transpose
+ // sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // vector-dense matrix multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense vector-dense matrix multiplication to a
+ // transpose dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense vector-dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a transpose dense vector-dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose dense vector-dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a transpose dense vector-dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a transpose
+ // dense vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR( VT, MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSCALARMULTEXPR SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Expression object for scaled transpose dense vector-dense matrix multiplications.
+// \ingroup dense_vector_expression
+//
+// This specialization of the DVecScalarMultExpr class represents the compile time expression
+// for scaled multiplications between a non-transpose dense vector and a row-major dense matrix.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename MT // Type of the right-hand side dense matrix
+ , typename ST > // Type of the side scalar value
+class DVecScalarMultExpr< TDVecDMatMultExpr<VT,MT>, ST, true >
+ : public DenseVector< DVecScalarMultExpr< TDVecDMatMultExpr<VT,MT>, ST, true >, true >
+ , private VecScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef TDVecDMatMultExpr<VT,MT> VMM; //!< Type of the dense vector-dense matrix multiplication expression.
+ typedef ResultType_<VMM> RES; //!< Result type of the dense vector-dense matrix multiplication expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the left-hand side dense vector epxression.
+ typedef ElementType_<MRT> MET; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
+ IsBLASCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the vector or the matrix operand requires an intermediate
+ evaluation, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateVector || evaluateMatrix ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types, the matrix type, and the scalar type are suited
+ for a BLAS kernel, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ !( IsBuiltin< ElementType_<T1> >::value && IsComplex<T4>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types, the matrix type, and the scalar type are suited
+ for a vectorized computation of the scaled vector/matrix multiplication, the nested
+ \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3>
+ , T4 >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecScalarMultExpr<VMM,ST,true> This; //!< Type of this DVecScalarMultExpr instance.
+ typedef MultTrait_<RES,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef const TDVecDMatMultExpr<VT,MT> LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+
+ //! Type for the assignment of the dense vector operand of the left-hand side expression.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Type for the assignment of the dense matrix operand of the left-hand side expression.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ VT::simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable<VET,MET,ST>::value &&
+ HasSIMDAdd<VET,MET>::value &&
+ HasSIMDMult<VET,MET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecScalarMultExpr class.
+ //
+ // \param vector The left-hand side dense vector of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DVecScalarMultExpr( const VMM& vector, ST scalar )
+ : vector_( vector ) // Left-hand side dense vector of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
+ return vector_[index] * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= vector_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const {
+ return vector_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return vector_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const {
+ return vector_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const {
+ RightOperand_<VMM> A( vector_.rightOperand() );
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) ) &&
+ ( size() > SMP_TDVECDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vector_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*!\brief Assignment of a scaled transpose dense vector-dense matrix multiplication to a
+ // transpose dense vector (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+ else if( right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectAssignKernel( ~lhs, x, A, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors (kernel selection)**********************************************
+ /*!\brief Selection of the kernel for an assignment of a scaled transpose dense vector-dense
+ // matrix multiplication to a dense vector (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( y, x, A, scalar );
+ else
+ selectBlasAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*!\brief Default assignment of a scaled transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the scaled transpose dense vector-
+ // dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ if( IsStrictlyUpper<MT1>::value ) {
+ reset( y[0] );
+ }
+
+ if( !IsLower<MT1>::value )
+ {
+ for( size_t j=( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ); j<N; ++j ) {
+ y[j] = x[0UL] * A(0UL,j);
+ }
+ }
+
+ for( size_t i=( IsLower<MT1>::value && !IsStrictlyLower<MT1>::value ? 0UL : 1UL ); i<M; ++i )
+ {
+ if( IsDiagonal<MT1>::value )
+ {
+ y[i] = x[i] * A(i,i) * scalar;
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i-1UL : i )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jnum( jend - jbegin );
+ const size_t jpos( jbegin + ( jnum & size_t(-2) ) );
+
+ for( size_t j=jbegin; j<jpos; j+=2UL ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ }
+ if( jpos < jend ) {
+ y[jpos] += x[i] * A(i,jpos);
+ }
+ if( IsLower<MT1>::value ) {
+ y[jend] = x[i] * A(i,jend);
+ }
+ }
+ }
+
+ if( IsStrictlyLower<MT1>::value ) {
+ reset( y[N-1UL] );
+ }
+
+ if( !IsDiagonal<MT1>::value )
+ {
+ const size_t iend( IsStrictlyLower<MT1>::value ? N-1UL : N );
+ for( size_t j=( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ); j<iend; ++j ) {
+ y[j] *= scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*!\brief Default assignment of a small scaled transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*!\brief Default assignment of a small scaled transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the scaled transpose dense vector-
+ // dense matrix multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , xmm1*factor );
+ y.store( j+SIMDSIZE , xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, xmm4*factor );
+ y.store( j+SIMDSIZE*4UL, xmm5*factor );
+ y.store( j+SIMDSIZE*5UL, xmm6*factor );
+ y.store( j+SIMDSIZE*6UL, xmm7*factor );
+ y.store( j+SIMDSIZE*7UL, xmm8*factor );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , xmm1*factor );
+ y.store( j+SIMDSIZE , xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, xmm4*factor );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , xmm1*factor );
+ y.store( j+SIMDSIZE , xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, xmm3*factor );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , xmm1*factor );
+ y.store( j+SIMDSIZE, xmm2*factor );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, xmm1*factor );
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+1UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] = value * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*!\brief Default assignment of a large scaled transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*!\brief Default assignment of a large scaled transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the scaled transpose dense vector-
+ // dense matrix multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jblock( 32768UL / sizeof( ElementType ) );
+ const size_t iblock( ( N < jblock )?( 8UL ):( 4UL ) );
+
+ const SIMDType factor( set( scalar ) );
+
+ BLAZE_INTERNAL_ASSERT( ( jblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ reset( y );
+
+ for( size_t jj=0U; jj<N; jj+=jblock ) {
+ for( size_t ii=0UL; ii<M; ii+=iblock )
+ {
+ const size_t iend( min( ii+iblock, M ) );
+ const size_t jtmp( min( jj+jblock, N ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT1>::value ? iend-1UL : iend ) ) )
+ :( jtmp ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( ( IsUpper<MT1>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT1>::value ? ii+1UL : ii ) & size_t(-SIMDSIZE) ) )
+ :( jj ) );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4*factor );
+ y.store( j+SIMDSIZE*4UL, y.load(j+SIMDSIZE*4UL) + xmm5*factor );
+ y.store( j+SIMDSIZE*5UL, y.load(j+SIMDSIZE*5UL) + xmm6*factor );
+ y.store( j+SIMDSIZE*6UL, y.load(j+SIMDSIZE*6UL) + xmm7*factor );
+ y.store( j+SIMDSIZE*7UL, y.load(j+SIMDSIZE*7UL) + xmm8*factor );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4*factor );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE, y.load(j+SIMDSIZE) + xmm2*factor );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, y.load(j) + xmm1*factor );
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ ElementType value = ElementType();
+
+ for( size_t i=ii; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] += value * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors (default)********************************************
+ /*!\brief Default assignment of a scaled transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large scaled
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectLargeAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors******************************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based assignment of a scaled transpose dense vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense vector-dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ assign( y, scalar * x );
+ trmv( y, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ }
+ else {
+ gemv( y, x, A, ET(scalar), ET(0) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*!\brief Assignment of a scaled transpose dense vector-dense matrix multiplication to a
+ // transpose sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // vector-dense matrix multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*!\brief Addition assignment of a scaled transpose dense vector-dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL || right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectAddAssignKernel( ~lhs, x, A, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors (kernel selection)*************************************
+ /*!\brief Selection of the kernel for an addition assignment of a scaled transpose dense vector-
+ // dense matrix multiplication to a dense vector (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( y, x, A, scalar );
+ else
+ selectBlasAddAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*!\brief Default addition assignment of a scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the scaled transpose
+ // dense vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ y.addAssign( x * A * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (small matrices)*******************************
+ /*!\brief Default addition assignment of a small scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (small matrices)********************
+ /*!\brief Vectorized default addition assignment of a small scaled transpose dense vector-dense
+ // matrix multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the scaled
+ // transpose dense vector-dense matrix multiplication. This kernel is optimized for small
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4*factor );
+ y.store( j+SIMDSIZE*4UL, y.load(j+SIMDSIZE*4UL) + xmm5*factor );
+ y.store( j+SIMDSIZE*5UL, y.load(j+SIMDSIZE*5UL) + xmm6*factor );
+ y.store( j+SIMDSIZE*6UL, y.load(j+SIMDSIZE*6UL) + xmm7*factor );
+ y.store( j+SIMDSIZE*7UL, y.load(j+SIMDSIZE*7UL) + xmm8*factor );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4*factor );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE, y.load(j+SIMDSIZE) + xmm2*factor );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, y.load(j) + xmm1*factor );
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+1UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] += value * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (large matrices)*******************************
+ /*!\brief Default addition assignment of a large scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (large matrices)********************
+ /*!\brief Vectorized default addition assignment of a large scaled transpose dense vector-dense
+ // matrix multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the scaled
+ // transpose dense vector-dense matrix multiplication. This kernel is optimized for large
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jblock( 32768UL / sizeof( ElementType ) );
+ const size_t iblock( ( N < jblock )?( 8UL ):( 4UL ) );
+
+ const SIMDType factor( set( scalar ) );
+
+ BLAZE_INTERNAL_ASSERT( ( jblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ for( size_t jj=0U; jj<N; jj+=jblock ) {
+ for( size_t ii=0UL; ii<M; ii+=iblock )
+ {
+ const size_t iend( min( ii+iblock, M ) );
+ const size_t jtmp( min( jj+jblock, N ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT1>::value ? iend-1UL : iend ) ) )
+ :( jtmp ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( ( IsUpper<MT1>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT1>::value ? ii+1UL : ii ) & size_t(-SIMDSIZE) ) )
+ :( jj ) );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4*factor );
+ y.store( j+SIMDSIZE*4UL, y.load(j+SIMDSIZE*4UL) + xmm5*factor );
+ y.store( j+SIMDSIZE*5UL, y.load(j+SIMDSIZE*5UL) + xmm6*factor );
+ y.store( j+SIMDSIZE*6UL, y.load(j+SIMDSIZE*6UL) + xmm7*factor );
+ y.store( j+SIMDSIZE*7UL, y.load(j+SIMDSIZE*7UL) + xmm8*factor );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) + xmm4*factor );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) + xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) + xmm3*factor );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , y.load(j ) + xmm1*factor );
+ y.store( j+SIMDSIZE, y.load(j+SIMDSIZE) + xmm2*factor );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, y.load(j) + xmm1*factor );
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ ElementType value = ElementType();
+
+ for( size_t i=ii; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] += value * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors (default)***********************************
+ /*!\brief Default addition assignment of a scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // scaled transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectLargeAddAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors*********************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based addition assignment of a scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor
+ // \return void
+ //
+ // This function performs the scaled transpose dense vector-dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( scalar * x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ addAssign( y, tmp );
+ }
+ else {
+ gemv( y, x, A, ET(scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*!\brief Subtraction assignment of a scaled transpose dense vector-dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a scaled
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL || right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectSubAssignKernel( ~lhs, x, A, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors (kernel selection)**********************************
+ /*!\brief Selection of the kernel for a subtraction assignment of a scaled transpose dense vector-
+ // dense matrix multiplication to a dense vector (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( y, x, A, scalar );
+ else
+ selectBlasSubAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the scaled transpose
+ // dense vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ y.subAssign( x * A * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (small matrices)****************************
+ /*!\brief Default subtraction assignment of a small scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // scaled transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (small matrices)*****************
+ /*!\brief Vectorized default subtraction assignment of a small scaled transpose dense vector-
+ // dense matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // scaled transpose dense vector-dense matrix multiplication. This kernel is optimized for
+ // small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ const SIMDType factor( set( scalar ) );
+
+ size_t j( 0UL );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) - xmm4*factor );
+ y.store( j+SIMDSIZE*4UL, y.load(j+SIMDSIZE*4UL) - xmm5*factor );
+ y.store( j+SIMDSIZE*5UL, y.load(j+SIMDSIZE*5UL) - xmm6*factor );
+ y.store( j+SIMDSIZE*6UL, y.load(j+SIMDSIZE*6UL) - xmm7*factor );
+ y.store( j+SIMDSIZE*7UL, y.load(j+SIMDSIZE*7UL) - xmm8*factor );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) - xmm4*factor );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3*factor );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , y.load(j ) - xmm1*factor );
+ y.store( j+SIMDSIZE, y.load(j+SIMDSIZE) - xmm2*factor );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ SIMDType xmm1;
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, y.load(j) - xmm1*factor );
+ }
+
+ for( ; remainder && j<N; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( min( j+1UL, M ) - ( IsStrictlyUpper<MT1>::value ? 1UL : 0UL ) )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ ElementType value = ElementType();
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] -= value * scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (large matrices)****************************
+ /*!\brief Default subtraction assignment of a large scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // scaled transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (large matrices)*****************
+ /*!\brief Vectorized default subtraction assignment of a large scaled transpose dense vector-
+ // dense matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // scaled transpose dense vector-dense matrix multiplication. This kernel is optimized for
+ // large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ const size_t jblock( 32768UL / sizeof( ElementType ) );
+ const size_t iblock( ( N < jblock )?( 8UL ):( 4UL ) );
+
+ const SIMDType factor( set( scalar ) );
+
+ BLAZE_INTERNAL_ASSERT( ( jblock % SIMDSIZE ) == 0UL, "Invalid block size detected" );
+
+ for( size_t jj=0U; jj<N; jj+=jblock ) {
+ for( size_t ii=0UL; ii<M; ii+=iblock )
+ {
+ const size_t iend( min( ii+iblock, M ) );
+ const size_t jtmp( min( jj+jblock, N ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( min( jtmp, ( IsStrictlyLower<MT1>::value ? iend-1UL : iend ) ) )
+ :( jtmp ) );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( ( IsUpper<MT1>::value )
+ ?( max( jj, ( IsStrictlyUpper<MT1>::value ? ii+1UL : ii ) & size_t(-SIMDSIZE) ) )
+ :( jj ) );
+
+ for( ; (j+SIMDSIZE*7UL) < jpos; j+=SIMDSIZE*8UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+SIMDSIZE*4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+SIMDSIZE*5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+SIMDSIZE*6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+SIMDSIZE*7UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) - xmm4*factor );
+ y.store( j+SIMDSIZE*4UL, y.load(j+SIMDSIZE*4UL) - xmm5*factor );
+ y.store( j+SIMDSIZE*5UL, y.load(j+SIMDSIZE*5UL) - xmm6*factor );
+ y.store( j+SIMDSIZE*6UL, y.load(j+SIMDSIZE*6UL) - xmm7*factor );
+ y.store( j+SIMDSIZE*7UL, y.load(j+SIMDSIZE*7UL) - xmm8*factor );
+ }
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL )
+ {
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+SIMDSIZE*3UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3*factor );
+ y.store( j+SIMDSIZE*3UL, y.load(j+SIMDSIZE*3UL) - xmm4*factor );
+ }
+
+ for( ; (j+SIMDSIZE*2UL) < jpos; j+=SIMDSIZE*3UL )
+ {
+ SIMDType xmm1, xmm2, xmm3;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE );
+ xmm3 = xmm3 + x1 * A.load(i,j+SIMDSIZE*2UL);
+ }
+
+ y.store( j , y.load(j ) - xmm1*factor );
+ y.store( j+SIMDSIZE , y.load(j+SIMDSIZE ) - xmm2*factor );
+ y.store( j+SIMDSIZE*2UL, y.load(j+SIMDSIZE*2UL) - xmm3*factor );
+ }
+
+ for( ; (j+SIMDSIZE) < jpos; j+=SIMDSIZE*2UL )
+ {
+ SIMDType xmm1, xmm2;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ const SIMDType x1( set( x[i] ) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+SIMDSIZE);
+ }
+
+ y.store( j , y.load(j ) - xmm1*factor );
+ y.store( j+SIMDSIZE, y.load(j+SIMDSIZE) - xmm2*factor );
+ }
+
+ for( ; j<jpos; j+=SIMDSIZE )
+ {
+ SIMDType xmm1;
+
+ for( size_t i=ii; i<iend; ++i ) {
+ xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
+ }
+
+ y.store( j, y.load(j) - xmm1*factor );
+ }
+
+ for( ; remainder && j<jend; ++j )
+ {
+ ElementType value = ElementType();
+
+ for( size_t i=ii; i<iend; ++i ) {
+ value += x[i] * A(i,j);
+ }
+
+ y[j] -= value * scalar;
+ }
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors (default)********************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // scaled transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectLargeSubAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors******************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based subtraction assignment of a scaled transpose dense vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense vector-dense matrix multiplication based
+ // on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( scalar * x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ subAssign( y, tmp );
+ }
+ else {
+ gemv( y, x, A, ET(-scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*!\brief Multiplication assignment of a scaled transpose dense vector-dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}*=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a scaled
+ // transpose dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*!\brief Division assignment of a scaled transpose dense vector-dense matrix multiplication to
+ // a transpose dense vector (\f$ \vec{y}/=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a scaled transpose
+ // dense vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*!\brief SMP assignment of a scaled transpose dense vector-dense matrix multiplication to a
+ // transpose dense vector (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+ else if( right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( left ); // Evaluation of the left-hand side dense vector operand
+ RT A( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, x * A * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*!\brief SMP assignment of a scaled transpose dense vector-dense matrix multiplication to a
+ // transpose sparse vector.
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense vector-dense matrix multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*!\brief SMP addition assignment of a scaled transpose dense vector-dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a scaled
+ // transpose dense vector-dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL || right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( left ); // Evaluation of the left-hand side dense vector operand
+ RT A( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, x * A * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*!\brief SMP subtraction assignment of a scaled transpose dense vector-dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a scaled
+ // transpose dense vector-dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL || right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( left ); // Evaluation of the left-hand side dense vector operand
+ RT A( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, x * A * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*!\brief SMP multiplication assignment of a scaled transpose dense vector-dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}*=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // scaled transpose dense vector-dense matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be
+ // selected by the compiler in case the expression specific parallel evaluation strategy
+ // is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*!\brief SMP dvision assignment of a scaled transpose dense vector-dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}/=s*A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a scaled
+ // transpose dense vector-dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VMM );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VMM );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector and a
+// row-major dense matrix (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side transpose dense vector for the multiplication.
+// \param mat The right-hand side row-major dense matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator represents the multiplication between a transpose dense vector and a row-major
+// dense matrix:
+
+ \code
+ using blaze::rowVector;
+ using blaze::rowMajor;
+
+ blaze::DynamicVector<double,rowVector> x, y;
+ blaze::DynamicMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ y = x * A;
+ \endcode
+
+// The operator returns an expression representing a transpose dense vector of the higher-order
+// element type of the two involved element types \a T1::ElementType and \a T2::ElementType.
+// Both the dense matrix type \a T1 and the dense vector type \a T2 as well as the two element
+// types \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of rows of
+// the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const DisableIf_< IsMatMatMultExpr<T2>, TDVecDMatMultExpr<T1,T2> >
+ operator*( const DenseVector<T1,true>& vec, const DenseMatrix<T2,false>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return TDVecDMatMultExpr<T1,T2>( ~vec, ~mat );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector and a
+// dense matrix-matrix multiplication expression (\f$ \vec{y}^T=\vec{x}^T*(A*B) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector for the multiplication.
+// \param mat The right-hand side dense matrix-matrix multiplication.
+// \return The resulting vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a dense
+// vector and a dense matrix-matrix multiplication expression. It restructures the expression
+// \f$ \vec{y}^T=\vec{x}^T*(A*B) \f$ to the expression \f$ \vec{y}^T=(\vec{x}^T*A)*B \f$.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const EnableIf_< IsMatMatMultExpr<T2>, MultExprTrait_<T1,T2> >
+ operator*( const DenseVector<T1,true>& vec, const DenseMatrix<T2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( T1 );
+
+ return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct Size< TDVecDMatMultExpr<VT,MT> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct IsAligned< TDVecDMatMultExpr<VT,MT> >
+ : public BoolConstant< And< IsAligned<VT>, IsAligned<MT> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, bool AF >
+struct SubvectorExprTrait< TDVecDMatMultExpr<VT,MT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>
+ , SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDVecDVecMultExpr.h b/src/cpu/blaze/math/expressions/TDVecDVecMultExpr.h
new file mode 100644
index 00000000..ad01b57c
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDVecDVecMultExpr.h
@@ -0,0 +1,261 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDVecDVecMultExpr.h
+// \brief Header file for the dense vector/dense vector inner product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDVECDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDVECDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the dense vector/dense vector scalar multiplication.
+// \ingroup dense_vector
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side dense vector
+struct TDVecDVecMultExprHelper
+{
+ //**Type definitions****************************************************************************
+ //! Composite type of the left-hand side dense vector expression.
+ typedef RemoveReference_< CompositeType_<T1> > CT1;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef RemoveReference_< CompositeType_<T2> > CT2;
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ enum : bool { value = useOptimizedKernels &&
+ CT1::simdEnabled &&
+ CT2::simdEnabled &&
+ IsSame< ElementType_<CT1>, ElementType_<CT2> >::value &&
+ HasSIMDAdd< ElementType_<CT1>, ElementType_<CT1> >::value &&
+ HasSIMDMult< ElementType_<CT1>, ElementType_<CT1> >::value };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default multiplication operator for the scalar product (inner product) of two dense
+// vectors (\f$ s=\vec{a}*\vec{b} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the inner product.
+// \param rhs The right-hand side dense vector for the inner product.
+// \return The scalar product.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the scalar product (inner product) of two dense vectors:
+
+ \code
+ blaze::DynamicVector<double> a, b;
+ blaze::double res;
+ // ... Resizing and initialization
+ res = trans(a) * b;
+ \endcode
+
+// The operator returns a scalar value of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side dense vector
+inline DisableIf_< TDVecDVecMultExprHelper<T1,T2>
+ , const MultTrait_< ElementType_<T1>, ElementType_<T2> > >
+ operator*( const DenseVector<T1,true>& lhs, const DenseVector<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef CompositeType_<T1> Lhs;
+ typedef CompositeType_<T2> Rhs;
+ typedef ElementType_<T1> ET1;
+ typedef ElementType_<T2> ET2;
+ typedef MultTrait_<ET1,ET2> MultType;
+
+ if( (~lhs).size() == 0UL ) return MultType();
+
+ Lhs left ( ~lhs );
+ Rhs right( ~rhs );
+
+ MultType sp( left[0UL] * right[0UL] );
+ size_t i( 1UL );
+
+ for( ; (i+4UL) <= left.size(); i+=4UL ) {
+ sp += left[i ] * right[i ] +
+ left[i+1UL] * right[i+1UL] +
+ left[i+2UL] * right[i+2UL] +
+ left[i+3UL] * right[i+3UL];
+ }
+ for( ; (i+2UL) <= left.size(); i+=2UL ) {
+ sp += left[i ] * right[i ] +
+ left[i+1UL] * right[i+1UL];
+ }
+ for( ; i<left.size(); ++i ) {
+ sp += left[i] * right[i];
+ }
+
+ return sp;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SIMD optimized multiplication operator for the scalar product (inner product) of two
+// dense vectors (\f$ s=\vec{a}*\vec{b} \f$).
+// \ingroup dense_vector
+//
+// \param lhs The left-hand side dense vector for the inner product.
+// \param rhs The right-hand side dense vector for the inner product.
+// \return The scalar product.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the scalar product (inner product) of two dense vectors:
+
+ \code
+ using blaze::columnVector;
+
+ blaze::DynamicVector<double,columnVector> a, b;
+ blaze::double res;
+ // ... Resizing and initialization
+ res = trans(a) * b;
+ \endcode
+
+// The operator returns a scalar value of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side dense vector
+inline EnableIf_< TDVecDVecMultExprHelper<T1,T2>
+ , const MultTrait_< ElementType_<T1>, ElementType_<T2> > >
+ operator*( const DenseVector<T1,true>& lhs, const DenseVector<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef CompositeType_<T1> Lhs;
+ typedef CompositeType_<T2> Rhs;
+ typedef ElementType_<T1> ET1;
+ typedef ElementType_<T2> ET2;
+ typedef MultTrait_<ET1,ET2> MultType;
+
+ enum : size_t { SIMDSIZE = SIMDTrait<MultType>::size };
+
+ if( (~lhs).size() == 0UL ) return MultType();
+
+ Lhs left ( ~lhs );
+ Rhs right( ~rhs );
+
+ const size_t N( left.size() );
+
+ SIMDTrait_<MultType> xmm1, xmm2, xmm3, xmm4;
+ size_t i( 0UL );
+
+ for( ; (i+SIMDSIZE*4UL) <= N; i+=SIMDSIZE*4UL ) {
+ xmm1 = xmm1 + ( left.load(i ) * right.load(i ) );
+ xmm2 = xmm2 + ( left.load(i+SIMDSIZE ) * right.load(i+SIMDSIZE ) );
+ xmm3 = xmm3 + ( left.load(i+SIMDSIZE*2UL) * right.load(i+SIMDSIZE*2UL) );
+ xmm4 = xmm4 + ( left.load(i+SIMDSIZE*3UL) * right.load(i+SIMDSIZE*3UL) );
+ }
+ for( ; (i+SIMDSIZE*2UL) <= N; i+=SIMDSIZE*2UL ) {
+ xmm1 = xmm1 + ( left.load(i ) * right.load(i ) );
+ xmm2 = xmm2 + ( left.load(i+SIMDSIZE) * right.load(i+SIMDSIZE) );
+ }
+ for( ; (i+SIMDSIZE) <= N; i+=SIMDSIZE ) {
+ xmm1 = xmm1 + ( left.load(i) * right.load(i) );
+ }
+
+ MultType sp( sum( xmm1 + xmm2 + xmm3 + xmm4 ) );
+
+ for( ; i<N; ++i ) {
+ sp += left[i] * right[i];
+ }
+
+ return sp;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDVecSMatMultExpr.h b/src/cpu/blaze/math/expressions/TDVecSMatMultExpr.h
new file mode 100644
index 00000000..3812d935
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDVecSMatMultExpr.h
@@ -0,0 +1,1037 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDVecSMatMultExpr.h
+// \brief Header file for the transpose dense vector/sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDVECSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDVECSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDVECSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense vector-sparse matrix multiplications.
+// \ingroup dense_vector_expression
+//
+// The TDVecSMatMultExpr class represents the compile time expression for multiplications
+// between transpose dense vectors and row-major sparse matrices.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename MT > // Type of the right-hand side sparse matrix
+class TDVecSMatMultExpr : public DenseVector< TDVecSMatMultExpr<VT,MT>, true >
+ , private TVecMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the vector or the matrix operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateVector || evaluateMatrix ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDVecSMatMultExpr<VT,MT> This; //!< Type of this TDVecSMatMultExpr instance.
+ typedef MultTrait_<VRT,MRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > RightOperand;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDVecSMatMultExpr class.
+ */
+ explicit inline TDVecSMatMultExpr( const VT& vec, const MT& mat ) noexcept
+ : vec_( vec ) // Left-hand side dense vector of the multiplication expression
+ , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( vec_.size() == mat.rows(), "Invalid vector and matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return vec_[index] * mat_(index,index);
+ }
+ else if( IsLower<MT>::value )
+ {
+ const size_t begin( IsStrictlyLower<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.rows() - begin );
+ return subvector( vec_, begin, n ) * subvector( column( mat_, index ), begin, n );
+ }
+ else if( IsUpper<MT>::value )
+ {
+ const size_t n( IsStrictlyUpper<MT>::value ? index : index+1UL );
+ return subvector( vec_, 0UL, n ) * subvector( column( mat_, index ), 0UL, n );
+ }
+ else
+ {
+ return vec_ * column( mat_, index );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return vec_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_TDVECSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vec_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand mat_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*!\brief Assignment of a transpose dense vector-sparse matrix multiplication to a dense
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense vector-
+ // sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ reset( ~lhs );
+
+ if( rhs.mat_.rows() == 0UL ) return;
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operator
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecSMatMultExpr::selectAssignKernel( ~lhs, x, A );
+ }
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a transpose dense vector-sparse matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the serial assignment kernel for the transpose sparse vector-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > ConstIterator;
+
+ for( size_t i=0UL; i<x.size(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ if( IsResizable< ElementType_<VT1> >::value &&
+ isDefault( y[element->index()] ) )
+ y[element->index()] = x[i] * element->value();
+ else
+ y[element->index()] += x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*!\brief Assignment of a transpose dense vector-sparse matrix multiplication to a sparse
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense vector-
+ // sparse matrix multiplication expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*!\brief Addition assignment of a transpose dense vector-sparse matrix multiplication to a
+ // dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // dense vector-sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operator
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecSMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
+ }
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a transpose dense vector-sparse matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the serial addition assignment kernel for the transpose sparse
+ // vector-transpose sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > ConstIterator;
+
+ for( size_t i=0UL; i<x.size(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ y[element->index()] += x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*!\brief Subtraction assignment of a transpose dense vector-sparse matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense vector-sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operator
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecSMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
+ }
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a transpose dense vector-sparse matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the serial subtraction assignment kernel for the transpose sparse
+ // vector-transpose sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > ConstIterator;
+
+ for( size_t i=0UL; i<x.size(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ y[element->index()] -= x[i] * element->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*!\brief Multiplication assignment of a transpose dense vector-sparse matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // dense vector-sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*!\brief Division assignment of a transpose dense vector-sparse matrix multiplication to a
+ // dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a transpose dense
+ // vector-sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*!\brief SMP assignment of a transpose dense vector-sparse matrix multiplication to a dense
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // vector-sparse matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ reset( ~lhs );
+
+ if( rhs.mat_.rows() == 0UL ) return;
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*!\brief SMP assignment of a transpose dense vector-sparse matrix multiplication to a sparse
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // vector-sparse matrix multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*!\brief Addition assignment of a transpose dense vector-sparse matrix multiplication to a
+ // dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense vector-sparse matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*!\brief SMP subtraction assignment of a transpose dense vector-sparse matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense vector-sparse matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*!\brief SMP multiplication assignment of a transpose dense vector-sparse matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose dense vector-sparse matrix multiplication expression to a dense vector. Due
+ // to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*!\brief SMP division assignment of a transpose dense vector-sparse matrix multiplication to
+ // a dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a transpose
+ // dense vector-sparse matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR( VT, MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector and a
+// row-major sparse matrix (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side transpose dense vector for the multiplication.
+// \param mat The right-hand side row-major sparse matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator represents the multiplication between a transpose dense vector and a row-major
+// sparse matrix:
+
+ \code
+ using blaze::rowVector;
+ using blaze::rowMajor;
+
+ blaze::DynamicVector<double,rowVector> x, y;
+ blaze::CompressedMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ y = x * A;
+ \endcode
+
+// The operator returns an expression representing a transpose dense vector of the higher-order
+// element type of the two involved element types \a T1::ElementType and \a T2::ElementType.
+// Both the sparse matrix type \a T1 and the dense vector type \a T2 as well as the two element
+// types \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of rows of
+// the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const DisableIf_< Or< IsSymmetric<T2>, IsMatMatMultExpr<T2> >, TDVecSMatMultExpr<T1,T2> >
+ operator*( const DenseVector<T1,true>& vec, const SparseMatrix<T2,false>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return TDVecSMatMultExpr<T1,T2>( ~vec, ~mat );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector and a
+// symmetric row-major sparse matrix (\f$ \vec{a}=B*\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side transpose dense vector for the multiplication.
+// \param mat The right-hand side row-major sparse matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator implements the performance optimized treatment of the multiplication of
+// a transpose dense vector and a symmetric row-major sparse matrix. It restructures the
+// expression \f$ \vec{y}^T=\vec{x}^T*A \f$ to the expression \f$ \vec{y}^T=\vec{x}^T*A^T \f$.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const EnableIf_< IsSymmetric<T2>, MultExprTrait_<T1,T2> >
+ operator*( const DenseVector<T1,true>& vec, const SparseMatrix<T2,false>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATMULTEXPR_TYPE( T2 );
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return (~vec) * trans( ~mat );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector and a
+// sparse matrix-matrix multiplication expression (\f$ \vec{y}^T=\vec{x}^T*(A*B) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side dense vector for the multiplication.
+// \param mat The right-hand side sparse matrix-matrix multiplication.
+// \return The resulting vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a dense
+// vector and a sparse matrix-matrix multiplication expression. It restructures the expression
+// \f$ \vec{y}^T=\vec{x}^T*(A*B) \f$ to the expression \f$ \vec{y}^T=(\vec{x}^T*A)*B \f$.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline const EnableIf_< IsMatMatMultExpr<T2>, MultExprTrait_<T1,T2> >
+ operator*( const DenseVector<T1,true>& vec, const SparseMatrix<T2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( T2 );
+
+ return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct Size< TDVecSMatMultExpr<VT,MT> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct IsAligned< TDVecSMatMultExpr<VT,MT> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, bool AF >
+struct SubvectorExprTrait< TDVecSMatMultExpr<VT,MT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>
+ , SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDVecSVecMultExpr.h b/src/cpu/blaze/math/expressions/TDVecSVecMultExpr.h
new file mode 100644
index 00000000..34dc853b
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDVecSVecMultExpr.h
@@ -0,0 +1,142 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDVecSVecMultExpr.h
+// \brief Header file for the dense vector/sparse vector inner product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDVECSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDVECSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (inner product) of a dense and a
+// sparse vector (\f$ s=\vec{a}*\vec{b} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side dense vector for the inner product.
+// \param rhs The right-hand side sparse vector for the inner product.
+// \return The scalar product.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the scalar product (inner product) of a dense vector and a sparse
+// vector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ blaze::DynamicVector<double,rowVector> a;
+ blaze::CompressedVector<double,columnVector> b;
+ blaze::real res;
+ // ... Resizing and initialization
+ res = a * b;
+ \endcode
+
+// The operator returns a scalar value of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator*( const DenseVector<T1,true>& lhs, const SparseVector<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef CompositeType_<T1> Lhs; // Composite type of the left-hand side dense vector expression
+ typedef CompositeType_<T2> Rhs; // Composite type of the right-hand side sparse vector expression
+ typedef RemoveReference_<Lhs> X1; // Auxiliary type for the left-hand side composite type
+ typedef RemoveReference_<Rhs> X2; // Auxiliary type for the right-hand side composite type
+ typedef ElementType_<X1> ET1; // Element type of the left-hand side dense vector expression
+ typedef ElementType_<X2> ET2; // Element type of the right-hand side sparse vector expression
+ typedef MultTrait_<ET1,ET2> MultType; // Multiplication result type
+ typedef ConstIterator_<X2> ConstIterator; // Iterator type of the right-hand sparse vector expression
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( T1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( T2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( T1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( T2 );
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ Lhs left ( ~lhs );
+ Rhs right( ~rhs );
+
+ ConstIterator element( right.begin() );
+ ConstIterator end ( right.end() );
+
+ MultType sp = MultType();
+
+ if( element != end ) {
+ sp = left[ element->index() ] * element->value();
+ ++element;
+ for( ; element!=end; ++element )
+ sp += left[ element->index() ] * element->value();
+ }
+
+ return sp;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDVecTDMatMultExpr.h b/src/cpu/blaze/math/expressions/TDVecTDMatMultExpr.h
new file mode 100644
index 00000000..6dbe65ff
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDVecTDMatMultExpr.h
@@ -0,0 +1,5439 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDVecTDMatMultExpr.h
+// \brief Header file for the transpose dense vector/transpose dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDVECTDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDVECTDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/blas/gemv.h>
+#include <blaze/math/blas/trmv.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/math/expressions/VecScalarMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/BLAS.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDVECTDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense vector-transpose dense matrix multiplications.
+// \ingroup dense_vector_expression
+//
+// The TDVecTDMatMultExpr class represents the compile time expression for multiplications
+// between transpose dense vectors and column-major dense matrices.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename MT > // Type of the right-hand side dense matrix
+class TDVecTDMatMultExpr : public DenseVector< TDVecTDMatMultExpr<VT,MT>, true >
+ , private TVecMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the left-hand side dense vector epxression.
+ typedef ElementType_<MRT> MET; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
+ IsBLASCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the vector or the matrix operand requires an intermediate
+ evaluation, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateVector || evaluateMatrix ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types and the matrix type are suited for a BLAS kernel,
+ the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types and the matrix type are suited for a vectorized
+ computation of the vector/matrix multiplication, the nested \a value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDVecTDMatMultExpr<VT,MT> This; //!< Type of this TDVecTDMatMultExpr instance.
+ typedef MultTrait_<VRT,MRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ VT::simdEnabled && MT::simdEnabled &&
+ HasSIMDAdd<VET,MET>::value &&
+ HasSIMDMult<VET,MET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDVecTDMatMultExpr class.
+ //
+ // \param vec The left-hand side vector operand of the multiplication expression.
+ // \param mat The right-hand side matrix operand of the multiplication expression.
+ */
+ explicit inline TDVecTDMatMultExpr( const VT& vec, const MT& mat ) noexcept
+ : vec_( vec ) // Left-hand side dense vector of the multiplication expression
+ , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return vec_[index] * mat_(index,index);
+ }
+ else if( IsLower<MT>::value && ( index > 8UL ) )
+ {
+ const size_t begin( IsStrictlyLower<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.rows() - begin );
+ return subvector( vec_, begin, n ) * subvector( column( mat_, index ), begin, n );
+ }
+ else if( IsUpper<MT>::value && ( index + 8UL < mat_.rows() ) )
+ {
+ const size_t n( IsStrictlyUpper<MT>::value ? index : index+1UL );
+ return subvector( vec_, 0UL, n ) * subvector( column( mat_, index ), 0UL, n );
+ }
+ else
+ {
+ return vec_ * column( mat_, index );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return vec_.isAligned() && mat_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( mat_.rows() * mat_.columns() < TDVECTDMATMULT_THRESHOLD ) ) &&
+ ( size() > SMP_TDVECTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vec_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand mat_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense vector-transpose dense matrix multiplication to a
+ // transpose dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense vector-
+ // transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+ else if( rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecTDMatMultExpr::selectAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors (kernel selection)**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a transpose dense vector-transpose
+ // dense matrix multiplication to a dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( y, x, A );
+ else
+ selectBlasAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense vector-transpose dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose dense vector-
+ // transpose dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ y.assign( x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (small matrices)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a small transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the transpose dense
+ // vector-transpose dense matrix multiplication. This kernel is optimized for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+7UL);
+ }
+
+ y[j ] = sum( xmm1 );
+ y[j+1UL] = sum( xmm2 );
+ y[j+2UL] = sum( xmm3 );
+ y[j+3UL] = sum( xmm4 );
+ y[j+4UL] = sum( xmm5 );
+ y[j+5UL] = sum( xmm6 );
+ y[j+6UL] = sum( xmm7 );
+ y[j+7UL] = sum( xmm8 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ y[j+4UL] += x[i] * A(i,j+4UL);
+ y[j+5UL] += x[i] * A(i,j+5UL);
+ y[j+6UL] += x[i] * A(i,j+6UL);
+ y[j+7UL] += x[i] * A(i,j+7UL);
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ }
+
+ y[j ] = sum( xmm1 );
+ y[j+1UL] = sum( xmm2 );
+ y[j+2UL] = sum( xmm3 );
+ y[j+3UL] = sum( xmm4 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ }
+ }
+
+ for( ; (j+3UL) <= N; j+=3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+2UL : j+3UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ }
+
+ y[j ] = sum( xmm1 );
+ y[j+1UL] = sum( xmm2 );
+ y[j+2UL] = sum( xmm3 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ }
+
+ y[j ] = sum( xmm1 );
+ y[j+1UL] = sum( xmm2 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ xmm1 = xmm1 + x.load(i) * A.load(i,j);
+ }
+
+ y[j] = sum( xmm1 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] += x[i] * A(i,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose dense
+ // vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (large matrices)*****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default assignment of a large transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the transpose dense
+ // vector-transpose dense matrix multiplication. This kernel is optimized for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ reset( y );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) + x3 * A.load(i2,j+4UL) + x4 * A.load(i3,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) + x3 * A.load(i2,j+5UL) + x4 * A.load(i3,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) + x3 * A.load(i2,j+6UL) + x4 * A.load(i3,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) + x3 * A.load(i2,j+7UL) + x4 * A.load(i3,j+7UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ y[j+4UL] += x[i] * A(i,j+4UL);
+ y[j+5UL] += x[i] * A(i,j+5UL);
+ y[j+6UL] += x[i] * A(i,j+6UL);
+ y[j+7UL] += x[i] * A(i,j+7UL);
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j] += sum( x1 * A.load(i,j) + x2 * A.load(i1,j) + x3 * A.load(i2,j) + x4 * A.load(i3,j) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j] += sum( x1 * A.load(i,j) + x2 * A.load(i1,j) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j] += sum( x1 * A.load(i,j) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] += x[i] * A(i,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors (default)********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose dense vector-transpose dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectLargeAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors******************************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based assignment of a transpose dense vector-transpose dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function performs the transpose dense vector-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ assign( y, x );
+ trmv( y, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ }
+ else {
+ gemv( y, x, A, ET(1), ET(0) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose dense vector-transpose dense matrix multiplication to a
+ // transpose sparse vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense vector-
+ // transpose dense matrix multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose dense vector-transpose dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose dense
+ // vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecTDMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors (kernel selection)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a transpose dense vector-
+ // transpose dense matrix multiplication to a dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( y, x, A );
+ else
+ selectBlasAddAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose dense
+ // vector-transpose dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ y.addAssign( x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (small matrices)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultAddAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (small matrices)********************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a small transpose dense vector-transpose
+ // dense matrix multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the
+ // transpose dense vector-transpose dense matrix multiplication. This kernel is optimized
+ // for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+7UL);
+ }
+
+ y[j ] += sum( xmm1 );
+ y[j+1UL] += sum( xmm2 );
+ y[j+2UL] += sum( xmm3 );
+ y[j+3UL] += sum( xmm4 );
+ y[j+4UL] += sum( xmm5 );
+ y[j+5UL] += sum( xmm6 );
+ y[j+6UL] += sum( xmm7 );
+ y[j+7UL] += sum( xmm8 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ y[j+4UL] += x[i] * A(i,j+4UL);
+ y[j+5UL] += x[i] * A(i,j+5UL);
+ y[j+6UL] += x[i] * A(i,j+6UL);
+ y[j+7UL] += x[i] * A(i,j+7UL);
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ }
+
+ y[j ] += sum( xmm1 );
+ y[j+1UL] += sum( xmm2 );
+ y[j+2UL] += sum( xmm3 );
+ y[j+3UL] += sum( xmm4 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ }
+ }
+
+ for( ; (j+3UL) <= N; j+=3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+2UL : j+3UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ }
+
+ y[j ] += sum( xmm1 );
+ y[j+1UL] += sum( xmm2 );
+ y[j+2UL] += sum( xmm3 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ }
+
+ y[j ] += sum( xmm1 );
+ y[j+1UL] += sum( xmm2 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(i);
+ }
+
+ y[j] += sum( xmm1 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] += x[i] * A(i,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (large matrices)*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultAddAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (large matrices)********************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default addition assignment of a large transpose dense vector-transpose
+ // dense matrix multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the
+ // transpose dense vector-transpose dense matrix multiplication. This kernel is optimized
+ // for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) + x3 * A.load(i2,j+4UL) + x4 * A.load(i3,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) + x3 * A.load(i2,j+5UL) + x4 * A.load(i3,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) + x3 * A.load(i2,j+6UL) + x4 * A.load(i3,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) + x3 * A.load(i2,j+7UL) + x4 * A.load(i3,j+7UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ y[j+4UL] += x[i] * A(i,j+4UL);
+ y[j+5UL] += x[i] * A(i,j+5UL);
+ y[j+6UL] += x[i] * A(i,j+6UL);
+ y[j+7UL] += x[i] * A(i,j+7UL);
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j] += sum( x1 * A.load(i,j) + x2 * A.load(i1,j) + x3 * A.load(i2,j) + x4 * A.load(i3,j) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j] += sum( x1 * A.load(i,j) + x2 * A.load(i1,j) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j] += sum( x1 * A.load(i,j) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] += x[i] * A(i,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors (default)***********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectLargeAddAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors*********************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based addition assignment of a vector-matrix multiplication
+ // (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function performs the transpose dense vector-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ addAssign( y, tmp );
+ }
+ else {
+ gemv( y, x, A, ET(1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ TDVecTDMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors (kernel selection)**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for a subtraction assignment of a transpose dense vector-
+ // transpose dense matrix multiplication to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( y, x, A );
+ else
+ selectBlasSubAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose dense
+ // vector-transpose dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ y.subAssign( x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (small matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultSubAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (small matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a small transpose dense vector-transpose
+ // dense matrix multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // transpose dense vector-transpose dense matrix multiplication. This kernel is optimized
+ // for small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectSmallSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+7UL);
+ }
+
+ y[j ] -= sum( xmm1 );
+ y[j+1UL] -= sum( xmm2 );
+ y[j+2UL] -= sum( xmm3 );
+ y[j+3UL] -= sum( xmm4 );
+ y[j+4UL] -= sum( xmm5 );
+ y[j+5UL] -= sum( xmm6 );
+ y[j+6UL] -= sum( xmm7 );
+ y[j+7UL] -= sum( xmm8 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j );
+ y[j+1UL] -= x[i] * A(i,j+1UL);
+ y[j+2UL] -= x[i] * A(i,j+2UL);
+ y[j+3UL] -= x[i] * A(i,j+3UL);
+ y[j+4UL] -= x[i] * A(i,j+4UL);
+ y[j+5UL] -= x[i] * A(i,j+5UL);
+ y[j+6UL] -= x[i] * A(i,j+6UL);
+ y[j+7UL] -= x[i] * A(i,j+7UL);
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ }
+
+ y[j ] -= sum( xmm1 );
+ y[j+1UL] -= sum( xmm2 );
+ y[j+2UL] -= sum( xmm3 );
+ y[j+3UL] -= sum( xmm4 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j );
+ y[j+1UL] -= x[i] * A(i,j+1UL);
+ y[j+2UL] -= x[i] * A(i,j+2UL);
+ y[j+3UL] -= x[i] * A(i,j+3UL);
+ }
+ }
+
+ for( ; (j+3UL) <= N; j+=3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+2UL : j+3UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ }
+
+ y[j ] -= sum( xmm1 );
+ y[j+1UL] -= sum( xmm2 );
+ y[j+2UL] -= sum( xmm3 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j );
+ y[j+1UL] -= x[i] * A(i,j+1UL);
+ y[j+2UL] -= x[i] * A(i,j+2UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ }
+
+ y[j ] -= sum( xmm1 );
+ y[j+1UL] -= sum( xmm2 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j );
+ y[j+1UL] -= x[i] * A(i,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(i);
+ }
+
+ y[j] -= sum( xmm1 );
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] -= x[i] * A(i,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (large matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectDefaultSubAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (large matrices)*****************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized default subtraction assignment of a large transpose dense vector-transpose
+ // dense matrix multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the
+ // transpose dense vector-transpose dense matrix multiplication. This kernel is optimized
+ // for large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1> >
+ selectLargeSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) );
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) );
+ y[j+4UL] -= sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) + x3 * A.load(i2,j+4UL) + x4 * A.load(i3,j+4UL) );
+ y[j+5UL] -= sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) + x3 * A.load(i2,j+5UL) + x4 * A.load(i3,j+5UL) );
+ y[j+6UL] -= sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) + x3 * A.load(i2,j+6UL) + x4 * A.load(i3,j+6UL) );
+ y[j+7UL] -= sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) + x3 * A.load(i2,j+7UL) + x4 * A.load(i3,j+7UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) );
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) );
+ y[j+4UL] -= sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) );
+ y[j+5UL] -= sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) );
+ y[j+6UL] -= sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) );
+ y[j+7UL] -= sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] -= sum( x1 * A.load(i,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) );
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) );
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) );
+ y[j+4UL] -= sum( x1 * A.load(i,j+4UL) );
+ y[j+5UL] -= sum( x1 * A.load(i,j+5UL) );
+ y[j+6UL] -= sum( x1 * A.load(i,j+6UL) );
+ y[j+7UL] -= sum( x1 * A.load(i,j+7UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j );
+ y[j+1UL] -= x[i] * A(i,j+1UL);
+ y[j+2UL] -= x[i] * A(i,j+2UL);
+ y[j+3UL] -= x[i] * A(i,j+3UL);
+ y[j+4UL] -= x[i] * A(i,j+4UL);
+ y[j+5UL] -= x[i] * A(i,j+5UL);
+ y[j+6UL] -= x[i] * A(i,j+6UL);
+ y[j+7UL] -= x[i] * A(i,j+7UL);
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) );
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) );
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] -= sum( x1 * A.load(i,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) );
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) );
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j );
+ y[j+1UL] -= x[i] * A(i,j+1UL);
+ y[j+2UL] -= x[i] * A(i,j+2UL);
+ y[j+3UL] -= x[i] * A(i,j+3UL);
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] -= sum( x1 * A.load(i,j ) );
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j );
+ y[j+1UL] -= x[i] * A(i,j+1UL);
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j] -= sum( x1 * A.load(i,j) + x2 * A.load(i1,j) + x3 * A.load(i2,j) + x4 * A.load(i3,j) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j] -= sum( x1 * A.load(i,j) + x2 * A.load(i1,j) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j] -= sum( x1 * A.load(i,j) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] -= x[i] * A(i,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors (default)********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ selectLargeSubAssignKernel( y, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors******************************************
+#if BLAZE_BLAS_MODE
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief BLAS-based subtraction assignment of a vector-matrix multiplication
+ // (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side transpose dense vector operand.
+ // \param A The right-hand side column-major dense matrix operand.
+ // \return void
+ //
+ // This function performs the transpose dense vector-transpose dense matrix multiplication
+ // based on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1> >
+ selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ subAssign( y, tmp );
+ }
+ else {
+ gemv( y, x, A, ET(-1), ET(1) );
+ }
+ }
+ /*! \endcond */
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Division assignment of a transpose dense vector-transpose dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense vector-transpose dense matrix multiplication to
+ // a transpose dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // vector-transpose dense matrix multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+ else if( rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose dense vector-transpose dense matrix multiplication to
+ // a transpose sparse vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // vector-transpose dense matrix multiplication expression to a sparse vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR( VT, MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DVECSCALARMULTEXPR SPECIALIZATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Expression object for scaled transpose dense vector-transpose dense matrix multiplications.
+// \ingroup dense_vector_expression
+//
+// This specialization of the DVecScalarMultExpr class represents the compile time expression
+// for scaled multiplications between a non-transpose dense vector and a column-major dense matrix.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename MT // Type of the right-hand side dense matrix
+ , typename ST > // Type of the side scalar value
+class DVecScalarMultExpr< TDVecTDMatMultExpr<VT,MT>, ST, true >
+ : public DenseVector< DVecScalarMultExpr< TDVecTDMatMultExpr<VT,MT>, ST, true >, true >
+ , private VecScalarMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef TDVecTDMatMultExpr<VT,MT> VMM; //!< Type of the dense vector-dense matrix multiplication expression.
+ typedef ResultType_<VMM> RES; //!< Result type of the dense vector-dense matrix multiplication expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the left-hand side dense vector epxression.
+ typedef ElementType_<MRT> MET; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
+ IsBLASCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the target vector is SMP assignable and either the vector or the matrix operand
+ require an intermediate evaluation, the nested \a value will be set to 1, otherwise it
+ will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = T1::smpAssignable && ( evaluateVector || evaluateMatrix ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types, the matrix type, and the scalar type are suited
+ for a BLAS kernel, the nested \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseBlasKernel {
+ enum : bool { value = BLAZE_BLAS_MODE &&
+ HasMutableDataAccess<T1>::value &&
+ HasConstDataAccess<T2>::value &&
+ HasConstDataAccess<T3>::value &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ IsBLASCompatible< ElementType_<T1> >::value &&
+ IsBLASCompatible< ElementType_<T2> >::value &&
+ IsBLASCompatible< ElementType_<T3> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T2> >::value &&
+ IsSame< ElementType_<T1>, ElementType_<T3> >::value &&
+ !( IsBuiltin< ElementType_<T1> >::value && IsComplex<T4>::value ) };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the two involved vector types, the matrix type, and the scalar type are suited
+ for a vectorized computation of the scaled vector/matrix multiplication, the nested
+ \a value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3, typename T4 >
+ struct UseVectorizedDefaultKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T2::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3>
+ , T4 >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef DVecScalarMultExpr<VMM,ST,true> This; //!< Type of this DVecScalarMultExpr instance.
+ typedef MultTrait_<RES,ST> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef const TDVecTDMatMultExpr<VT,MT> LeftOperand;
+
+ //! Composite type of the right-hand side scalar value.
+ typedef ST RightOperand;
+
+ //! Type for the assignment of the dense vector operand of the left-hand side expression.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Type for the assignment of the dense matrix operand of the left-hand side expression.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ VT::simdEnabled && MT::simdEnabled &&
+ AreSIMDCombinable<VET,MET,ST>::value &&
+ HasSIMDAdd<VET,MET>::value &&
+ HasSIMDMult<VET,MET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the DVecScalarMultExpr class.
+ //
+ // \param vector The left-hand side dense vector of the multiplication expression.
+ // \param scalar The right-hand side scalar of the multiplication expression.
+ */
+ explicit inline DVecScalarMultExpr( const VMM& vector, ST scalar )
+ : vector_( vector ) // Left-hand side dense vector of the multiplication expression
+ , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
+ return vector_[index] * scalar_;
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= vector_.size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const {
+ return vector_.size();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const {
+ return vector_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side scalar operand.
+ //
+ // \return The right-hand side scalar operand.
+ */
+ inline RightOperand rightOperand() const {
+ return scalar_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const {
+ return vector_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const {
+ RightOperand_<VMM> A( vector_.rightOperand() );
+ return ( !BLAZE_BLAS_IS_PARALLEL ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) ) &&
+ ( size() > SMP_TDVECTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vector_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*!\brief Assignment of a scaled transpose dense vector-transpose dense matrix multiplication
+ // to a transpose dense vector (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline void assign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+ else if( right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectAssignKernel( ~lhs, x, A, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors (kernel selection)**********************************************
+ /*!\brief Selection of the kernel for an assignment of a scaled transpose dense vector-transpose
+ // dense matrix multiplication to a dense vector (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
+ selectSmallAssignKernel( y, x, A, scalar );
+ else
+ selectBlasAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*!\brief Default assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the scaled transpose dense vector-
+ // transpose dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ y.assign( x * A * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (small matrices)****************************************
+ /*!\brief Default assignment of a small scaled transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (small matrices)*****************************
+ /*!\brief Vectorized default assignment of a small scaled transpose dense vector-transpose
+ // dense matrix multiplication (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the scaled transpose
+ // dense vector-transpose dense matrix multiplication. This kernel is optimized for small
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+7UL);
+ }
+
+ y[j ] = sum( xmm1 ) * scalar;
+ y[j+1UL] = sum( xmm2 ) * scalar;
+ y[j+2UL] = sum( xmm3 ) * scalar;
+ y[j+3UL] = sum( xmm4 ) * scalar;
+ y[j+4UL] = sum( xmm5 ) * scalar;
+ y[j+5UL] = sum( xmm6 ) * scalar;
+ y[j+6UL] = sum( xmm7 ) * scalar;
+ y[j+7UL] = sum( xmm8 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] += x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] += x[i] * A(i,j+3UL) * scalar;
+ y[j+4UL] += x[i] * A(i,j+4UL) * scalar;
+ y[j+5UL] += x[i] * A(i,j+5UL) * scalar;
+ y[j+6UL] += x[i] * A(i,j+6UL) * scalar;
+ y[j+7UL] += x[i] * A(i,j+7UL) * scalar;
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ }
+
+ y[j ] = sum( xmm1 ) * scalar;
+ y[j+1UL] = sum( xmm2 ) * scalar;
+ y[j+2UL] = sum( xmm3 ) * scalar;
+ y[j+3UL] = sum( xmm4 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] += x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] += x[i] * A(i,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+3UL) <= N; j+=3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+2UL : j+3UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ }
+
+ y[j ] = sum( xmm1 ) * scalar;
+ y[j+1UL] = sum( xmm2 ) * scalar;
+ y[j+2UL] = sum( xmm3 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] += x[i] * A(i,j+2UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ }
+
+ y[j ] = sum( xmm1 ) * scalar;
+ y[j+1UL] = sum( xmm2 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(i);
+ }
+
+ y[j] = sum( xmm1 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] += x[i] * A(i,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors (large matrices)****************************************
+ /*!\brief Default assignment of a large scaled transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a scaled transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default assignment to dense vectors (large matrices)*****************************
+ /*!\brief Vectorized default assignment of a large scaled transpose dense vector-transpose
+ // dense matrix multiplication (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default assignment kernel for the scaled transpose
+ // dense vector-transpose dense matrix multiplication. This kernel is optimized for large
+ // matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ reset( y );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) + x3 * A.load(i2,j+4UL) + x4 * A.load(i3,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) + x3 * A.load(i2,j+5UL) + x4 * A.load(i3,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) + x3 * A.load(i2,j+6UL) + x4 * A.load(i3,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) + x3 * A.load(i2,j+7UL) + x4 * A.load(i3,j+7UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) );
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) );
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) );
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) );
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ y[j+4UL] += x[i] * A(i,j+4UL);
+ y[j+5UL] += x[i] * A(i,j+5UL);
+ y[j+6UL] += x[i] * A(i,j+6UL);
+ y[j+7UL] += x[i] * A(i,j+7UL);
+ }
+
+ y[j ] *= scalar;
+ y[j+1UL] *= scalar;
+ y[j+2UL] *= scalar;
+ y[j+3UL] *= scalar;
+ y[j+4UL] *= scalar;
+ y[j+5UL] *= scalar;
+ y[j+6UL] *= scalar;
+ y[j+7UL] *= scalar;
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) );
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ y[j+2UL] += x[i] * A(i,j+2UL);
+ y[j+3UL] += x[i] * A(i,j+3UL);
+ }
+
+ y[j ] *= scalar;
+ y[j+1UL] *= scalar;
+ y[j+2UL] *= scalar;
+ y[j+3UL] *= scalar;
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) );
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j );
+ y[j+1UL] += x[i] * A(i,j+1UL);
+ }
+
+ y[j ] *= scalar;
+ y[j+1UL] *= scalar;
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j] += sum( x1 * A.load(i,j) + x2 * A.load(i1,j) + x3 * A.load(i2,j) + x4 * A.load(i3,j) );
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j] += sum( x1 * A.load(i,j) + x2 * A.load(i1,j) );
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j] += sum( x1 * A.load(i,j) );
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] += x[i] * A(i,j);
+ }
+
+ y[j] *= scalar;
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors (default)********************************************
+ /*!\brief Default assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a large scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectLargeAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based assignment to dense vectors******************************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense vector-transpose dense matrix
+ // multiplication based on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ assign( y, scalar * x );
+ trmv( y, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ }
+ else {
+ gemv( y, x, A, ET(scalar), ET(0) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*!\brief Assignment of a scaled transpose dense vector-transpose dense matrix multiplication
+ // to a transpose sparse vector (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a scaled transpose dense
+ // vector-transpose dense matrix multiplication expression to a sparse vector.
+ */
+ template< typename VT1 // Type of the target sparse vector
+ , bool TF > // Transpose flag of the target sparse vector
+ friend inline void assign( SparseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*!\brief Addition assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a scaled transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL || right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectAddAssignKernel( ~lhs, x, A, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors (kernel selection)*************************************
+ /*!\brief Selection of the kernel for an addition assignment of a scaled transpose dense vector-
+ // transpose dense matrix multiplication to a dense vector (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
+ selectSmallAddAssignKernel( y, x, A, scalar );
+ else
+ selectBlasAddAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*!\brief Default addition assignment of a scaled transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the scaled transpose
+ // dense vector-transpose dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ y.addAssign( x * A * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (small matrices)*******************************
+ /*!\brief Default addition assignment of a small scaled transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (small matrices)********************
+ /*!\brief Vectorized default addition assignment of a small scaled transpose dense vector-
+ // transpose dense matrix multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the scaled
+ // transpose dense vector-transpose dense matrix multiplication. This kernel is optimized for
+ // small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+7UL);
+ }
+
+ y[j ] += sum( xmm1 ) * scalar;
+ y[j+1UL] += sum( xmm2 ) * scalar;
+ y[j+2UL] += sum( xmm3 ) * scalar;
+ y[j+3UL] += sum( xmm4 ) * scalar;
+ y[j+4UL] += sum( xmm5 ) * scalar;
+ y[j+5UL] += sum( xmm6 ) * scalar;
+ y[j+6UL] += sum( xmm7 ) * scalar;
+ y[j+7UL] += sum( xmm8 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] += x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] += x[i] * A(i,j+3UL) * scalar;
+ y[j+4UL] += x[i] * A(i,j+4UL) * scalar;
+ y[j+5UL] += x[i] * A(i,j+5UL) * scalar;
+ y[j+6UL] += x[i] * A(i,j+6UL) * scalar;
+ y[j+7UL] += x[i] * A(i,j+7UL) * scalar;
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ }
+
+ y[j ] += sum( xmm1 ) * scalar;
+ y[j+1UL] += sum( xmm2 ) * scalar;
+ y[j+2UL] += sum( xmm3 ) * scalar;
+ y[j+3UL] += sum( xmm4 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] += x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] += x[i] * A(i,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+3UL) <= N; j+=3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+2UL : j+3UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ }
+
+ y[j ] += sum( xmm1 ) * scalar;
+ y[j+1UL] += sum( xmm2 ) * scalar;
+ y[j+2UL] += sum( xmm3 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] += x[i] * A(i,j+2UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ }
+
+ y[j ] += sum( xmm1 ) * scalar;
+ y[j+1UL] += sum( xmm2 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(i);
+ }
+
+ y[j] += sum( xmm1 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] += x[i] * A(i,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors (large matrices)*******************************
+ /*!\brief Default addition assignment of a large scaled transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultAddAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default addition assignment to dense vectors (large matrices)********************
+ /*!\brief Vectorized default addition assignment of a large scaled transpose dense vector-
+ // transpose dense matrix multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default addition assignment kernel for the scaled
+ // transpose dense vector-transpose dense matrix multiplication. This kernel is optimized for
+ // large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) ) * scalar;
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) ) * scalar;
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) ) * scalar;
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) + x3 * A.load(i2,j+4UL) + x4 * A.load(i3,j+4UL) ) * scalar;
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) + x3 * A.load(i2,j+5UL) + x4 * A.load(i3,j+5UL) ) * scalar;
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) + x3 * A.load(i2,j+6UL) + x4 * A.load(i3,j+6UL) ) * scalar;
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) + x3 * A.load(i2,j+7UL) + x4 * A.load(i3,j+7UL) ) * scalar;
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) ) * scalar;
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) ) * scalar;
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) ) * scalar;
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) ) * scalar;
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) ) * scalar;
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) ) * scalar;
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) ) * scalar;
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) ) * scalar;
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) ) * scalar;
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) ) * scalar;
+ y[j+4UL] += sum( x1 * A.load(i,j+4UL) ) * scalar;
+ y[j+5UL] += sum( x1 * A.load(i,j+5UL) ) * scalar;
+ y[j+6UL] += sum( x1 * A.load(i,j+6UL) ) * scalar;
+ y[j+7UL] += sum( x1 * A.load(i,j+7UL) ) * scalar;
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] += x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] += x[i] * A(i,j+3UL) * scalar;
+ y[j+4UL] += x[i] * A(i,j+4UL) * scalar;
+ y[j+5UL] += x[i] * A(i,j+5UL) * scalar;
+ y[j+6UL] += x[i] * A(i,j+6UL) * scalar;
+ y[j+7UL] += x[i] * A(i,j+7UL) * scalar;
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) ) * scalar;
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) ) * scalar;
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) ) * scalar;
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) ) * scalar;
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) ) * scalar;
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) ) * scalar;
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) ) * scalar;
+ y[j+2UL] += sum( x1 * A.load(i,j+2UL) ) * scalar;
+ y[j+3UL] += sum( x1 * A.load(i,j+3UL) ) * scalar;
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] += x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] += x[i] * A(i,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) ) * scalar;
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] += sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) ) * scalar;
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] += sum( x1 * A.load(i,j ) ) * scalar;
+ y[j+1UL] += sum( x1 * A.load(i,j+1UL) ) * scalar;
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] += x[i] * A(i,j ) * scalar;
+ y[j+1UL] += x[i] * A(i,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j] += sum( x1 * A.load(i,j) + x2 * A.load(i1,j) + x3 * A.load(i2,j) + x4 * A.load(i3,j) ) * scalar;
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j] += sum( x1 * A.load(i,j) + x2 * A.load(i1,j) ) * scalar;
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j] += sum( x1 * A.load(i,j) ) * scalar;
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] += x[i] * A(i,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors (default)***********************************
+ /*!\brief Default addition assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a large
+ // scaled transpose dense vector-transpose dense matrix multiplication expression to a dense
+ // vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectLargeAddAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based addition assignment to dense vectors*********************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based addition assignment of a scaled transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor
+ // \return void
+ //
+ // This function performs the scaled transpose dense vector-transpose dense matrix
+ // multiplication based on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( scalar * x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ addAssign( y, tmp );
+ }
+ else {
+ gemv( y, x, A, ET(scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*!\brief Subtraction assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL || right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
+ RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ DVecScalarMultExpr::selectSubAssignKernel( ~lhs, x, A, rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors (kernel selection)**********************************
+ /*!\brief Selection of the kernel for a subtraction assignment of a scaled transpose dense vector-
+ // transpose dense matrix multiplication to a dense vector (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ if( ( IsDiagonal<MT1>::value ) ||
+ ( IsComputation<MT>::value && !evaluateMatrix ) ||
+ ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
+ selectSmallSubAssignKernel( y, x, A, scalar );
+ else
+ selectBlasSubAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the scaled transpose
+ // dense vector-transpose dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline void selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ y.subAssign( x * A * scalar );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (small matrices)****************************
+ /*!\brief Default subtraction assignment of a small scaled transpose dense vector-transpose
+ // dense matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (small matrices)*****************
+ /*!\brief Vectorized default subtraction assignment of a small scaled transpose dense vector-
+ // transpose matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the scaled
+ // transpose dense vector-transpose dense matrix multiplication. This kernel is optimized for
+ // small matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectSmallSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ xmm5 = xmm5 + x1 * A.load(i,j+4UL);
+ xmm6 = xmm6 + x1 * A.load(i,j+5UL);
+ xmm7 = xmm7 + x1 * A.load(i,j+6UL);
+ xmm8 = xmm8 + x1 * A.load(i,j+7UL);
+ }
+
+ y[j ] -= sum( xmm1 ) * scalar;
+ y[j+1UL] -= sum( xmm2 ) * scalar;
+ y[j+2UL] -= sum( xmm3 ) * scalar;
+ y[j+3UL] -= sum( xmm4 ) * scalar;
+ y[j+4UL] -= sum( xmm5 ) * scalar;
+ y[j+5UL] -= sum( xmm6 ) * scalar;
+ y[j+6UL] -= sum( xmm7 ) * scalar;
+ y[j+7UL] -= sum( xmm8 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j ) * scalar;
+ y[j+1UL] -= x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] -= x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] -= x[i] * A(i,j+3UL) * scalar;
+ y[j+4UL] -= x[i] * A(i,j+4UL) * scalar;
+ y[j+5UL] -= x[i] * A(i,j+5UL) * scalar;
+ y[j+6UL] -= x[i] * A(i,j+6UL) * scalar;
+ y[j+7UL] -= x[i] * A(i,j+7UL) * scalar;
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3, xmm4;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ xmm4 = xmm4 + x1 * A.load(i,j+3UL);
+ }
+
+ y[j ] -= sum( xmm1 ) * scalar;
+ y[j+1UL] -= sum( xmm2 ) * scalar;
+ y[j+2UL] -= sum( xmm3 ) * scalar;
+ y[j+3UL] -= sum( xmm4 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j ) * scalar;
+ y[j+1UL] -= x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] -= x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] -= x[i] * A(i,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+3UL) <= N; j+=3UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+2UL : j+3UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2, xmm3;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ xmm3 = xmm3 + x1 * A.load(i,j+2UL);
+ }
+
+ y[j ] -= sum( xmm1 ) * scalar;
+ y[j+1UL] -= sum( xmm2 ) * scalar;
+ y[j+2UL] -= sum( xmm3 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j ) * scalar;
+ y[j+1UL] -= x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] -= x[i] * A(i,j+2UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1, xmm2;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ xmm1 = xmm1 + x1 * A.load(i,j );
+ xmm2 = xmm2 + x1 * A.load(i,j+1UL);
+ }
+
+ y[j ] -= sum( xmm1 ) * scalar;
+ y[j+1UL] -= sum( xmm2 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j ) * scalar;
+ y[j+1UL] -= x[i] * A(i,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ SIMDType xmm1;
+ size_t i( ibegin );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ xmm1 = xmm1 + A.load(i,j) * x.load(i);
+ }
+
+ y[j] -= sum( xmm1 ) * scalar;
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] -= x[i] * A(i,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors (large matrices)****************************
+ /*!\brief Default subtraction assignment of a large scaled transpose dense vector-transpose
+ // dense matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectDefaultSubAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**Vectorized default subtraction assignment to dense vectors (large matrices)*****************
+ /*!\brief Vectorized default subtraction assignment of a large scaled transpose dense vector-
+ // transpose matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function implements the vectorized default subtraction assignment kernel for the scaled
+ // transpose dense vector-transpose dense matrix multiplication. This kernel is optimized for
+ // large matrices.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >
+ selectLargeSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ const size_t M( A.rows() );
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT2>::value || !IsPadded<MT1>::value );
+
+ size_t j( 0UL );
+
+ for( ; (j+8UL) <= N; j+=8UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+7UL : j+8UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) ) * scalar;
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) ) * scalar;
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) ) * scalar;
+ y[j+4UL] -= sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) + x3 * A.load(i2,j+4UL) + x4 * A.load(i3,j+4UL) ) * scalar;
+ y[j+5UL] -= sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) + x3 * A.load(i2,j+5UL) + x4 * A.load(i3,j+5UL) ) * scalar;
+ y[j+6UL] -= sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) + x3 * A.load(i2,j+6UL) + x4 * A.load(i3,j+6UL) ) * scalar;
+ y[j+7UL] -= sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) + x3 * A.load(i2,j+7UL) + x4 * A.load(i3,j+7UL) ) * scalar;
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) ) * scalar;
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) ) * scalar;
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) ) * scalar;
+ y[j+4UL] -= sum( x1 * A.load(i,j+4UL) + x2 * A.load(i1,j+4UL) ) * scalar;
+ y[j+5UL] -= sum( x1 * A.load(i,j+5UL) + x2 * A.load(i1,j+5UL) ) * scalar;
+ y[j+6UL] -= sum( x1 * A.load(i,j+6UL) + x2 * A.load(i1,j+6UL) ) * scalar;
+ y[j+7UL] -= sum( x1 * A.load(i,j+7UL) + x2 * A.load(i1,j+7UL) ) * scalar;
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] -= sum( x1 * A.load(i,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) ) * scalar;
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) ) * scalar;
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) ) * scalar;
+ y[j+4UL] -= sum( x1 * A.load(i,j+4UL) ) * scalar;
+ y[j+5UL] -= sum( x1 * A.load(i,j+5UL) ) * scalar;
+ y[j+6UL] -= sum( x1 * A.load(i,j+6UL) ) * scalar;
+ y[j+7UL] -= sum( x1 * A.load(i,j+7UL) ) * scalar;
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j ) * scalar;
+ y[j+1UL] -= x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] -= x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] -= x[i] * A(i,j+3UL) * scalar;
+ y[j+4UL] -= x[i] * A(i,j+4UL) * scalar;
+ y[j+5UL] -= x[i] * A(i,j+5UL) * scalar;
+ y[j+6UL] -= x[i] * A(i,j+6UL) * scalar;
+ y[j+7UL] -= x[i] * A(i,j+7UL) * scalar;
+ }
+ }
+
+ for( ; (j+4UL) <= N; j+=4UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+3UL : j+4UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) ) * scalar;
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) + x3 * A.load(i2,j+2UL) + x4 * A.load(i3,j+2UL) ) * scalar;
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) + x3 * A.load(i2,j+3UL) + x4 * A.load(i3,j+3UL) ) * scalar;
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) ) * scalar;
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) + x2 * A.load(i1,j+2UL) ) * scalar;
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) + x2 * A.load(i1,j+3UL) ) * scalar;
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] -= sum( x1 * A.load(i,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) ) * scalar;
+ y[j+2UL] -= sum( x1 * A.load(i,j+2UL) ) * scalar;
+ y[j+3UL] -= sum( x1 * A.load(i,j+3UL) ) * scalar;
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j ) * scalar;
+ y[j+1UL] -= x[i] * A(i,j+1UL) * scalar;
+ y[j+2UL] -= x[i] * A(i,j+2UL) * scalar;
+ y[j+3UL] -= x[i] * A(i,j+3UL) * scalar;
+ }
+ }
+
+ for( ; (j+2UL) <= N; j+=2UL )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j+1UL : j+2UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) + x3 * A.load(i2,j ) + x4 * A.load(i3,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) + x3 * A.load(i2,j+1UL) + x4 * A.load(i3,j+1UL) ) * scalar;
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j ] -= sum( x1 * A.load(i,j ) + x2 * A.load(i1,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) + x2 * A.load(i1,j+1UL) ) * scalar;
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j ] -= sum( x1 * A.load(i,j ) ) * scalar;
+ y[j+1UL] -= sum( x1 * A.load(i,j+1UL) ) * scalar;
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j ] -= x[i] * A(i,j ) * scalar;
+ y[j+1UL] -= x[i] * A(i,j+1UL) * scalar;
+ }
+ }
+
+ if( j < N )
+ {
+ const size_t ibegin( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? j : j+1UL )
+ :( M ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( remainder ? ( iend & size_t(-SIMDSIZE) ) : iend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const size_t i2( i+SIMDSIZE*2UL );
+ const size_t i3( i+SIMDSIZE*3UL );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ const SIMDType x3( x.load(i2) );
+ const SIMDType x4( x.load(i3) );
+ y[j] -= sum( x1 * A.load(i,j) + x2 * A.load(i1,j) + x3 * A.load(i2,j) + x4 * A.load(i3,j) ) * scalar;
+ }
+
+ for( ; (i+SIMDSIZE) < ipos; i+=SIMDSIZE*2UL ) {
+ const size_t i1( i+SIMDSIZE );
+ const SIMDType x1( x.load(i ) );
+ const SIMDType x2( x.load(i1) );
+ y[j] -= sum( x1 * A.load(i,j) + x2 * A.load(i1,j) ) * scalar;
+ }
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ const SIMDType x1( x.load(i) );
+ y[j] -= sum( x1 * A.load(i,j) ) * scalar;
+ }
+
+ for( ; remainder && i<iend; ++i ) {
+ y[j] -= x[i] * A(i,j) * scalar;
+ }
+ }
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors (default)********************************
+ /*!\brief Default subtraction assignment of a scaled transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a large
+ // scaled transpose dense vector-transpose dense matrix multiplication expression to a dense
+ // vector.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline DisableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ selectLargeSubAssignKernel( y, x, A, scalar );
+ }
+ //**********************************************************************************************
+
+ //**BLAS-based subtraction assignment to dense vectors******************************************
+#if BLAZE_BLAS_MODE
+ /*!\brief BLAS-based subtraction assignment of a scaled transpose dense vector-transpose dense
+ // matrix multiplication (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side dense vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \param scalar The scaling factor.
+ // \return void
+ //
+ // This function performs the scaled transpose dense vector-transpose dense matrix
+ // multiplication based on the according BLAS functionality.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 // Type of the right-hand side matrix operand
+ , typename ST2 > // Type of the scalar value
+ static inline EnableIf_< UseBlasKernel<VT1,VT2,MT1,ST2> >
+ selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
+ {
+ typedef ElementType_<VT1> ET;
+
+ if( IsTriangular<MT1>::value ) {
+ ResultType_<VT1> tmp( serial( scalar * x ) );
+ trmv( tmp, A, ( IsLower<MT1>::value )?( CblasLower ):( CblasUpper ) );
+ subAssign( y, tmp );
+ }
+ else {
+ gemv( y, x, A, ET(-scalar), ET(1) );
+ }
+ }
+#endif
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*!\brief Multiplication assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T*=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*!\brief Division assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T/=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a scaled transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline void divAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*!\brief SMP assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense vector-transpose dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+ else if( right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( left ); // Evaluation of the left-hand side dense vector operand
+ RT A( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, x * A * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*!\brief SMP assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose sparse vector (\f$ \vec{y}^T=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a scaled transpose
+ // dense vector-transpose dense matrix multiplication expression to a sparse vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 // Type of the target sparse vector
+ , bool TF > // Transpose flag of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( SparseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*!\brief SMP addition assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T+=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL || right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( left ); // Evaluation of the left-hand side dense vector operand
+ RT A( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, x * A * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*!\brief SMP subtraction assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T-=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side scaled multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ LeftOperand_<VMM> left ( rhs.vector_.leftOperand() );
+ RightOperand_<VMM> right( rhs.vector_.rightOperand() );
+
+ if( right.rows() == 0UL || right.columns() == 0UL ) {
+ return;
+ }
+
+ LT x( left ); // Evaluation of the left-hand side dense vector operand
+ RT A( right ); // Evaluation of the right-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, x * A * rhs.scalar_ );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*!\brief SMP multiplication assignment of a scaled transpose dense vector-transpose dense
+ // matrix multiplication to a transpose dense vector (\f$ \vec{y}^T*=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*!\brief SMP division assignment of a scaled transpose dense vector-transpose dense matrix
+ // multiplication to a transpose dense vector (\f$ \vec{y}^T/=s*\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a scaled
+ // transpose dense vector-transpose dense matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 // Type of the target dense vector
+ , bool TF > // Transpose flag of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpDivAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VMM );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VMM );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector and a
+// column-major dense matrix (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+// \ingroup dense_matrix
+//
+// \param vec The left-hand side transpose dense vector for the multiplication.
+// \param mat The right-hand side column-major dense matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator represents the multiplication between a transpose dense vector and a column-major
+// dense matrix:
+
+ \code
+ using blaze::rowVector;
+ using blaze::columnMajor;
+
+ blaze::DynamicVector<double,rowVector> x, y;
+ blaze::DynamicMatrix<double,columnMajor> A;
+ // ... Resizing and initialization
+ y = x * A;
+ \endcode
+
+// The operator returns an expression representing a transpose dense vector of the higher-order
+// element type of the two involved element types \a T1::ElementType and \a T2::ElementType.
+// Both the dense matrix type \a T1 and the dense vector type \a T2 as well as the two element
+// types \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of rows of
+// the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const DisableIf_< IsMatMatMultExpr<T2>, TDVecTDMatMultExpr<T1,T2> >
+ operator*( const DenseVector<T1,true>& vec, const DenseMatrix<T2,true>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return TDVecTDMatMultExpr<T1,T2>( ~vec, ~mat );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct Size< TDVecTDMatMultExpr<VT,MT> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct IsAligned< TDVecTDMatMultExpr<VT,MT> >
+ : public BoolConstant< And< IsAligned<VT>, IsAligned<MT> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, bool AF >
+struct SubvectorExprTrait< TDVecTDMatMultExpr<VT,MT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>
+ , SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TDVecTSMatMultExpr.h b/src/cpu/blaze/math/expressions/TDVecTSMatMultExpr.h
new file mode 100644
index 00000000..52b968da
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TDVecTSMatMultExpr.h
@@ -0,0 +1,884 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TDVecTSMatMultExpr.h
+// \brief Header file for the transpose dense vector/transpose sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TDVECTSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TDVECTSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TDVECSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose dense vector-transpose sparse matrix multiplications.
+// \ingroup dense_vector_expression
+//
+// The TDVecTSMatMultExpr class represents the compile time expression for multiplications
+// between transpose dense vectors and column-major sparse matrices.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename MT > // Type of the right-hand side sparse matrix
+class TDVecTSMatMultExpr : public DenseVector< TDVecTSMatMultExpr<VT,MT>, true >
+ , private TVecMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side dense vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the multiplication expression. In case either the vector or
+ the matrix operand requires an intermediate evaluation or the dense vector expression
+ is a compound expression, \a useAssign will be set to \a true and the multiplication
+ expression will be evaluated via the \a assign function family. Otherwise \a useAssign
+ will be set to \a false and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = ( evaluateVector || evaluateMatrix ) };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the vector or the matrix operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TDVecTSMatMultExpr<VT,MT> This; //!< Type of this TDVecTSMatMultExpr instance.
+ typedef MultTrait_<VRT,MRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const TDVecTSMatMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > RightOperand;
+
+ //! Composite type of the left-hand side dense vector expression.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TDVecTSMatMultExpr class.
+ */
+ explicit inline TDVecTSMatMultExpr( const VT& vec, const MT& mat ) noexcept
+ : vec_( vec ) // Left-hand side dense vector of the multiplication expression
+ , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( vec_.size() == mat.rows(), "Invalid vector and matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
+ return vec_ * column( mat_, index );
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side dense vector operand.
+ //
+ // \return The left-hand side dense vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return vec_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_TDVECTSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vec_; //!< Left-hand side dense vector of the multiplication expression.
+ RightOperand mat_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*!\brief Assignment of a transpose dense vector-transpose sparse matrix multiplication to a
+ // dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense vector-
+ // transpose sparse matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case either the left-hand side vector operand is a compound expression or the right-hand
+ // side matrix operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operator
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ assign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*!\brief Assignment of a transpose dense vector-transpose sparse matrix multiplication to a
+ // sparse vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose dense vector-
+ // transpose sparse matrix multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case either the left-hand side vector operand is a compound expression or the right-hand
+ // side matrix operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*!\brief Addition assignment of a transpose dense vector-transpose sparse matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // dense vector-transpose sparse matrix multiplication expression to a dense vector. Due
+ // to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case either the left-hand side vector operand is a compound expression
+ // or the right-hand side matrix operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operator
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ addAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*!\brief Subtraction assignment of a transpose dense vector-transpose sparse matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // dense vector-transpose sparse matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either the left-hand side vector operand is a compound expression
+ // or the right-hand side matrix operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+
+ LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operator
+ RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ subAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*!\brief Multiplication assignment of a transpose dense vector-transpose sparse matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // dense vector-transpose sparse matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case either the left-hand side vector operand is a compound expression or the
+ // right-hand side matrix operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*!\brief Division assignment of a transpose dense vector-transpose sparse matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a transpose
+ // dense vector-transpose sparse matrix multiplication expression to a dense vector. Due
+ // to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case either the left-hand side vector operand is a compound expression
+ // or the right-hand side matrix operand requires an intermediate evaluation.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ divAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*!\brief SMP assignment of a transpose dense vector-transpose sparse matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // vector-transpose sparse matrix multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*!\brief SMP assignment of a transpose dense vector-transpose sparse matrix multiplication
+ // to a sparse vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose dense
+ // vector-transpose sparse matrix multiplication expression to a sparse vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*!\brief SMP addition assignment of a transpose dense vector-transpose sparse matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // dense vector-transpose sparse matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*!\brief SMP subtraction assignment of a transpose dense vector-transpose sparse matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // dense vector-transpose sparse matrix multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.rows() == 0UL ) {
+ return;
+ }
+
+ LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
+ RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
+
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*!\brief SMP multiplication assignment of a transpose dense vector-transpose sparse matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose dense vector-transpose sparse matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*!\brief SMP division assignment of a transpose dense vector-transpose sparse matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a transpose
+ // dense vector-transpose sparse matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,true>& lhs, const TDVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR( VT, MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose dense vector and a
+// column-major sparse matrix (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+// \ingroup sparse_matrix
+//
+// \param vec The left-hand side transpose dense vector for the multiplication.
+// \param mat The right-hand side column-major sparse matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator represents the multiplication between a transpose dense vector and a column-major
+// sparse matrix:
+
+ \code
+ using blaze::rowVector;
+ using blaze::columnMajor;
+
+ blaze::DynamicVector<double,rowVector> x, y;
+ blaze::CompressedMatrix<double,columnMajor> A;
+ // ... Resizing and initialization
+ y = x * A;
+ \endcode
+
+// The operator returns an expression representing a transpose dense vector of the higher-order
+// element type of the two involved element types \a T1::ElementType and \a T2::ElementType.
+// Both the dense matrix type \a T1 and the dense vector type \a T2 as well as the two element
+// types \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of rows of
+// the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side dense vector
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const DisableIf_< IsMatMatMultExpr<T2>, TDVecTSMatMultExpr<T1,T2> >
+ operator*( const DenseVector<T1,true>& vec, const SparseMatrix<T2,true>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return TDVecTSMatMultExpr<T1,T2>( ~vec, ~mat );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct Size< TDVecTSMatMultExpr<VT,MT> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct IsAligned< TDVecTSMatMultExpr<VT,MT> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, bool AF >
+struct SubvectorExprTrait< TDVecTSMatMultExpr<VT,MT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>
+ , SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatDMatMultExpr.h b/src/cpu/blaze/math/expressions/TSMatDMatMultExpr.h
new file mode 100644
index 00000000..33562772
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatDMatMultExpr.h
@@ -0,0 +1,2084 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatDMatMultExpr.h
+// \brief Header file for the transpose sparse matrix/dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The TSMatDMatMultExpr class represents the compile time expression for multiplications between
+// a column-major sparse matrix and a row-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TSMatDMatMultExpr : public DenseMatrix< TSMatDMatMultExpr<MT1,MT2>, true >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the right-hand side dense matrix operand is symmetric,
+ \a value is set to 1 and an optimized evaluation strategy is selected. Otherwise
+ \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsSymmetric<T2>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no SMP assignment is required and the element type of the target matrix has a
+ fixed size (i.e. is not resizable), the nested \value will be set to 1, otherwise it
+ will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !IsResizable<ET1>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no SMP assignment is required and the element type of the target matrix is
+ resizable, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatDMatMultExpr<MT1,MT2> This; //!< Type of this TSMatDMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatDMatMultExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the multiplication expression.
+ // \param rhs The right-hand side dense matrix operand of the multiplication expression.
+ */
+ explicit inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( columns() > SMP_TSMATDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-dense matrix multiplication to a dense matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a transpose sparse matrix-dense matrix
+ // multiplication to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t size( C.rows() * C.columns() );
+
+ if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
+ ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
+ selectSmallAssignKernel( C, A, B );
+ else
+ selectLargeAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose sparse matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a transpose sparse matrix-dense matrix
+ // multiplication expression to a dense matrix. This assign function is used in case the
+ // element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ reset( C );
+
+ if( IsDiagonal<MT5>::value )
+ {
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ C(element->index(),i) = element->value() * B(i,i);
+ }
+ }
+ }
+ else
+ {
+ const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ if( isDefault( C(element->index(),j) ) )
+ C(element->index(),j) = element->value() * B(i,j);
+ else
+ C(element->index(),j) += element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small transpose sparse matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose sparse
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices (small matrices)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a small transpose sparse matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // dense matrix multiplication expression to a dense matrix. This assign function is used in
+ // case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
+
+ reset( C );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i1,j) += v1 * B(i,j);
+ C(i2,j) += v2 * B(i,j);
+ C(i3,j) += v3 * B(i,j);
+ C(i4,j) += v4 * B(i,j);
+ }
+ }
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) += element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose sparse matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose sparse
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices (large matrices)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose sparse matrix-dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // dense matrix multiplication expression to a dense matrix. This assign function is used in
+ // case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( C, tmp * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-dense matrix multiplication to a sparse matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to row-major matrices**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a transpose sparse matrix-dense matrix multiplication to
+ // a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a transpose sparse
+ // matrix-dense matrix multiplication expression to a row-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse matrix-dense matrix multiplication to a
+ // dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose sparse
+ // matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a transpose sparse matrix-dense
+ // matrix multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t size( C.rows() * C.columns() );
+
+ if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
+ ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
+ selectSmallAddAssignKernel( C, A, B );
+ else
+ selectLargeAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose sparse matrix-dense matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a transpose sparse matrix-dense
+ // matrix multiplication expression to a dense matrix. This assign function is used in case the
+ // element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ if( IsDiagonal<MT5>::value )
+ {
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ C(element->index(),i) += element->value() * B(i,i);
+ }
+ }
+ }
+ else
+ {
+ const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) += element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small transpose sparse matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // sparse matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices (small matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a small transpose sparse matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose sparse
+ // matrix-dense matrix multiplication expression to a dense matrix. This assign function is used
+ // in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i1,j) += v1 * B(i,j);
+ C(i2,j) += v2 * B(i,j);
+ C(i3,j) += v3 * B(i,j);
+ C(i4,j) += v4 * B(i,j);
+ }
+ }
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) += element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose sparse matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // sparse matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices (large matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose sparse matrix-dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose sparse
+ // matrix-dense matrix multiplication expression to a dense matrix. This assign function is used
+ // in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( C, tmp * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to row-major matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a transpose sparse matrix-dense matrix
+ // multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a
+ // transpose sparse matrix-dense matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse matrix-dense matrix multiplication to a
+ // dense matrix (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an subtraction assignment of a transpose sparse matrix-
+ // dense matrix multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t size( C.rows() * C.columns() );
+
+ if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
+ ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
+ selectSmallSubAssignKernel( C, A, B );
+ else
+ selectLargeSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose sparse matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a transpose sparse matrix-
+ // dense matrix multiplication expression to a dense matrix. This assign function is used in
+ // case the element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ if( IsDiagonal<MT5>::value )
+ {
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ C(element->index(),i) -= element->value() * B(i,i);
+ }
+ }
+ }
+ else
+ {
+ const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) -= element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small transpose sparse matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose sparse matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices (small matrices)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a small transpose sparse matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-dense matrix multiplication expression to a dense matrix. This assign function
+ // is used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i1,j) -= v1 * B(i,j);
+ C(i2,j) -= v2 * B(i,j);
+ C(i3,j) -= v3 * B(i,j);
+ C(i4,j) -= v4 * B(i,j);
+ }
+ }
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) -= element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose sparse matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose sparse matrix-dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices (large matrices)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose sparse matrix-dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-dense matrix multiplication expression to a dense matrix. This assign function
+ // is used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( C, tmp * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to row-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a transpose sparse matrix-dense matrix
+ // multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // transpose sparse matrix-dense matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-dense matrix multiplication to a dense
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-dense matrix multiplication to a sparse
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-dense matrix multiplication expression to a sparse matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to row-major matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a transpose sparse matrix-dense matrix multiplication
+ // to a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a transpose
+ // sparse matrix-dense matrix multiplication expression to a row-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse matrix-dense matrix multiplication
+ // to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to row-major matrices*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a transpose sparse matrix-dense matrix
+ // multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // transpose sparse matrix-dense matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse matrix-dense matrix multiplication
+ // to a dense matrix (\f$ A-=B*C \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-dense matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case either of the two matrix operands requires an intermediate evaluation and no
+ // symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to row-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a transpose sparse matrix-dense matrix
+ // multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // transpose sparse matrix-dense matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major sparse matrix and
+// a row-major dense matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the multiplication.
+// \param rhs The right-hand side dense matrix for the multiplication.
+// \return The resulting matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the multiplication of a column-major sparse matrix and a row-major
+// dense matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,columnMajor> A;
+ blaze::DynamicMatrix<double,rowMajor> B;
+ blaze::DynamicMatrix<double,columnMajor> C;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const TSMatDMatMultExpr<T1,T2>
+ operator*( const SparseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TSMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TSMatDMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TSMatDMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< TSMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsAligned<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TSMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TSMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TSMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TSMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TSMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TSMatDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatDVecMultExprTrait< TSMatDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TSMatDVecMultExprTrait_< MT1, DMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatSVecMultExprTrait< TSMatDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TSMatDVecMultExprTrait_< MT1, DMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecTDMatMultExprTrait< VT, TSMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecDMatMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecTDMatMultExprTrait< VT, TSMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecDMatMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TSMatDMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TSMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TSMatDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatDMatSubExpr.h b/src/cpu/blaze/math/expressions/TSMatDMatSubExpr.h
new file mode 100644
index 00000000..6b1cb443
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatDMatSubExpr.h
@@ -0,0 +1,1021 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatDMatSubExpr.h
+// \brief Header file for the transpose sparse matrix/dense matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATDMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATTDMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-dense matrix subtractions.
+// \ingroup dense_matrix_expression
+//
+// The TSMatDMatSubExpr class represents the compile time expression for subtractions between
+// a column-major sparse matrix and a row-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+class TSMatDMatSubExpr : public DenseMatrix< TSMatDMatSubExpr<MT1,MT2>, false >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case at least one of the two matrix operands is not SMP assignable, \a value
+ is set to 1 and the expression specific evaluation strategy is selected. Otherwise \a value
+ is set to 0 and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatDMatSubExpr<MT1,MT2> This; //!< Type of this TSMatDMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side dense matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatDMatSubExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the addition expression.
+ // \param rhs The right-hand side dense matrix operand of the addition expression.
+ */
+ explicit inline TSMatDMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) ) ||
+ ( IsExpression<MT2>::value && rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return lhs_.isAliased( alias ) || rhs_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // dense matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO2>& lhs, const TSMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign ( ~lhs, -rhs.rhs_ );
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a sparse matrix-transpose dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a sparse matrix-transpose
+ // dense matrix subtraction expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,SO2>& lhs, const TSMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-transpose dense matrix subtraction to a dense
+ // matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // transpose dense matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const TSMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.rhs_ );
+ addAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // transpose dense matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const TSMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.rhs_ );
+ subAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-transpose dense matrix subtraction to a dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-transpose
+ // dense matrix subtraction expression to a dense matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( DenseMatrix<MT,SO2>& lhs, const TSMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign ( ~lhs, -rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a sparse matrix-transpose dense matrix subtraction to a sparse matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a sparse matrix-transpose
+ // dense matrix subtraction expression to a sparse matrix. Due to the explicit application of the
+ // SFINAE principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO2 > // Storage order of the target sparse matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAssign( SparseMatrix<MT,SO2>& lhs, const TSMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO2, OppositeType, ResultType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO2>& lhs, const TSMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-transpose dense matrix subtraction to a
+ // dense matrix.
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse
+ // matrix-transpose dense matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO2 > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO2>& lhs, const TSMatDMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a column-major sparse matrix and a row-major
+// dense matrix (\f$ A=B+C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix subtraction.
+// \param rhs The right-hand side dense matrix to be subtracted from the sparse matrix.
+// \return The difference of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the subtraction of a column-major sparse matrix and a row-major dense
+// matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,columnMajor> A;
+ blaze::DynamicMatrix<double,rowMajor> B, C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const TSMatDMatSubExpr<T1,T2>
+ operator-( const SparseMatrix<T1,true>& lhs, const DenseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TSMatDMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for the addition of a transpose sparse matrix-dense matrix
+// subtraction expression and a dense matrix (\f$ A=(B-C)+D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side transpose sparse matrix-dense matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The sum of the two matrices.
+//
+// This operator implements a performance optimized treatment of the addition of a transpose
+// sparse matrix-dense matrix subtraction expression to a dense matrix.
+*/
+template< typename T1 // Type of the sparse matrix of the left-hand side expression
+ , typename T2 // Type of the dense matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const AddExprTrait_< TSMatDMatSubExpr<T1,T2>, T3 >
+ operator+( const TSMatDMatSubExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ( (~rhs) - lhs.rightOperand() ) + lhs.leftOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for the subtraction of a transpose sparse matrix-dense matrix
+// subtraction expression and a dense matrix (\f$ A=(B-C)-D \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side transpose sparse matrix-dense matrix subtraction.
+// \param rhs The right-hand side dense matrix.
+// \return The difference of the two matrices.
+//
+// This operator implements a performance optimized treatment of the subtraction of a transpose
+// sparse matrix-dense matrix subtraction expression and a dense matrix.
+*/
+template< typename T1 // Type of the sparse matrix of the left-hand side expression
+ , typename T2 // Type of the dense matrix of the left-hand side expression
+ , typename T3 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const SubExprTrait_< TSMatDMatSubExpr<T1,T2>, T3 >
+ operator-( const TSMatDMatSubExpr<T1,T2>& lhs, const DenseMatrix<T3,SO>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return lhs.leftOperand() - ( lhs.rightOperand() + (~rhs) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TSMatDMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TSMatDMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< TSMatDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< TSMatDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TSMatDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TSMatDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TSMatDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TSMatDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TSMatDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TSMatDMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatAddExprTrait< TSMatDMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< DMatDMatSubExprTrait_<MT3,MT2>, MT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatAddExprTrait< TSMatDMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , DMatTSMatAddExprTrait_< TDMatDMatSubExprTrait_<MT3,MT2>, MT1 >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatDMatSubExprTrait< TSMatDMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsRowMajorMatrix<MT3> >
+ , TSMatDMatSubExprTrait_< MT1, DMatDMatAddExprTrait_<MT2,MT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename MT3 >
+struct DMatTDMatSubExprTrait< TSMatDMatSubExpr<MT1,MT2>, MT3 >
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseMatrix<MT3>, IsColumnMajorMatrix<MT3> >
+ , TSMatDMatSubExprTrait_< MT1, DMatTDMatAddExprTrait_<MT2,MT3> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TSMatDMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TSMatDMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TSMatDMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatDVecMultExpr.h b/src/cpu/blaze/math/expressions/TSMatDVecMultExpr.h
new file mode 100644
index 00000000..41f303f1
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatDVecMultExpr.h
@@ -0,0 +1,1033 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatDVecMultExpr.h
+// \brief Header file for the transpose sparse matrix/dense vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSMATDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-dense vector multiplications.
+// \ingroup dense_vector_expression
+//
+// The TSMatDVecMultExpr class represents the compile time expression for multiplications
+// between column-major sparse matrices and dense vectors.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename VT > // Type of the right-hand side dense vector
+class TSMatDVecMultExpr : public DenseVector< TSMatDVecMultExpr<MT,VT>, false >
+ , private MatVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side dense vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side dense vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateMatrix || evaluateVector ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatDVecMultExpr<MT,VT> This; //!< Type of this TSMatDVecMultExpr instance.
+ typedef MultTrait_<MRT,VRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side dense vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the right-hand side dense vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatDVecMultExpr class.
+ //
+ // \param mat The left-hand side sparse matrix operand of the multiplication expression.
+ // \param vec The right-hand side dense vector operand of the multiplication expression.
+ */
+ explicit inline TSMatDVecMultExpr( const MT& mat, const VT& vec ) noexcept
+ : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
+ , vec_( vec ) // Right-hand side dense vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return mat_(index,index) * vec_[index];
+ }
+ else if( IsLower<MT>::value )
+ {
+ const size_t n( IsStrictlyLower<MT>::value ? index : index+1UL );
+ return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n );
+ }
+ else if( IsUpper<MT>::value )
+ {
+ const size_t begin( IsStrictlyUpper<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.columns() - begin );
+ return subvector( row( mat_, index ), begin, n ) * subvector( vec_, begin, n );
+ }
+ else
+ {
+ return row( mat_, index ) * vec_;
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense vector operand.
+ //
+ // \return The right-hand side dense vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return vec_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_TSMATDVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand mat_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand vec_; //!< Right-hand side dense vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ reset( ~lhs );
+
+ if( rhs.mat_.columns() == 0UL ) return;
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ TSMatDVecMultExpr::selectAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a transpose sparse matrix-dense vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the serial assignment kernel for the transpose sparse matrix-
+ // dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > ConstIterator;
+
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ ConstIterator element( A.begin(j) );
+ const ConstIterator end( A.end(j) );
+
+ for( ; element!=end; ++element ) {
+ if( IsResizable< ElementType_<VT1> >::value &&
+ isDefault( y[element->index()] ) )
+ y[element->index()] = element->value() * x[j];
+ else
+ y[element->index()] += element->value() * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-dense vector multiplication to a sparse
+ // vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // dense vector multiplication expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a sparse matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a sparse matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) return;
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ TSMatDVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a transpose sparse matrix-dense vector
+ // multiplication (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the serial addition assignment kernel for the transpose sparse
+ // matrix-dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > ConstIterator;
+
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ ConstIterator element( A.begin(j) );
+ const ConstIterator end( A.end(j) );
+
+ for( ; element!=end; ++element ) {
+ y[element->index()] += element->value() * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a sparse matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) return;
+
+ LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ TSMatDVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense vectors*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a transpose sparse matrix-dense vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side dense vector operand.
+ // \return void
+ //
+ // This function implements the serial subtraction assignment kernel for the transpose sparse
+ // matrix-dense vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > ConstIterator;
+
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ ConstIterator element( A.begin(j) );
+ const ConstIterator end( A.end(j) );
+
+ for( ; element!=end; ++element ) {
+ y[element->index()] -= element->value() * x[j];
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a sparse
+ // matrix-dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Disision assignment of a sparse matrix-dense vector multiplication to a dense vector
+ // (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a sparse matrix-
+ // dense vector multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ reset( ~lhs );
+
+ if( rhs.mat_.columns() == 0UL ) return;
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-dense vector multiplication to a sparse
+ // vector (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-dense vector multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a sparse
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) return;
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpAddAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a sparse
+ // matrix- dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ if( rhs.mat_.columns() == 0UL ) return;
+
+ LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
+ RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ smpSubAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a sparse matrix-dense vector multiplication to a
+ // dense vector (\f$ \vec{y}*=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // sparse matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP division assignment of a sparse matrix-dense vector multiplication to a dense
+ // vector (\f$ \vec{y}/=A*\vec{x} \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a sparse
+ // matrix-dense vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,false>& lhs, const TSMatDVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR( MT, VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major sparse matrix and a
+// dense vector (\f$ \vec{y}=A*\vec{x} \f$).
+// \ingroup dense_vector
+//
+// \param mat The left-hand side column-major sparse matrix for the multiplication.
+// \param vec The right-hand side dense vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator represents the multiplication between a column-major sparse matrix and a dense
+// vector:
+
+ \code
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ blaze::CompressedMatrix<double,columnMajor> A;
+ blaze::DynamicVector<double,columnVector> x, y;
+ // ... Resizing and initialization
+ y = A * x;
+ \endcode
+
+// The operator returns an expression representing a dense vector of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both the
+// sparse matrix type \a T1 and the dense vector type \a T2 as well as the two element types
+// \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of columns
+// of the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense vector
+inline const DisableIf_< Or< IsSymmetric<T1>, IsMatMatMultExpr<T1> >, TSMatDVecMultExpr<T1,T2> >
+ operator*( const SparseMatrix<T1,true>& mat, const DenseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return TSMatDVecMultExpr<T1,T2>( ~mat, ~vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a symmetric column-major sparse matrix
+// and a dense vector (\f$ \vec{a}=B*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param mat The left-hand side column-major sparse matrix for the multiplication.
+// \param vec The right-hand side dense vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// symmetric column-major sparse matrix and a dense vector. It restructures the expression
+// \f$ \vec{y}=A^T*\vec{x} \f$ to the expression \f$ \vec{y}=A*\vec{x} \f$.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense vector
+inline const EnableIf_< IsSymmetric<T1>, MultExprTrait_<T1,T2> >
+ operator*( const SparseMatrix<T1,true>& mat, const DenseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATMULTEXPR_TYPE( T1 );
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return trans( ~mat ) * (~vec);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct Size< TSMatDVecMultExpr<MT,VT> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct IsAligned< TSMatDVecMultExpr<MT,VT> >
+ : public BoolConstant< IsAligned<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, bool AF >
+struct SubvectorExprTrait< TSMatDVecMultExpr<MT,VT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>
+ , SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatSMatMultExpr.h b/src/cpu/blaze/math/expressions/TSMatSMatMultExpr.h
new file mode 100644
index 00000000..fd4a8061
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatSMatMultExpr.h
@@ -0,0 +1,1519 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatSMatMultExpr.h
+// \brief Header file for the transpose sparse matrix/sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SMatSVecMultExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSMATSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-sparse matrix multiplications.
+// \ingroup sparse_matrix_expression
+//
+// The TSMatSMatMultExpr class represents the compile time expression for multiplications between
+// a column-major and a row-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TSMatSMatMultExpr : public SparseMatrix< TSMatSMatMultExpr<MT1,MT2>, true >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateLeft = RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateRight = RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the target matrix is row-major and the left-hand side
+ matrix operand of type \a T2 is symmetric or in case the target matrix is column-major
+ and the right-hand side matrix operands of type \a T3 is symmetric, \a value is set to
+ 1 and an optimized evaluation strategy is selected. Otherwise \a value is set to 0 and
+ the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = ( IsRowMajorMatrix<T1>::value && IsSymmetric<T2>::value ) ||
+ ( IsColumnMajorMatrix<T1>::value && IsSymmetric<T3>::value ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation and in case no symmetry can be exploited, the nested \value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T2>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatSMatMultExpr<MT1,MT2> This; //!< Type of this TSMatSMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatSMatMultExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the multiplication expression.
+ // \param rhs The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline TSMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline constexpr size_t nonZeros() const noexcept {
+ return 0UL;
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const noexcept {
+ UNUSED_PARAMETER( i );
+ return 0UL;
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_TSMATSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse matrix multiplication to a dense
+ // matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose sparse matrix-sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose sparse matrix-
+ // sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ const LeftIterator lend( A.end(j) );
+ for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
+ const RightIterator rend( B.end(j) );
+ for( RightIterator relem=B.begin(j); relem!=rend; ++relem )
+ {
+ if( IsResizable< ElementType_<MT3> >::value &&
+ isDefault( C(lelem->index(),relem->index()) ) ) {
+ C(lelem->index(),relem->index()) = lelem->value() * relem->value();
+ }
+ else {
+ C(lelem->index(),relem->index()) += lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse matrix multiplication to a row-major
+ // sparse matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // sparse matrix multiplication expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT1> );
+
+ const OppositeType_<MT1> tmp( serial( rhs.lhs_ ) );
+ assign( ~lhs, tmp * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse matrix multiplication to a
+ // column-major sparse matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // sparse matrix multiplication expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_<MT2> );
+
+ const OppositeType_<MT2> tmp( serial( rhs.rhs_ ) );
+ assign( ~lhs, rhs.lhs_ * tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to row-major matrices**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a transpose sparse matrix-sparse matrix multiplication to
+ // a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a transpose sparse
+ // matrix-sparse matrix multiplication expression to a row-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to column-major matrices*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a transpose sparse matrix-sparse matrix multiplication
+ // to a column-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a transpose sparse
+ // matrix-sparse matrix multiplication expression to a column-major matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse matrix-sparse matrix multiplication to
+ // a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matarix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose sparse matrix-sparse matrix multiplication
+ // (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose sparse
+ // matrix-sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ const LeftIterator lend( A.end(j) );
+ for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
+ const RightIterator rend( B.end(j) );
+ for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
+ C(lelem->index(),relem->index()) += lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to row-major matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a transpose sparse matrix-sparse matrix
+ // multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a row-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to column-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a transpose sparse matrix-sparse matrix
+ // multiplication to a column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a column-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse matrix-sparse matrix multiplication
+ // to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose sparse matrix-sparse matrix multiplication
+ // (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose sparse
+ // matrix-sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ const LeftIterator lend( A.end(j) );
+ for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
+ const RightIterator rend( B.end(j) );
+ for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
+ C(lelem->index(),relem->index()) -= lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to row-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a transpose sparse matrix-sparse matrix
+ // multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // transpose sparse matrix-sparse matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to column-major matrices*******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a transpose sparse matrix-sparse matrix
+ // multiplication to a column-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // transpose sparse matrix-sparse matrix multiplication expression to a column-major matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to matrices******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-sparse matrix multiplication to a matrix
+ // (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-sparse matrix multiplication expression to a matrix. Due to the explicit application
+ // of the SFINAE principle this function can only be selected by the compiler in case either
+ // of the two matrix operands requires an intermediate evaluation and no symmetry can be
+ // exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to row-major matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a transpose sparse matrix-sparse matrix multiplication
+ // to a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a row-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to column-major matrices***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a transpose sparse matrix-sparse matrix multiplication
+ // to a column-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a column-major matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse matrix-sparse matrix multiplication
+ // to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case either of the two matrix operands requires an intermediate evaluation and no symmetry
+ // can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matarix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to row-major matrices*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a transpose sparse matrix-sparse matrix
+ // multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // transpose sparse matrix-sparse matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to column-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a transpose sparse matrix-sparse matrix
+ // multiplication to a column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // transpose sparse matrix-sparse matrix multiplication expression to a column-major matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse matrix-sparse matrix multiplication
+ // to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case either of the two matrix operands requires an intermediate evaluation and no symmetry
+ // can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to row-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a transpose sparse matrix-sparse matrix
+ // multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // transpose sparse matrix-sparse matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to column-major matrices***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a transpose sparse matrix-sparse matrix
+ // multiplication to a column-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // transpose sparse matrix-sparse matrix multiplication expression to a column-major matrix.
+ // Due to the explicit application of the SFINAE principle this function can only be selected
+ // by the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major sparse matrix and a
+// row-major sparse matrix (\f$ A=B*C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix multiplication.
+// \param rhs The right-hand side sparse matrix for the matrix multiplication.
+// \return The product of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the multiplication of a column-major sparse matrix and a row-major
+// sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,columnMajor> A, C;
+ blaze::CompressedMatrix,double,rowMajor> B;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const TSMatSMatMultExpr<T1,T2>
+ operator*( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TSMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TSMatSMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TSMatSMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TSMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TSMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TSMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TSMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TSMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TSMatSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TSMatDVecMultExprTrait< TSMatSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TSMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TSMatSVecMultExprTrait< TSMatSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TSMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecTSMatMultExprTrait< VT, TSMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecSMatMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecTSMatMultExprTrait< VT, TSMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDVecSMatMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TSMatSMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TSMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TSMatSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatSMatSubExpr.h b/src/cpu/blaze/math/expressions/TSMatSMatSubExpr.h
new file mode 100644
index 00000000..7cd9a164
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatSMatSubExpr.h
@@ -0,0 +1,1060 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatSMatSubExpr.h
+// \brief Header file for the transpose sparse matrix/sparse matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATSMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATSMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSMATSMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-sparse matrix subtractions.
+// \ingroup sparse_matrix_expression
+//
+// The TSMatSMatSubExpr class represents the compile time expression for subtractions between
+// a column-major sparse matrix and a row-major sparse matrix.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TSMatSMatSubExpr : public SparseMatrix< TSMatSMatSubExpr<MT1,MT2>, false >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSymmetricKernel struct is a helper struct for the selection of the serial
+ evaluation strategy. In case the two given matrix types have a different storage
+ order and in case the second matrix type is symmetric, \a value is set to 1 and
+ an optimized evaluation strategy is selected. Otherwise \a value is set to 0 and
+ the default strategy is chosen. */
+ template< typename T1, typename T2 >
+ struct UseSymmetricKernel {
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_DIFFERENT_STORAGE_ORDER( T1, T2 );
+ enum : bool { value = IsSymmetric<T2>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = MT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatSMatSubExpr<MT1,MT2> This; //!< Type of this TSMatSMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatSMatSubExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the subtraction expression.
+ // \param rhs The right-hand side sparse matrix operand of the subtraction expression.
+ */
+ explicit inline TSMatSMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() + rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return lhs_.nonZeros(i) + rhs_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse matrix subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ assign( ~lhs, rhs.lhs_ );
+
+ if( !IsResizable< ElementType_<MT> >::value ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else
+ {
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
+ const RightIterator end( B.end(i) );
+ for( RightIterator element=B.begin(i); element!=end; ++element ) {
+ if( isDefault( (~lhs)(i,element->index()) ) )
+ (~lhs)(i,element->index()) = -element->value();
+ else
+ (~lhs)(i,element->index()) -= element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse matrix subtraction to a row-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a transpose sparse matrix-sparse matrix
+ // subtraction expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT1> >
+ assign( SparseMatrix<MT,false>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< OppositeType_<RT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ const OppositeType_<RT1> A( serial( rhs.lhs_ ) );
+
+ // Evaluation of the right-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) );
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix subtraction
+ for( size_t i=0UL; i<(~lhs).rows(); ++i )
+ {
+ const LeftIterator lend( A.end(i) );
+ const RightIterator rend( B.end(i) );
+
+ LeftIterator l( A.begin(i) );
+ RightIterator r( B.begin(i) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( i, r->index(), -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( i, l->index(), l->value()-r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( i, l->index(), l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( i, r->index(), -r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( i );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse matrix subtraction to a row-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // sparse matrix subtraction expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT1> >
+ assign( SparseMatrix<MT,false>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) - rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse matrix subtraction to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a transpose sparse matrix-
+ // sparse matrix subtraction expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT2> >
+ assign( SparseMatrix<MT,true>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< OppositeType_<RT2> > RightIterator;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ CT1 A( serial( rhs.lhs_ ) );
+
+ // Evaluation of the right-hand side sparse matrix operand
+ const OppositeType_<RT2> B( serial( rhs.rhs_ ) );
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix subtraction
+ for( size_t j=0UL; j<(~lhs).columns(); ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), j, -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), j, l->value()-r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), j, -r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( j );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse matrix subtraction to a column-major
+ // sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // sparse matrix subtraction expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT2> >
+ assign( SparseMatrix<MT,true>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, rhs.lhs_ - trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse matrix-sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse matrix-sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse matrix-sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse matrix-sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse matrix-sparse matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse matrix-sparse matrix subtraction
+ // to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse matrix-sparse matrix subtraction expression to a dense matrix. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of a column-major and a row-major sparse
+// matrix (\f$ A=B-C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix subtraction.
+// \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the subtraction of a column-major and a row-major sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,columnMajor> A;
+ blaze::CompressedMatrix<double,rowMajor> B, C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const TSMatSMatSubExpr<T1,T2>
+ operator-( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TSMatSMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TSMatSMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TSMatSMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< TSMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< TSMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TSMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TSMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TSMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TSMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TSMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TSMatSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TSMatSMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TSMatSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TSMatSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatSVecMultExpr.h b/src/cpu/blaze/math/expressions/TSMatSVecMultExpr.h
new file mode 100644
index 00000000..1f2ae941
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatSVecMultExpr.h
@@ -0,0 +1,896 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatSVecMultExpr.h
+// \brief Header file for the transpose sparse matrix/sparse vector multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/MatVecMultExpr.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/dense/DynamicVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATDVECMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse matrix-sparse vector multiplications.
+// \ingroup sparse_vector_expression
+//
+// The TSMatSVecMultExpr class represents the compile time expression for multiplications
+// between column-major sparse matrices and sparse vectors.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename VT > // Type of the right-hand side sparse vector
+class TSMatSVecMultExpr : public SparseVector< TSMatSVecMultExpr<MT,VT>, false >
+ , private MatVecMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> MRT; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<VT> VRT; //!< Result type of the right-hand side sparse vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the right-hand side sparse vector expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse vector expression.
+ enum : bool { evaluateVector = RequiresEvaluation<VT>::value || IsComputation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateMatrix || evaluateVector ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatSVecMultExpr<MT,VT> This; //!< Type of this TSMatSVecMultExpr instance.
+ typedef MultTrait_<MRT,VRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > LT;
+
+ //! Type for the assignment of the right-hand side sparse vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
+ !evaluateVector && VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatSVecMultExpr class.
+ //
+ // \param mat The left-hand side sparse matrix operand of the multiplication expression.
+ // \param vec The right-hand side sparse vector operand of the multiplication expression.
+ */
+ explicit inline TSMatSVecMultExpr( const MT& mat, const VT& vec ) noexcept
+ : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
+ , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return mat_(index,index) * vec_[index];
+ }
+ else if( IsLower<MT>::value )
+ {
+ const size_t n( IsStrictlyLower<MT>::value ? index : index+1UL );
+ return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n );
+ }
+ else if( IsUpper<MT>::value )
+ {
+ const size_t begin( IsStrictlyUpper<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.columns() - begin );
+ return subvector( row( mat_, index ), begin, n ) * subvector( vec_, begin, n );
+ }
+ else
+ {
+ return row( mat_, index ) * vec_;
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns an estimation for the number of non-zero elements in the sparse vector.
+ //
+ // \return The estimate for the number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return mat_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand function**********************************************************************
+ /*!\brief Returns the right-hand side sparse vector operand.
+ //
+ // \return The right-hand side sparse vector operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_SMATSVECMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand mat_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand vec_; //!< Right-hand side sparse vector of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse vector multiplication to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Resetting the left-hand side target dense vector
+ reset( ~lhs );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the transpose sparse matrix-sparse vector multiplication
+ TSMatSVecMultExpr::selectAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose sparse matrix-sparse vector multiplication
+ // (\f$ \vec{y}=A*\vec{x} \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose sparse matrix-
+ // sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+
+ const VectorIterator vend ( x.end() );
+ VectorIterator velem( x.begin() );
+
+ for( ; velem!=vend; ++velem )
+ {
+ const MatrixIterator mend ( A.end ( velem->index() ) );
+ MatrixIterator melem( A.begin( velem->index() ) );
+
+ for( ; melem!=mend; ++melem ) {
+ if( IsResizable< ElementType_<VT1> >::value &&
+ isDefault( y[melem->index()] ) )
+ y[melem->index()] = melem->value() * velem->value();
+ else
+ y[melem->index()] += melem->value() * velem->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-sparse vector multiplication to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // sparse vector multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const DynamicVector<ElementType_<VT1>,false> tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse matrix-sparse vector multiplication to a
+ // dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse matrix-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the transpose sparse matrix-sparse vector multiplication
+ TSMatSVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose sparse matrix-sparse vector multiplication
+ // (\f$ \vec{y}+=A*\vec{x} \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the sparse matrix-sparse
+ // vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+
+ const VectorIterator vend ( x.end() );
+ VectorIterator velem( x.begin() );
+
+ for( ; velem!=vend; ++velem )
+ {
+ const MatrixIterator mend ( A.end ( velem->index() ) );
+ MatrixIterator melem( A.begin( velem->index() ) );
+
+ for( ; melem!=mend; ++melem ) {
+ y[melem->index()] += melem->value() * velem->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse matrix-sparse vector multiplication to
+ // a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the transpose sparse matrix-sparse vector multiplication
+ TSMatSVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose sparse matrix-sparse vector
+ // multiplication (\f$ \vec{y}-=A*\vec{x} \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param A The left-hand side sparse matrix operand.
+ // \param x The right-hand side sparse vector operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the sparse matrix-
+ // sparse vector multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename MT1 // Type of the left-hand side matrix operand
+ , typename VT2 > // Type of the right-hand side vector operand
+ static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
+ {
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+
+ const VectorIterator vend ( x.end() );
+ VectorIterator velem( x.begin() );
+
+ for( ; velem!=vend; ++velem )
+ {
+ const MatrixIterator mend ( A.end ( velem->index() ) );
+ MatrixIterator melem( A.begin( velem->index() ) );
+
+ for( ; melem!=mend; ++melem ) {
+ y[melem->index()] -= melem->value() * velem->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a transpose sparse matrix-sparse vector multiplication
+ // to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // sparse matrix-sparse vector multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-sparse vector multiplication to a dense
+ // vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Resetting the left-hand side target dense vector
+ reset( ~lhs );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the transpose sparse matrix-sparse vector multiplication
+ smpAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse matrix-sparse vector multiplication
+ // to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the transpose sparse matrix-sparse vector multiplication
+ smpAddAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse matrix-sparse vector multiplication
+ // to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse matrix-sparse vector multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the right-hand side sparse vector operand
+ RT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the left-hand side sparse matrix operand
+ LT A( rhs.mat_ );
+
+ // Checking the evaluated operators
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the transpose sparse matrix-sparse vector multiplication
+ smpSubAssign( ~lhs, A * x );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a transpose sparse matrix-sparse vector multiplication
+ // to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose sparse matrix-sparse vector multiplication expression to a dense vector. Due
+ // to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR( MT, VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose sparse matrix and a
+// sparse vector (\f$ \vec{y}=A*\vec{x} \f$).
+// \ingroup sparse_vector
+//
+// \param mat The left-hand side sparse matrix for the multiplication.
+// \param vec The right-hand side sparse vector for the multiplication.
+// \return The resulting vector.
+// \exception std::invalid_argument Matrix and vector sizes do not match.
+//
+// This operator represents the multiplication between a transpose sparse matrix and a sparse
+// vector:
+
+ \code
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ blaze::CompressedMatrix<double,columnMajor> A;
+ blaze::CompressedVector<double,columnVector> x, y;
+ // ... Resizing and initialization
+ y = A * x;
+ \endcode
+
+// The operator returns an expression representing a sparse vector of the higher-order element
+// type of the two involved element types \a T1::ElementType and \a T2::ElementType. Both the
+// sparse matrix type \a T1 and the sparse vector type \a T2 as well as the two element types
+// \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of columns
+// of the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const DisableIf_< IsMatMatMultExpr<T1>, TSMatSVecMultExpr<T1,T2> >
+ operator*( const SparseMatrix<T1,true>& mat, const SparseVector<T2,false>& vec )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~mat).columns() != (~vec).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
+ }
+
+ return TSMatSVecMultExpr<T1,T2>( ~mat, ~vec );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT >
+struct Size< TSMatSVecMultExpr<MT,VT> > : public Rows<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, typename VT, bool AF >
+struct SubvectorExprTrait< TSMatSVecMultExpr<MT,VT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT,AF>
+ , SubvectorExprTrait_<const VT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatTDMatMultExpr.h b/src/cpu/blaze/math/expressions/TSMatTDMatMultExpr.h
new file mode 100644
index 00000000..7834e973
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatTDMatMultExpr.h
@@ -0,0 +1,2118 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatTDMatMultExpr.h
+// \brief Header file for the transpose sparse matrix/transpose dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/StorageOrder.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SMATDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-transpose dense matrix multiplications.
+// \ingroup dense_matrix_expression
+//
+// The TSMatTDMatMultExpr class represents the compile time expression for multiplications between
+// a column-major sparse matrix and a column-major dense matrix.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TSMatTDMatMultExpr : public DenseMatrix< TSMatTDMatMultExpr<MT1,MT2>, true >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<RT1> ET1; //!< Element type of the left-hand side dense matrix expression.
+ typedef ElementType_<RT2> ET2; //!< Element type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the either of the two matrix operands is symmetric,
+ \a value is set to 1 and an optimized evaluation strategy is selected. Otherwise
+ \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no SMP assignment is required and the element type of the target matrix has a
+ fixed size (i.e. is not resizable), the nested \value will be set to 1, otherwise it
+ will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !IsResizable<ET1>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case no SMP assignment is required and the element type of the target matrix is
+ resizable, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatTDMatMultExpr<MT1,MT2> This; //!< Type of this TSMatTDMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side dense matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateLeft, const RT1, CT1 > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateRight, const RT2, CT2 > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatTDMatMultExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the multiplication expression.
+ // \param rhs The right-hand side dense matrix operand of the multiplication expression.
+ */
+ explicit inline TSMatTDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return rhs_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( columns() > SMP_TSMATTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose dense matrix multiplication to a
+ // dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatTDMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices (kernel selection)*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an assignment of a transpose sparse matrix-transpose
+ // dense matrix multiplication to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t size( C.rows() * C.columns() );
+
+ if( ( IsRowMajorMatrix<MT3>::value && size < TSMATTDMATMULT_THRESHOLD ) ||
+ ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
+ selectSmallAssignKernel( C, A, B );
+ else
+ selectLargeAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose sparse matrix-transpose dense matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default assignment of a transpose sparse matrix-transpose
+ // dense matrix multiplication expression to a dense matrix. This assign function is used
+ // in case the element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ reset( C );
+
+ if( IsDiagonal<MT5>::value )
+ {
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ C(element->index(),i) = element->value() * B(i,i);
+ }
+ }
+ }
+ else
+ {
+ const size_t block( 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ if( isDefault( C(element->index(),j) ) )
+ C(element->index(),j) = element->value() * B(i,j);
+ else
+ C(element->index(),j) += element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (small matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a small transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose sparse
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices (small matrices)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a small transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose dense matrix multiplication expression to a dense matrix. This assign function is
+ // used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? 128UL : 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( size_t j=jj; j<jpos; ++j ) {
+ reset( C(i,j) );
+ }
+ }
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i1,j) += v1 * B(i,j);
+ C(i2,j) += v2 * B(i,j);
+ C(i3,j) += v3 * B(i,j);
+ C(i4,j) += v4 * B(i,j);
+ }
+ }
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) += element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices (large matrices)***************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the assignment of a transpose sparse
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense matrices (large matrices)*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a large transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose dense matrix multiplication expression to a dense matrix. This assign function is
+ // used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+
+ const OppositeType_<MT4> tmp( serial( A ) );
+ assign( C, tmp * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse matrices***************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose dense matrix multiplication to
+ // a sparse matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose dense matrix multiplication expression to a sparse matrix.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a transpose sparse
+ // matrix-transpose dense matrix multiplication expression. Due to the explicit application of
+ // the SFINAE principle this function can only be selected by the compiler in case the symmetry
+ // of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose sparse
+ // matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices (kernel selection)************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an addition assignment of a transpose sparse matrix-
+ // transpose dense matrix multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t size( C.rows() * C.columns() );
+
+ if( ( IsRowMajorMatrix<MT3>::value && size < TSMATTDMATMULT_THRESHOLD ) ||
+ ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
+ selectSmallAddAssignKernel( C, A, B );
+ else
+ selectLargeAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default addition assignment of a transpose sparse matrix-
+ // transpose dense matrix multiplication expression to a dense matrix. This assign function
+ // is used in case the element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ if( IsDiagonal<MT5>::value )
+ {
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ C(element->index(),i) += element->value() * B(i,i);
+ }
+ }
+ }
+ else
+ {
+ const size_t block( 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) += element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (small matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a small transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices (small matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a small transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix. This
+ // assign function is used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? 128UL : 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i1,j) += v1 * B(i,j);
+ C(i2,j) += v2 * B(i,j);
+ C(i3,j) += v3 * B(i,j);
+ C(i4,j) += v4 * B(i,j);
+ }
+ }
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) += element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices (large matrices)******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the addition assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultAddAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense matrices (large matrices)****************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a large transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix. This
+ // assign function is used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+
+ const OppositeType_<MT4> tmp( serial( A ) );
+ addAssign( C, tmp * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a
+ // transpose sparse matrix-transpose dense matrix multiplication expression. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices (kernel selection)*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Selection of the kernel for an subtraction assignment of a transpose sparse matrix-
+ // transpose dense matrix multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ const size_t size( C.rows() * C.columns() );
+
+ if( ( IsRowMajorMatrix<MT3>::value && size < TSMATTDMATMULT_THRESHOLD ) ||
+ ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
+ selectSmallSubAssignKernel( C, A, B );
+ else
+ selectLargeSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment of a transpose sparse matrix-
+ // transpose dense matrix multiplication expression to a dense matrix. This assign function
+ // is used in case the element type of the target matrix is resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ if( IsDiagonal<MT5>::value )
+ {
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ for( ; element!=end; ++element ) {
+ C(element->index(),i) -= element->value() * B(i,i);
+ }
+ }
+ }
+ else
+ {
+ const size_t block( 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) -= element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (small matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a small transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose sparse matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices (small matrices)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a small transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix. This
+ // assign function is used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> ConstIterator;
+
+ const size_t block( IsRowMajorMatrix<MT3>::value ? 128UL : 64UL );
+
+ for( size_t jj=0UL; jj<B.columns(); jj+=block )
+ {
+ const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
+
+ for( size_t i=0UL; i<A.columns(); ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT5>::value )
+ ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
+ :( jj ) );
+ const size_t jend( ( IsLower<MT5>::value )
+ ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
+ :( jpos ) );
+
+ if( jbegin >= jend )
+ continue;
+
+ const ConstIterator end( A.end(i) );
+ ConstIterator element( A.begin(i) );
+
+ const size_t nonzeros( A.nonZeros(i) );
+ const size_t kpos( nonzeros & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
+
+ for( size_t k=0UL; k<kpos; k+=4UL )
+ {
+ const size_t i1( element->index() );
+ const ET1 v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const ET1 v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const ET1 v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const ET1 v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(i1,j) -= v1 * B(i,j);
+ C(i2,j) -= v2 * B(i,j);
+ C(i3,j) -= v3 * B(i,j);
+ C(i4,j) -= v4 * B(i,j);
+ }
+ }
+
+ for( ; element!=end; ++element ) {
+ for( size_t j=jbegin; j<jend; ++j ) {
+ C(element->index(),j) -= element->value() * B(i,j);
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices (large matrices)***************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function relays to the default implementation of the subtraction assignment of a
+ // transpose sparse matrix-transpose dense matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ selectDefaultSubAssignKernel( C, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense matrices (large matrices)*************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a large transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side multiplication operand.
+ // \param B The right-hand side multiplication operand.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix. This
+ // assign function is used in case the element type of the target matrix is not resizable.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
+ selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_<MT4> );
+
+ const OppositeType_<MT4> tmp( serial( A ) );
+ subAssign( C, tmp * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // transpose sparse matrix-transpose dense matrix multiplication expression. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-transpose dense matrix multiplication
+ // to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-transpose dense matrix multiplication expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-transpose dense matrix multiplication to
+ // a sparse matrix (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-transpose dense matrix multiplication expression to a sparse matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target sparse matrix
+ , bool SO > // Storage order of the target sparse matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType );
+ BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER( MT, TmpType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ const TmpType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a transpose sparse matrix-transpose dense matrix
+ // multiplication (\f$ C=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler
+ // in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C+=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // transpose sparse matrix-transpose dense matrix multiplication expression. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse matrix-transpose dense matrix
+ // multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse matrix-transpose dense matrix multiplication expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
+ RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a transpose sparse matrix-transpose dense
+ // matrix multiplication (\f$ C-=A*B \f$).
+ // \ingroup dense_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of
+ // a transpose sparse matrix-transpose dense matrix multiplication expression. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ else if( IsSymmetric<MT1>::value )
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
+ else
+ smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a column-major sparse matrix and
+// a column-major dense matrix (\f$ A=B*C \f$).
+// \ingroup dense_matrix
+//
+// \param lhs The left-hand side sparse matrix for the multiplication.
+// \param rhs The right-hand side dense matrix for the multiplication.
+// \return The resulting matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This operator represents the multiplication of a column-major sparse matrix and a column-major
+// dense matrix:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,columnMajor> A;
+ blaze::DynamicMatrix<double,columnMajor> B, C;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a dense matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const TSMatTDMatMultExpr<T1,T2>
+ operator*( const SparseMatrix<T1,true>& lhs, const DenseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TSMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TSMatTDMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TSMatTDMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsAligned< TSMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< IsAligned<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TSMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TSMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TSMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TSMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TSMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TSMatTDMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatDVecMultExprTrait< TSMatTDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TSMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TDMatSVecMultExprTrait< TSMatTDMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TSMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTDMatMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TSVecTDMatMultExprTrait_< TSVecTSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TSMatTDMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TSMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TSMatTDMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatTSMatAddExpr.h b/src/cpu/blaze/math/expressions/TSMatTSMatAddExpr.h
new file mode 100644
index 00000000..b6aa6fe2
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatTSMatAddExpr.h
@@ -0,0 +1,1066 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatTSMatAddExpr.h
+// \brief Header file for the transpose sparse matrix/transpose sparse matrix addition expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTSMATADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATTSMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatAddExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSMATTSMATADDEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-transpose sparse matrix additions.
+// \ingroup sparse_matrix_expression
+//
+// The TSMatTSMatAddExpr class represents the compile time expression for additions between
+// two column-major sparse matrices.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TSMatTSMatAddExpr : public SparseMatrix< TSMatTSMatAddExpr<MT1,MT2>, true >
+ , private MatMatAddExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef AddExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSymmetricKernel struct is a helper struct for the selection of the serial
+ evaluation strategy. In case the target matrix is column-major and both matrix
+ operands are symmetric, \a value is set to 1 and an optimized evaluation strategy
+ is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseSymmetricKernel {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( T1 );
+ enum : bool { value = IsSymmetric<T2>::value && IsSymmetric<T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = MT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatTSMatAddExpr<MT1,MT2> This; //!< Type of this TSMatTSMatAddExpr instance.
+ typedef AddTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatTSMatAddExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the addition expression.
+ // \param rhs The right-hand side sparse matrix operand of the addition expression.
+ */
+ explicit inline TSMatTSMatAddExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the addition expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) + rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() + rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return lhs_.nonZeros(i) + rhs_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the addition expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the addition expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix addition to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpsoe sparse matrix-
+ // transpose sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ assign( ~lhs, rhs.lhs_ );
+
+ if( !IsResizable< ElementType_<MT> >::value ) {
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ else
+ {
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
+ const RightIterator end( B.end(j) );
+ for( RightIterator element=B.begin(j); element!=end; ++element ) {
+ if( isDefault( (~lhs)(element->index(),j) ) )
+ (~lhs)(element->index(),j) = element->value();
+ else
+ (~lhs)(element->index(),j) += element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix addition to a
+ // row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a transpose sparse matrix-transpose
+ // sparse matrix addition expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+
+ // Counting the number of elements per column
+ std::vector<size_t> nonzeros( m, 0UL );
+ for( size_t j=0UL; j<n; ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ ++nonzeros[l->index()];
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ ++nonzeros[r->index()];
+ ++r;
+ }
+ else {
+ ++nonzeros[l->index()];
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ ++nonzeros[l->index()];
+ ++l;
+ }
+
+ while( r != rend ) {
+ ++nonzeros[r->index()];
+ ++r;
+ }
+ }
+
+ // Resizing the left-hand side sparse matrix
+ for( size_t i=0UL; i<m; ++i ) {
+ (~lhs).reserve( i, nonzeros[i] );
+ }
+
+ // Performing the matrix addition
+ for( size_t j=0UL; j<n; ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), j, r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), j, l->value()+r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), j, r->value() );
+ ++r;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix addition to a
+ // row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose sparse matrix addition expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) + trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix addition to a
+ // column-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side addition expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose sparse matrix addition expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix addition
+ for( size_t j=0UL; j<(~lhs).columns(); ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), j, r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), j, l->value()+r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), j, r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( j );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse matrix-transpose sparse matrix addition
+ // to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse matrix-transpose sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse matrix-transpose sparse matrix
+ // addition to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-transpose sparse matrix addition expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse matrix-transpose sparse matrix addition
+ // to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse matrix-transpose sparse matrix addition expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse matrix-transpose sparse matrix
+ // addition to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side addition expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse matrix-transpose sparse matrix addition expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatAddExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATADDEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition operator for the addition of two column-major sparse matrices (\f$ A=B+C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix addition.
+// \param rhs The right-hand side sparse matrix to be added to the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the addition of two column-major sparse matrices:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,columnMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A + B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the AddTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const TSMatTSMatAddExpr<T1,T2>
+ operator+( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TSMatTSMatAddExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TSMatTSMatAddExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TSMatTSMatAddExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< TSMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< TSMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TSMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TSMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >
+ , And< IsUniLower<MT2>, IsStrictlyLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TSMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TSMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TSMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >
+ , And< IsUniUpper<MT2>, IsStrictlyUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TSMatTSMatAddExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TSMatTSMatAddExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TSMatTSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TSMatTSMatAddExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = AddExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatTSMatMultExpr.h b/src/cpu/blaze/math/expressions/TSMatTSMatMultExpr.h
new file mode 100644
index 00000000..4da8dcd3
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatTSMatMultExpr.h
@@ -0,0 +1,1439 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatTSMatMultExpr.h
+// \brief Header file for the transpose sparse matrix/transpose sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATTSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/Infinity.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSMatMultExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSMATTSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-transpose sparse matrix multiplications.
+// \ingroup sparse_matrix_expression
+//
+// The TSMatTSMatMultExpr class represents the compile time expression for multiplications between
+// two column-major sparse matrices.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TSMatTSMatMultExpr : public SparseMatrix< TSMatTSMatMultExpr<MT1,MT2>, true >
+ , private MatMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse matrix expression.
+ enum : bool { evaluateLeft = RequiresEvaluation<MT1>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateRight = RequiresEvaluation<MT2>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The CanExploitSymmetry struct is a helper struct for the selection of the optimal
+ evaluation strategy. In case the target matrix is row-major and both matrix operands
+ are symmetric, \a value is set to 1 and an optimized evaluation strategy is selected.
+ Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct CanExploitSymmetry {
+ enum : bool { value = IsRowMajorMatrix<T1>::value &&
+ IsSymmetric<T2>::value && IsSymmetric<T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The IsEvaluationRequired struct is a helper struct for the selection of the parallel
+ evaluation strategy. In case either of the two matrix operands requires an intermediate
+ evaluation and in case no symmetry can be exploited, the nested \value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct IsEvaluationRequired {
+ enum : bool { value = ( evaluateLeft || evaluateRight ) &&
+ !CanExploitSymmetry<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatTSMatMultExpr<MT1,MT2> This; //!< Type of this TSMatTSMatMultExpr instance.
+ typedef MultTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
+ !evaluateRight && MT2::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatTSMatMultExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the multiplication expression.
+ // \param rhs The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline TSMatTSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
+
+ if( IsDiagonal<MT1>::value ) {
+ return lhs_(i,i) * rhs_(i,j);
+ }
+ else if( IsDiagonal<MT2>::value ) {
+ return lhs_(i,j) * rhs_(j,j);
+ }
+ else if( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) {
+ const size_t begin( ( IsUpper<MT1>::value )
+ ?( ( IsLower<MT2>::value )
+ ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
+ , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
+ :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
+ :( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
+ :( 0UL ) ) );
+ const size_t end( ( IsLower<MT1>::value )
+ ?( ( IsUpper<MT2>::value )
+ ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
+ , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
+ :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
+ :( ( IsUpper<MT2>::value )
+ ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
+ :( lhs_.columns() ) ) );
+
+ if( begin >= end ) return ElementType();
+
+ const size_t n( end - begin );
+
+ return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
+ }
+ else {
+ return row( lhs_, i ) * column( rhs_, j );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= rhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return rhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline constexpr size_t nonZeros() const noexcept {
+ return 0UL;
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const noexcept {
+ UNUSED_PARAMETER( i );
+ return 0UL;
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( rows() > SMP_TSMATTSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the multiplication expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix multiplication
+ // to a dense matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense matrices********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose sparse matrix-transpose sparse matrix multiplication
+ // (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose sparse matrix-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t j=0UL; j<C.columns(); ++j ) {
+ const RightIterator rend( B.end(j) );
+ for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
+ const LeftIterator lend( A.end( relem->index() ) );
+ for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem )
+ {
+ if( IsResizable< ElementType_<MT3> >::value &&
+ isDefault( C(lelem->index(),j) ) ) {
+ C(lelem->index(),j) = lelem->value() * relem->value();
+ }
+ else {
+ C(lelem->index(),j) += lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix multiplication to a
+ // row-major sparse matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose sparse matrix multiplication expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( ResultType );
+
+ const ResultType tmp( serial( rhs ) );
+ (~lhs).reserve( tmp.nonZeros() );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix multiplication to a
+ // column-major sparse matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose sparse matrix multiplication expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // (Over-)Estimating the number of non-zero entries in the resulting matrix
+ size_t nonzeros( 0UL );
+
+ for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
+ const RightIterator rend( B.end(j) );
+ for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
+ nonzeros += A.nonZeros( relem->index() );
+ }
+ }
+
+ if( nonzeros > (~lhs).rows() * (~lhs).columns() ) {
+ nonzeros = (~lhs).rows() * (~lhs).columns();
+ }
+
+ (~lhs).reserve( nonzeros );
+ nonzeros = 0UL;
+
+ // Performing the matrix-matrix multiplication
+ std::vector<ElementType> values ( (~lhs).rows(), ElementType() );
+ std::vector<byte_t> valid ( (~lhs).rows(), 0 );
+ std::vector<size_t> indices( (~lhs).rows(), 0UL );
+ size_t minIndex( inf ), maxIndex( 0UL );
+
+ for( size_t j=0UL; j<(~lhs).columns(); ++j )
+ {
+ const RightIterator rend( B.end(j) );
+ for( RightIterator relem=B.begin(j); relem!=rend; ++relem )
+ {
+ const LeftIterator lend( A.end( relem->index() ) );
+ for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem )
+ {
+ if( !valid[lelem->index()] ) {
+ values[lelem->index()] = lelem->value() * relem->value();
+ valid [lelem->index()] = 1;
+ indices[nonzeros] = lelem->index();
+ ++nonzeros;
+ if( lelem->index() < minIndex ) minIndex = lelem->index();
+ if( lelem->index() > maxIndex ) maxIndex = lelem->index();
+ }
+ else {
+ values[lelem->index()] += lelem->value() * relem->value();
+ }
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( nonzeros <= (~lhs).rows(), "Invalid number of non-zero elements" );
+
+ if( nonzeros > 0UL )
+ {
+ BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
+
+ if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
+ {
+ std::sort( indices.begin(), indices.begin() + nonzeros );
+
+ for( size_t i=0UL; i<nonzeros; ++i )
+ {
+ const size_t index( indices[i] );
+ if( !isDefault( values[index] ) ) {
+ (~lhs).append( index, j, values[index] );
+ reset( values[index] );
+ }
+
+ reset( valid [index] );
+ }
+ }
+ else {
+ for( size_t i=minIndex; i<=maxIndex; ++i )
+ {
+ if( !isDefault( values[i] ) ) {
+ (~lhs).append( i, j, values[i] );
+ reset( values[i] );
+ }
+
+ reset( valid [i] );
+ }
+ }
+
+ nonzeros = 0UL;
+ minIndex = inf;
+ maxIndex = 0UL;
+ }
+
+ (~lhs).finalize( j );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring assignment to row-major matrices**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication to a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring assignment of a transpose sparse
+ // matrix-transpose sparse matrix multiplication expression to a row-major matrix. Due to the
+ // explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ assign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose sparse
+ // matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matarix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense matrices***********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose sparse
+ // matrix-transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t j=0UL; j<C.columns(); ++j ) {
+ const RightIterator rend( B.end(j) );
+ for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
+ const LeftIterator lend( A.end( relem->index() ) );
+ for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem ) {
+ C(lelem->index(),j) += lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring addition assignment to row-major matrices*************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring addition assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring addition assignment of a transpose
+ // sparse matrix-transpose sparse matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ addAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-sparse matrix multiplication expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matarix
+ friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ TSMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense matrices********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param C The target left-hand side dense matrix.
+ // \param A The left-hand side sparse matrix operand.
+ // \param B The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose sparse
+ // matrix-transpose sparse matrix multiplication.
+ */
+ template< typename MT3 // Type of the left-hand side target matrix
+ , typename MT4 // Type of the left-hand side matrix operand
+ , typename MT5 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
+ {
+ typedef ConstIterator_<MT4> LeftIterator;
+ typedef ConstIterator_<MT5> RightIterator;
+
+ for( size_t j=0UL; j<C.columns(); ++j ) {
+ const RightIterator rend( B.end(j) );
+ for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
+ const LeftIterator lend( A.end( relem->index() ) );
+ for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem ) {
+ C(lelem->index(),j) -= lelem->value() * relem->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring subtraction assignment to row-major matrices**********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring subtraction assignment of a transpose sparse matrix-transpose sparse
+ // matrix multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring subtraction assignment of a
+ // transpose sparse matrix-transpose sparse matrix multiplication expression to a row-major
+ // matrix. Due to the explicit application of the SFINAE principle this function can only
+ // be selected by the compiler in case the symmetry of either of the two matrix operands
+ // can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ subAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to matrices******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse matrix-transpose sparse matrix multiplication
+ // to a matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // matrix-transpose sparse matrix multiplication expression to a matrix. Due to the explicit
+ // application of the SFINAE principle this function can only be selected by the compiler in
+ // case either of the two matrix operands requires an intermediate evaluation and no symmetry
+ // can be exploited.
+ */
+ template< typename MT // Type of the target matrix
+ , bool SO > // Storage order of the target matrix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP assignment to row-major matrices******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication to a row-major matrix (\f$ C=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP assignment of a transpose
+ // sparse matrix-transpose sparse matrix multiplication expression to a row-major matrix. Due
+ // to the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case the symmetry of either of the two matrix operands can be exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication to a dense matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse matrix-transpose sparse matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by
+ // the compiler in case either of the two matrix operands requires an intermediate evaluation
+ // and no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matarix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP addition assignment to row-major matrices*********************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP addition assignment of a transpose sparse matrix-transpose sparse
+ // matrix multiplication to a row-major matrix (\f$ C+=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP addition assignment of a
+ // transpose sparse matrix-transpose sparse matrix multiplication expression to a row-major
+ // matrix. Due to the explicit application of the SFINAE principle this function can only be
+ // selected by the compiler in case the symmetry of either of the two matrix operands can be
+ // exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpAddAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse matrix-transpose sparse matrix
+ // multiplication to a dense matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse matrix-transpose sparse matrix multiplication expression to a dense matrix. Due to
+ // the explicit application of the SFINAE principle this function can only be selected by the
+ // compiler in case either of the two matrix operands requires an intermediate evaluation and
+ // no symmetry can be exploited.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matarix
+ friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, A * B );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Restructuring SMP subtraction assignment to row-major matrices******************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Restructuring SMP subtraction assignment of a transpose sparse matrix-transpose sparse
+ // matrix multiplication to a row-major matrix (\f$ C-=A*B \f$).
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side matrix.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the symmetry-based restructuring SMP subtraction assignment of a
+ // transpose sparse matrix-transpose sparse matrix multiplication expression to a row-major
+ // matrix. Due to the explicit application of the SFINAE principle this function can only be
+ // selected by the compiler in case the symmetry of either of the two matrix operands can be
+ // exploited.
+ */
+ template< typename MT > // Type of the target matrix
+ friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
+ smpSubAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of two column-major sparse matrices
+// (\f$ A=B*C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix multiplication.
+// \param rhs The right-hand side sparse matrix for the matrix multiplication.
+// \return The product of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the multiplication of two column-major sparse matrices:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A * B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the MultTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const TSMatTSMatMultExpr<T1,T2>
+ operator*( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TSMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TSMatTSMatMultExpr<MT1,MT2> > : public Rows<MT1>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TSMatTSMatMultExpr<MT1,MT2> > : public Columns<MT2>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TSMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TSMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TSMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
+ , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TSMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TSMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TSMatTSMatMultExpr<MT1,MT2> >
+ : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
+ , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TSMatDVecMultExprTrait< TSMatTSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TSMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, typename VT >
+struct TSMatSVecMultExprTrait< TSMatTSMatMultExpr<MT1,MT2>, VT >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TSMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_<MT2,VT> >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TDVecTSMatMultExprTrait< VT, TSMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDVecTSMatMultExprTrait_< TDVecTSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT1, typename MT2 >
+struct TSVecTSMatMultExprTrait< VT, TSMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TSVecTSMatMultExprTrait_< TSVecTSMatMultExprTrait_<VT,MT1>, MT2 >
+ , INVALID_TYPE >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TSMatTSMatMultExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TSMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TSMatTSMatMultExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSMatTSMatSubExpr.h b/src/cpu/blaze/math/expressions/TSMatTSMatSubExpr.h
new file mode 100644
index 00000000..e5c280d8
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSMatTSMatSubExpr.h
@@ -0,0 +1,1064 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSMatTSMatSubExpr.h
+// \brief Header file for the transpose sparse matrix/transpose sparse matrix subtraction expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTSMATSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSMATTSMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatSubExpr.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTemporary.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/Rows.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSMATTSMATSUBEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse matrix-transpose sparse matrix subtractions.
+// \ingroup sparse_matrix_expression
+//
+// The TSMatTSMatSubExpr class represents the compile time expression for subtractions between
+// two column-major sparse matrices.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+class TSMatTSMatSubExpr : public SparseMatrix< TSMatTSMatSubExpr<MT1,MT2>, true >
+ , private MatMatSubExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT1> RT1; //!< Result type of the left-hand side sparse matrix expression.
+ typedef ResultType_<MT2> RT2; //!< Result type of the right-hand side sparse matrix expression.
+ typedef ReturnType_<MT1> RN1; //!< Return type of the left-hand side sparse matrix expression.
+ typedef ReturnType_<MT2> RN2; //!< Return type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<MT1> CT1; //!< Composite type of the left-hand side sparse matrix expression.
+ typedef CompositeType_<MT2> CT2; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**Return type evaluation**********************************************************************
+ //! Compilation switch for the selection of the subscript operator return type.
+ /*! The \a returnExpr compile time constant expression is a compilation switch for the
+ selection of the \a ReturnType. If either matrix operand returns a temporary vector
+ or matrix, \a returnExpr will be set to \a false and the subscript operator will
+ return it's result by value. Otherwise \a returnExpr will be set to \a true and
+ the subscript operator may return it's result as an expression. */
+ enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
+
+ //! Expression return type for the subscript operator.
+ typedef SubExprTrait_<RN1,RN2> ExprReturnType;
+ //**********************************************************************************************
+
+ //**Serial evaluation strategy******************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSymmetricKernel struct is a helper struct for the selection of the serial
+ evaluation strategy. In case the target matrix is column-major and both matrix
+ operands are symmetric, \a value is set to 1 and an optimized evaluation strategy
+ is selected. Otherwise \a value is set to 0 and the default strategy is chosen. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseSymmetricKernel {
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( T1 );
+ enum : bool { value = IsSymmetric<T2>::value && IsSymmetric<T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Parallel evaluation strategy****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case the target matrix is SMP assignable, \a value is set to 1 and the
+ expression specific evaluation strategy is selected. Otherwise \a value is set to 0
+ and the default strategy is chosen. */
+ template< typename MT >
+ struct UseSMPAssign {
+ enum : bool { value = MT::smpAssignable };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSMatTSMatSubExpr<MT1,MT2> This; //!< Type of this TSMatTSMatSubExpr instance.
+ typedef SubTrait_<RT1,RT2> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+
+ //! Return type for expression template evaluations.
+ typedef const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType;
+
+ //! Data type for composite expression templates.
+ typedef const ResultType CompositeType;
+
+ //! Composite type of the left-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSMatTSMatSubExpr class.
+ //
+ // \param lhs The left-hand side sparse matrix operand of the subtraction expression.
+ // \param rhs The right-hand side sparse matrix operand of the subtraction expression.
+ */
+ explicit inline TSMatTSMatSubExpr( const MT1& lhs, const MT2& rhs ) noexcept
+ : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
+ , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction expression
+ {
+ BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
+ }
+ //**********************************************************************************************
+
+ //**Access operator*****************************************************************************
+ /*!\brief 2D-access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator()( size_t i, size_t j ) const {
+ BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
+ return lhs_(i,j) - rhs_(i,j);
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the matrix elements.
+ //
+ // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+ // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid matrix access index.
+ */
+ inline ReturnType at( size_t i, size_t j ) const {
+ if( i >= lhs_.rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= lhs_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+ }
+ //**********************************************************************************************
+
+ //**Rows function*******************************************************************************
+ /*!\brief Returns the current number of rows of the matrix.
+ //
+ // \return The number of rows of the matrix.
+ */
+ inline size_t rows() const noexcept {
+ return lhs_.rows();
+ }
+ //**********************************************************************************************
+
+ //**Columns function****************************************************************************
+ /*!\brief Returns the current number of columns of the matrix.
+ //
+ // \return The number of columns of the matrix.
+ */
+ inline size_t columns() const noexcept {
+ return lhs_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the sparse matrix.
+ //
+ // \return The number of non-zero elements in the sparse matrix.
+ */
+ inline size_t nonZeros() const {
+ return lhs_.nonZeros() + rhs_.nonZeros();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns the number of non-zero elements in the specified row.
+ //
+ // \param i The index of the row.
+ // \return The number of non-zero elements of row \a i.
+ */
+ inline size_t nonZeros( size_t i ) const {
+ return lhs_.nonZeros(i) + rhs_.nonZeros(i);
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side transpose sparse matrix operand.
+ //
+ // \return The left-hand side transpose sparse matrix operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return lhs_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return rhs_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand lhs_; //!< Left-hand side sparse matrix of the subtraction expression.
+ RightOperand rhs_; //!< Right-hand side sparse matrix of the subtraction expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense matrices****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix subtraction to a
+ // dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpsoe sparse matrix-
+ // transpose sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void assign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ assign( ~lhs, rhs.lhs_ );
+
+ if( !IsResizable< ElementType_<MT> >::value ) {
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ else
+ {
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
+ const RightIterator end( B.end(j) );
+ for( RightIterator element=B.begin(j); element!=end; ++element ) {
+ if( isDefault( (~lhs)(element->index(),j) ) )
+ (~lhs)(element->index(),j) = -element->value();
+ else
+ (~lhs)(element->index(),j) -= element->value();
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix subtraction to a
+ // row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the default assignment of a transpose sparse matrix-transpose
+ // sparse matrix subtraction expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline DisableIf_< UseSymmetricKernel<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ const size_t m( rhs.rows() );
+ const size_t n( rhs.columns() );
+
+ // Counting the number of elements per column
+ std::vector<size_t> nonzeros( m, 0UL );
+ for( size_t j=0UL; j<n; ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ ++nonzeros[l->index()];
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ ++nonzeros[r->index()];
+ ++r;
+ }
+ else {
+ ++nonzeros[l->index()];
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ ++nonzeros[l->index()];
+ ++l;
+ }
+
+ while( r != rend ) {
+ ++nonzeros[r->index()];
+ ++r;
+ }
+ }
+
+ // Resizing the left-hand side sparse matrix
+ for( size_t i=0UL; i<m; ++i ) {
+ (~lhs).reserve( i, nonzeros[i] );
+ }
+
+ // Performing the matrix subtraction
+ for( size_t j=0UL; j<n; ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), j, -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), j, l->value()-r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), j, -r->value() );
+ ++r;
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to row-major sparse matrices*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix subtraction to a
+ // row-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose sparse matrix subtraction expression to a row-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline EnableIf_< UseSymmetricKernel<MT,MT1,MT2> >
+ assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ assign( ~lhs, trans( rhs.lhs_ ) - trans( rhs.rhs_ ) );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to column-major sparse matrices**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse matrix-transpose sparse matrix subtraction to a
+ // column-major sparse matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side sparse matrix.
+ // \param rhs The right-hand side subtraction expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse matrix-
+ // transpose sparse matrix subtraction expression to a column-major sparse matrix.
+ */
+ template< typename MT > // Type of the target sparse matrix
+ friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_< RemoveReference_<CT1> > LeftIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RightIterator;
+
+ CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
+ CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
+
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
+
+ // Final memory allocation (based on the evaluated operands)
+ (~lhs).reserve( A.nonZeros() + B.nonZeros() );
+
+ // Performing the matrix subtraction
+ for( size_t j=0UL; j<(~lhs).columns(); ++j )
+ {
+ const LeftIterator lend( A.end(j) );
+ const RightIterator rend( B.end(j) );
+
+ LeftIterator l( A.begin(j) );
+ RightIterator r( B.begin(j) );
+
+ while( l != lend && r != rend )
+ {
+ if( l->index() < r->index() ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+ else if( l->index() > r->index() ) {
+ (~lhs).append( r->index(), j, -r->value() );
+ ++r;
+ }
+ else {
+ (~lhs).append( l->index(), j, l->value()-r->value() );
+ ++l;
+ ++r;
+ }
+ }
+
+ while( l != lend ) {
+ (~lhs).append( l->index(), j, l->value() );
+ ++l;
+ }
+
+ while( r != rend ) {
+ (~lhs).append( r->index(), j, -r->value() );
+ ++r;
+ }
+
+ (~lhs).finalize( j );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense matrices*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse matrix-transpose sparse matrix subtraction
+ // to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse matrix-transpose sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, rhs.lhs_ );
+ subAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse matrices******************************************************
+ // No special implementation for the addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense matrices****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse matrix-transpose sparse matrix
+ // subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse matrix-transpose sparse matrix subtraction expression to a dense matrix.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, rhs.lhs_ );
+ addAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse matrices***************************************************
+ // No special implementation for the subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense matrices*************************************************
+ // No special implementation for the multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse matrices************************************************
+ // No special implementation for the multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense matrices************************************************************
+ // No special implementation for the SMP assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse matrices***********************************************************
+ // No special implementation for the SMP assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense matrices***************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse matrix-transpose sparse matrix
+ // subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse matrix-transpose sparse matrix subtraction expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpAddAssign( ~lhs, rhs.lhs_ );
+ smpSubAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse matrices**************************************************
+ // No special implementation for the SMP addition assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense matrices************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse matrix-transpose sparse matrix
+ // subtraction to a dense matrix.
+ // \ingroup sparse_matrix
+ //
+ // \param lhs The target left-hand side dense matrix.
+ // \param rhs The right-hand side subtraction expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse matrix-transpose sparse matrix subtraction expression to a dense matrix. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename MT // Type of the target dense matrix
+ , bool SO > // Storage order of the target dense matrix
+ friend inline EnableIf_< UseSMPAssign<MT> >
+ smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
+
+ smpSubAssign( ~lhs, rhs.lhs_ );
+ smpAddAssign( ~lhs, rhs.rhs_ );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse matrices***********************************************
+ // No special implementation for the SMP subtraction assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense matrices*********************************************
+ // No special implementation for the SMP multiplication assignment to dense matrices.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse matrices********************************************
+ // No special implementation for the SMP multiplication assignment to sparse matrices.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATSUBEXPR( MT1, MT2 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for the subtraction of two column-major sparse matrices
+// (\f$ A=B-C \f$).
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the matrix subtraction.
+// \param rhs The right-hand side sparse matrix to be subtracted from the left-hand side matrix.
+// \return The sum of the two matrices.
+// \exception std::invalid_argument Matrix sizes do not match
+//
+// This operator represents the subtraction of two column-major sparse matrices:
+
+ \code
+ using blaze::columnMajor;
+
+ blaze::CompressedMatrix<double,columnMajor> A, B, C;
+ // ... Resizing and initialization
+ C = A - B;
+ \endcode
+
+// The operator returns an expression representing a sparse matrix of the higher-order element
+// type of the two involved matrix element types \a T1::ElementType and \a T2::ElementType.
+// Both matrix types \a T1 and \a T2 as well as the two element types \a T1::ElementType and
+// \a T2::ElementType have to be supported by the SubTrait class template.\n
+// In case the current number of rows and columns of the two given matrices don't match, a
+// \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const TSMatTSMatSubExpr<T1,T2>
+ operator-( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ return TSMatTSMatSubExpr<T1,T2>( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Rows< TSMatTSMatSubExpr<MT1,MT2> >
+ : public Max< Rows<MT1>, Rows<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct Columns< TSMatTSMatSubExpr<MT1,MT2> >
+ : public Max< Columns<MT1>, Columns<MT2> >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSYMMETRIC SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsSymmetric< TSMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsSymmetric<MT1>::value && IsSymmetric<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISHERMITIAN SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsHermitian< TSMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< IsHermitian<MT1>::value && IsHermitian<MT2>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsLower< TSMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNILOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniLower< TSMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYLOWER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyLower< TSMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUpper< TSMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISUNIUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsUniUpper< TSMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsUniUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISSTRICTLYUPPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct IsStrictlyUpper< TSMatTSMatSubExpr<MT1,MT2> >
+ : public BoolConstant< And< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2, bool AF >
+struct SubmatrixExprTrait< TSMatTSMatSubExpr<MT1,MT2>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< SubmatrixExprTrait_<const MT1,AF>
+ , SubmatrixExprTrait_<const MT2,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct RowExprTrait< TSMatTSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< RowExprTrait_<const MT1>
+ , RowExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT1, typename MT2 >
+struct ColumnExprTrait< TSMatTSMatSubExpr<MT1,MT2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = SubExprTrait_< ColumnExprTrait_<const MT1>
+ , ColumnExprTrait_<const MT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSVecDMatMultExpr.h b/src/cpu/blaze/math/expressions/TSVecDMatMultExpr.h
new file mode 100644
index 00000000..c52d78aa
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSVecDMatMultExpr.h
@@ -0,0 +1,1839 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSVecDMatMultExpr.h
+// \brief Header file for the transpose sparse vector/dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSVECDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse vector-dense matrix multiplications.
+// \ingroup dense_vector_expression
+//
+// The TSVecDMatMultExpr class represents the compile time expression for multiplications
+// between transpose sparse vectors and row-major dense matrices.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename MT > // Type of the right-hand side dense matrix
+class TSVecDMatMultExpr : public DenseVector< TSVecDMatMultExpr<VT,MT>, true >
+ , private TVecMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side dense matrix expression.
+ typedef ElementType_<VRT> VET; //!< Element type of the left-hand side sparse vector expression.
+ typedef ElementType_<MRT> MET; //!< Element type of the right-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the vector or the matrix operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateVector || evaluateMatrix ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case the matrix type and the two involved vector types are suited for a vectorized
+ computation of the vector/matrix multiplication, the nested \value will be set to 1,
+ otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseVectorizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !IsDiagonal<T3>::value &&
+ T1::simdEnabled && T3::simdEnabled &&
+ AreSIMDCombinable< ElementType_<T1>
+ , ElementType_<T2>
+ , ElementType_<T3> >::value &&
+ HasSIMDAdd< ElementType_<T2>, ElementType_<T3> >::value &&
+ HasSIMDMult< ElementType_<T2>, ElementType_<T3> >::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case a vectorized computation of the vector/matrix multiplication is not possible, but
+ a loop-unrolled computation is feasible, the nested \value will be set to 1, otherwise it
+ will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseOptimizedKernel {
+ enum : bool { value = useOptimizedKernels &&
+ !UseVectorizedKernel<T1,T2,T3>::value &&
+ !IsDiagonal<T3>::value &&
+ !IsResizable< ElementType_<T1> >::value &&
+ !IsResizable<VET>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! In case neither a vectorized nor optimized computation is possible, the nested \value will
+ be set to 1, otherwise it will be 0. */
+ template< typename T1, typename T2, typename T3 >
+ struct UseDefaultKernel {
+ enum : bool { value = !UseVectorizedKernel<T1,T2,T3>::value &&
+ !UseOptimizedKernel<T1,T2,T3>::value };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSVecDMatMultExpr<VT,MT> This; //!< Type of this TSVecDMatMultExpr instance.
+ typedef MultTrait_<VRT,MRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< Resulting SIMD element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Type for the assignment of the right-hand side dense matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = !IsDiagonal<MT>::value &&
+ MT::simdEnabled &&
+ HasSIMDAdd<VET,MET>::value &&
+ HasSIMDMult<VET,MET>::value };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSVecDMatMultExpr class.
+ //
+ // \param vec The left-hand side sparse vector operand of the multiplication expression.
+ // \param mat The right-hand side dense matrix operand of the multiplication expression.
+ */
+ explicit inline TSVecDMatMultExpr( const VT& vec, const MT& mat ) noexcept
+ : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
+ , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return vec_[index] * mat_(index,index);
+ }
+ else if( IsLower<MT>::value )
+ {
+ const size_t begin( IsStrictlyLower<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.rows() - begin );
+ return subvector( vec_, begin, n ) * subvector( column( mat_, index ), begin, n );
+ }
+ else if( IsUpper<MT>::value )
+ {
+ const size_t n( IsStrictlyUpper<MT>::value ? index : index+1UL );
+ return subvector( vec_, 0UL, n ) * subvector( column( mat_, index ), 0UL, n );
+ }
+ else
+ {
+ return vec_ * column( mat_, index );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side dense matrix operand.
+ //
+ // \return The right-hand side dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return vec_.isAliased( alias ) || mat_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vec_.isAliased( alias ) || mat_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return mat_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_TSVECDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vec_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand mat_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse vector-dense matrix multiplication to a dense vector
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse vector-
+ // dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ TSVecDMatMultExpr::selectAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose sparse vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose sparse vector-
+ // dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<VT1,VT2,MT1> >
+ selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ size_t last( 0UL );
+
+ if( IsUpper<MT1>::value ) {
+ const size_t jend( IsStrictlyUpper<MT1>::value ? element->index()+1UL : element->index() );
+ for( size_t j=0UL; j<jend; ++j )
+ reset( y[j] );
+ }
+
+ for( ; element!=end; ++element )
+ {
+ const size_t index( element->index() );
+
+ if( IsDiagonal<MT1>::value )
+ {
+
+
+ for( size_t j=last; j<index; ++j )
+ reset( y[j] );
+
+ y[index] = element->value() * A(index,index);
+ last = index + 1UL;
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? index+1UL : index )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? index : index+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<last; ++j ) {
+ y[j] += element->value() * A(index,j);
+ }
+ for( size_t j=last; j<jend; ++j ) {
+ y[j] = element->value() * A(index,j);
+ }
+
+ last = jend;
+ }
+ }
+
+ if( IsLower<MT1>::value ) {
+ for( size_t j=last; j<N; ++j )
+ reset( y[j] );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized assignment to dense vectors*******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized assignment of a transpose sparse vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the optimized assignment kernel for the transpose sparse vector-
+ // dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<VT1,VT2,MT1> >
+ selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t ipos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ if( ipos > 3UL )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
+
+ for( size_t j=0UL; j<N; ++j ) {
+ y[j] = v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
+ }
+ }
+ else
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+
+ for( size_t j=0UL; j<N; ++j ) {
+ y[j] = v1 * A(i1,j);
+ }
+ }
+
+ for( size_t i=(ipos>3UL)?(4UL):(1UL); (i+4UL)<=ipos; i+=4UL )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ y[j] += v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ y[j] += v1 * A(i1,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized assignment to dense vectors******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized assignment of a transpose sparse vector-dense matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized assignment kernel for the transpose sparse vector-
+ // dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<VT1,VT2,MT1> >
+ selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t ipos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ if( ipos > 3UL )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ y.store( j, xmm1 * A.load(i1,j) + xmm2 * A.load(i2,j) + xmm3 * A.load(i3,j) + xmm4 * A.load(i4,j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ y[j] = v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
+ }
+ }
+ else
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t jpos( remainder ? ( N & size_t(-SIMDSIZE) ) : N );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ y.store( j, xmm1 * A.load(i1,j) );
+ }
+ for( ; remainder && j<N; ++j ) {
+ y[j] = v1 * A(i1,j);
+ }
+ }
+
+ for( size_t i=(ipos>3UL)?(4UL):(1UL); (i+4UL)<=ipos; i+=4UL )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ y.store( j, y.load(j) + xmm1 * A.load(i1,j) + xmm2 * A.load(i2,j) + xmm3 * A.load(i3,j) + xmm4 * A.load(i4,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ y[j] += v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ y.store( j, y.load(j) + xmm1 * A.load(i1,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ y[j] += v1 * A(i1,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse vector-dense matrix multiplication to a sparse
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse vector-
+ // dense matrix multiplication expression to a sparse vector.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*!\brief Addition assignment of a transpose sparse vector-dense matrix multiplication to a
+ // dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose sparse
+ // vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ TSVecDMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
+ }
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose sparse vector-dense matrix multiplication
+ // (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose sparse
+ // vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<VT1,VT2,MT1> >
+ selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t index( element->index() );
+
+ if( IsDiagonal<MT1>::value )
+ {
+ y[index] += A(index,index) * element->value();
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? index+1UL : index )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? index : index+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ y[j] += element->value() * A(index,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized addition assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized addition assignment of a transpose sparse vector-dense matrix multiplication
+ // (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the optimized addition assignment kernel for the transpose sparse
+ // vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<VT1,VT2,MT1> >
+ selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t ipos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; (i+4UL)<=ipos; i+=4UL )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i1 )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ y[j] += v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ y[j] += v1 * A(i1,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized addition assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized addition assignment of a transpose sparse vector-dense matrix multiplication
+ // (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized addition assignment kernel for the transpose sparse
+ // vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<VT1,VT2,MT1> >
+ selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t ipos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; (i+4UL)<=ipos; i+=4UL )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ y.store( j, y.load(j) + xmm1 * A.load(i1,j) + xmm2 * A.load(i2,j) + xmm3 * A.load(i3,j) + xmm4 * A.load(i4,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ y[j] += v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ y.store( j, y.load(j) + xmm1 * A.load(i1,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ y[j] += v1 * A(i1,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*!\brief Subtraction assignment of a transpose sparse vector-dense matrix multiplication to a
+ // dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ TSVecDMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
+ }
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose sparse vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose
+ // sparse vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseDefaultKernel<VT1,VT2,MT1> >
+ selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ for( ; element!=end; ++element )
+ {
+ const size_t index( element->index() );
+
+ if( IsDiagonal<MT1>::value )
+ {
+ y[index] -= A(index,index) * element->value();
+ }
+ else
+ {
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? index+1UL : index )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? index : index+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ y[j] -= element->value() * A(index,j);
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Optimized subtraction assignment to dense vectors*******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Optimized subtraction assignment of a transpose sparse vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the optimized subtraction assignment kernel for the transpose
+ // sparse vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseOptimizedKernel<VT1,VT2,MT1> >
+ selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t ipos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; (i+4UL)<=ipos; i+=4UL )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i+1UL : i1 )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ y[j] -= v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
+ }
+ }
+ for( ; element!=end; ++element )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ y[j] -= v1 * A(i1,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Vectorized subtraction assignment to dense vectors******************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Vectorized subtraction assignment of a transpose sparse vector-dense matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side dense matrix operand.
+ // \return void
+ //
+ // This function implements the vectorized subtraction assignment kernel for the transpose
+ // sparse vector-dense matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline EnableIf_< UseVectorizedKernel<VT1,VT2,MT1> >
+ selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<LT> > ConstIterator;
+
+ BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
+
+ const size_t N( A.columns() );
+
+ const bool remainder( !IsPadded<VT1>::value || !IsPadded<MT1>::value );
+
+ ConstIterator element( x.begin() );
+ const ConstIterator end( x.end() );
+
+ const size_t ipos( x.nonZeros() & size_t(-4) );
+ BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t i=0UL; (i+4UL)<=ipos; i+=4UL )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+ ++element;
+ const size_t i2( element->index() );
+ const VET v2( element->value() );
+ ++element;
+ const size_t i3( element->index() );
+ const VET v3( element->value() );
+ ++element;
+ const size_t i4( element->index() );
+ const VET v4( element->value() );
+ ++element;
+
+ BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
+
+ const SIMDType xmm1( set( v1 ) );
+ const SIMDType xmm2( set( v2 ) );
+ const SIMDType xmm3( set( v3 ) );
+ const SIMDType xmm4( set( v4 ) );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ y.store( j, y.load(j) - xmm1 * A.load(i1,j) - xmm2 * A.load(i2,j) - xmm3 * A.load(i3,j) - xmm4 * A.load(i4,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ y[j] -= v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
+ }
+ }
+ for( ; element!=x.end(); ++element )
+ {
+ const size_t i1( element->index() );
+ const VET v1( element->value() );
+
+ const SIMDType xmm1( set( v1 ) );
+
+ const size_t jbegin( ( IsUpper<MT1>::value )
+ ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend( ( IsLower<MT1>::value )
+ ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
+ :( N ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( remainder ? ( jend & size_t(-SIMDSIZE) ) : jend );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % SIMDSIZE ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ y.store( j, y.load(j) - xmm1 * A.load(i1,j) );
+ }
+ for( ; remainder && j<jend; ++j ) {
+ y[j] -= v1 * A(i1,j);
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*!\brief Multiplication assignment of a transpose sparse vector-dense matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // sparse vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*!\brief Division assignment of a transpose sparse vector-dense matrix multiplication to a
+ // dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a transpose sparse
+ // vector-dense matrix multiplication expression to a dense vector.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline void divAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse vector-dense matrix multiplication to a dense
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ smpAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse vector-dense matrix multiplication to a sparse
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // vector-dense matrix multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*!\brief SMP addition assignment of a transpose sparse vector-dense matrix multiplication to
+ // a dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ smpAddAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*!\brief SMP subtraction assignment of a transpose sparse vector-dense matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ smpSubAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*!\brief SMP multiplication assignment of a transpose sparse vector-dense matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose sparse vector-dense matrix multiplication expression to a dense vector. Due
+ // to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*!\brief SMP division assignment of a transpose sparse vector-dense matrix multiplication to
+ // a dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a transpose
+ // sparse vector-dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR( VT, MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector and a
+// row-major dense matrix (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+// \ingroup dense_matrix
+//
+// \param vec The left-hand side transpose sparse vector for the multiplication.
+// \param mat The right-hand side row-major dense matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator represents the multiplication between a transpose sparse vector and a row-major
+// dense matrix:
+
+ \code
+ using blaze::rowVector;
+ using blaze::rowMajor;
+
+ blaze::CompressedVector<double,rowVector> x, y;
+ blaze::DynamicMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ y = x * A;
+ \endcode
+
+// The operator returns an expression representing a transpose sparse vector of the higher-order
+// element type of the two involved element types \a T1::ElementType and \a T2::ElementType.
+// Both the dense matrix type \a T1 and the dense vector type \a T2 as well as the two element
+// types \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of rows of
+// the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1, typename T2 >
+inline const DisableIf_< IsMatMatMultExpr<T2>, TSVecDMatMultExpr<T1,T2> >
+ operator*( const SparseVector<T1,true>& vec, const DenseMatrix<T2,false>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return TSVecDMatMultExpr<T1,T2>( ~vec, ~mat );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector and a
+// dense matrix-matrix multiplication expression (\f$ \vec{y}^T=\vec{x}^T*(A*B) \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side sparse vector for the multiplication.
+// \param mat The right-hand side dense matrix-matrix multiplication.
+// \return The resulting vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a sparse
+// vector and a dense matrix-matrix multiplication expression. It restructures the expression
+// \f$ \vec{y}^T=\vec{x}^T*(A*B) \f$ to the expression \f$ \vec{y}^T=(\vec{x}^T*A)*B \f$.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline const EnableIf_< IsMatMatMultExpr<T2>, MultExprTrait_<T1,T2> >
+ operator*( const SparseVector<T1,true>& vec, const DenseMatrix<T2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( T2 );
+
+ return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct Size< TSVecDMatMultExpr<VT,MT> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct IsAligned< TSVecDMatMultExpr<VT,MT> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, bool AF >
+struct SubvectorExprTrait< TSVecDMatMultExpr<VT,MT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>
+ , SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSVecDVecMultExpr.h b/src/cpu/blaze/math/expressions/TSVecDVecMultExpr.h
new file mode 100644
index 00000000..0826a768
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSVecDVecMultExpr.h
@@ -0,0 +1,142 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSVecDVecMultExpr.h
+// \brief Header file for the sparse vector/dense vector inner product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSVECDVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSVECDVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (inner product) of a sparse and a
+// dense vector (\f$ s=\vec{a}*\vec{b} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the inner product.
+// \param rhs The right-hand side dense vector for the inner product.
+// \return The scalar product.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the scalar product (inner product) of a sparse vector and a dense
+// vector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ blaze::CompressedVector<double,rowVector> a;
+ blaze::DynamicVector<double,columnVector> b;
+ blaze::real res;
+ // ... Resizing and initialization
+ res = a * b;
+ \endcode
+
+// The operator returns a scalar value of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 > // Type of the right-hand side dense vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator*( const SparseVector<T1,true>& lhs, const DenseVector<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef CompositeType_<T1> Lhs; // Composite type of the left-hand side sparse vector expression
+ typedef CompositeType_<T2> Rhs; // Composite type of the right-hand side dense vector expression
+ typedef RemoveReference_<Lhs> X1; // Auxiliary type for the left-hand side composite type
+ typedef RemoveReference_<Rhs> X2; // Auxiliary type for the right-hand side composite type
+ typedef ElementType_<X1> ET1; // Element type of the left-hand side sparse vector expression
+ typedef ElementType_<X2> ET2; // Element type of the right-hand side dense vector expression
+ typedef MultTrait_<ET1,ET2> MultType; // Multiplication result type
+ typedef ConstIterator_<X1> ConstIterator; // Iterator type of the left-hand sparse vector expression
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( T1 );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( T2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( T1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( T2 );
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ Lhs left ( ~lhs );
+ Rhs right( ~rhs );
+
+ ConstIterator element( left.begin() );
+ ConstIterator end ( left.end() );
+
+ MultType sp = MultType();
+
+ if( element != end ) {
+ sp = element->value() * right[ element->index() ];
+ ++element;
+ for( ; element!=end; ++element )
+ sp += element->value() * right[ element->index() ];
+ }
+
+ return sp;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSVecSMatMultExpr.h b/src/cpu/blaze/math/expressions/TSVecSMatMultExpr.h
new file mode 100644
index 00000000..06b87d21
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSVecSMatMultExpr.h
@@ -0,0 +1,927 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSVecSMatMultExpr.h
+// \brief Header file for the transpose sparse vector/sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSVECSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSVECSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/dense/DynamicVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSVECSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-sparse matrix multiplications.
+// \ingroup sparse_vector_expression
+//
+// The TSVecSMatMultExpr class represents the compile time expression for multiplications
+// between transpose sparse vectors and row-major sparse matrices.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename MT > // Type of the right-hand side sparse matrix
+class TSVecSMatMultExpr : public SparseVector< TSVecSMatMultExpr<VT,MT>, true >
+ , private TVecMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateVector || evaluateMatrix ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSVecSMatMultExpr<VT,MT> This; //!< Type of this TSVecSMatMultExpr instance.
+ typedef MultTrait_<VRT,MRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Type for the assignment of the right-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSVecSMatMultExpr class.
+ //
+ // \param vec The left-hand side sparse vector operand of the multiplication expression.
+ // \param mat The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline TSVecSMatMultExpr( const VT& vec, const MT& mat ) noexcept
+ : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
+ , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return vec_[index] * mat_(index,index);
+ }
+ else if( IsLower<MT>::value )
+ {
+ const size_t begin( IsStrictlyLower<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.rows() - begin );
+ return subvector( vec_, begin, n ) * subvector( column( mat_, index ), begin, n );
+ }
+ else if( IsUpper<MT>::value )
+ {
+ const size_t n( IsStrictlyUpper<MT>::value ? index : index+1UL );
+ return subvector( vec_, 0UL, n ) * subvector( column( mat_, index ), 0UL, n );
+ }
+ else
+ {
+ return vec_ * column( mat_, index );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns an estimation for the number of non-zero elements in the sparse vector.
+ //
+ // \return The estimate for the number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side sparse matrix operand.
+ //
+ // \return The right-hand side sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_TSVECSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vec_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand mat_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse vector-sparse matrix multiplication to a dense
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the assignment of a transpose sparse vector-sparse matrix
+ // multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Resetting the left-hand side target dense vector
+ reset( ~lhs );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ TSVecSMatMultExpr::selectAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose sparse vector-sparse matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default assignment kernel for the transpose sparse vector-
+ // sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+
+ const VectorIterator vend( x.end() );
+ VectorIterator velem( x.begin() );
+
+ for( ; velem!=vend; ++velem )
+ {
+ const MatrixIterator mend( A.end( velem->index() ) );
+ MatrixIterator melem( A.begin( velem->index() ) );
+
+ for( ; melem!=mend; ++melem ) {
+ if( IsResizable< ElementType_<VT1> >::value &&
+ isDefault( y[melem->index()] ) )
+ y[melem->index()] = velem->value() * melem->value();
+ else
+ y[melem->index()] += velem->value() * melem->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse vector-sparse matrix multiplication to a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse vector-
+ // sparse matrix multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const DynamicVector<ElementType_<VT1>,true> tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse vector-sparse matrix multiplication to
+ // a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse vector-sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ TSVecSMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose sparse vector-sparse matrix multiplication
+ // (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose sparse
+ // vector-sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+
+ const VectorIterator vend( x.end() );
+ VectorIterator velem( x.begin() );
+
+ for( ; velem!=vend; ++velem )
+ {
+ const MatrixIterator mend( A.end( velem->index() ) );
+ MatrixIterator melem( A.begin( velem->index() ) );
+
+ for( ; melem!=mend; ++melem ) {
+ y[melem->index()] += velem->value() * melem->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse vector-sparse matrix multiplication to
+ // a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse vector-sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ TSVecSMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose sparse vector-sparse matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose sparse
+ // vector-sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+
+ const VectorIterator vend( x.end() );
+ VectorIterator velem( x.begin() );
+
+ for( ; velem!=vend; ++velem )
+ {
+ const MatrixIterator mend( A.end( velem->index() ) );
+ MatrixIterator melem( A.begin( velem->index() ) );
+
+ for( ; melem!=mend; ++melem ) {
+ y[melem->index()] -= velem->value() * melem->value();
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a transpose sparse vector-sparse matrix multiplication
+ // to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // sparse vector-sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse vector-sparse matrix multiplication to a dense
+ // vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the SMP assignment of a transpose sparse vector-sparse matrix
+ // multiplication expression to a dense vector. Due to the explicit application of the SFINAE
+ // principle, this function can only be selected by the compiler in case the expression
+ // specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Resetting the left-hand side target dense vector
+ reset( ~lhs );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ smpAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse vector-sparse matrix multiplication to
+ // a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse vector-sparse matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ smpAddAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse vector-sparse matrix multiplication
+ // to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse vector-sparse matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler in
+ // case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ smpSubAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a transpose sparse vector-sparse matrix
+ // multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose sparse vector-sparse matrix multiplication expression to a dense vector. Due
+ // to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR( VT, MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector and a
+// row-major sparse matrix (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side transpose sparse vector for the multiplication.
+// \param mat The right-hand side row-major sparse matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator represents the multiplication between a transpose sparse vector and a row-major
+// sparse matrix:
+
+ \code
+ using blaze::rowVector;
+ using blaze::rowMajor;
+
+ blaze::CompressedVector<double,rowVector> x, y;
+ blaze::CompressedMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ y = x * A;
+ \endcode
+
+// The operator returns an expression representing a transpose sparse vector of the higher-order
+// element type of the two involved element types \a T1::ElementType and \a T2::ElementType.
+// Both the sparse vector type \a T1 and the sparse matrix type \a T2 as well as the two element
+// types \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of rows of
+// the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const DisableIf_< IsMatMatMultExpr<T2>, TSVecSMatMultExpr<T1,T2> >
+ operator*( const SparseVector<T1,true>& vec, const SparseMatrix<T2,false>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return TSVecSMatMultExpr<T1,T2>( ~vec, ~mat );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector and a
+// sparse matrix-matrix multiplication expression (\f$ \vec{y}^T=\vec{x}^T*(A*B) \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side sparse vector for the multiplication.
+// \param mat The right-hand side sparse matrix-matrix multiplication.
+// \return The resulting vector.
+//
+// This operator implements a performance optimized treatment of the multiplication of a sparse
+// vector and a sparse matrix-matrix multiplication expression. It restructures the expression
+// \f$ \vec{y}^T=\vec{x}^T*(A*B) \f$ to the expression \f$ \vec{y}^T=(\vec{x}^T*A)*B \f$.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline const EnableIf_< IsMatMatMultExpr<T2>, MultExprTrait_<T1,T2> >
+ operator*( const SparseVector<T1,true>& vec, const SparseMatrix<T2,SO>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( T2 );
+
+ return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct Size< TSVecSMatMultExpr<VT,MT> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, bool AF >
+struct SubvectorExprTrait< TSVecSMatMultExpr<VT,MT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>
+ , SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSVecSVecMultExpr.h b/src/cpu/blaze/math/expressions/TSVecSVecMultExpr.h
new file mode 100644
index 00000000..311ef031
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSVecSVecMultExpr.h
@@ -0,0 +1,215 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSVecSVecMultExpr.h
+// \brief Header file for the sparse vector/sparse vector inner product expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSVECSVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSVECSVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsOpposedView.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the scalar product (inner product) of two sparse vectors
+// (\f$ s=\vec{a}*\vec{b} \f$).
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the inner product.
+// \param rhs The right-hand side sparse vector for the inner product.
+// \return The scalar product.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// This operator represents the scalar product (inner product) of two sparse vectors:
+
+ \code
+ using blaze::columnVector;
+
+ blaze::CompressedVector<double,columnVector> a, b;
+ blaze::real res;
+ // ... Resizing and initialization
+ res = trans(a) * b;
+ \endcode
+
+// The operator returns a scalar value of the higher-order element type of the two involved
+// vector element types \a T1::ElementType and \a T2::ElementType. Both vector types \a T1
+// and \a T2 as well as the two element types \a T1::ElementType and \a T2::ElementType have
+// to be supported by the MultTrait class template.\n
+// In case the current sizes of the two given vectors don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 > // Type of the right-hand side sparse vector
+inline const MultTrait_< ElementType_<T1>, ElementType_<T2> >
+ operator*( const SparseVector<T1,true>& lhs, const SparseVector<T2,false>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef CompositeType_<T1> Lhs; // Composite type of the left-hand side sparse vector expression
+ typedef CompositeType_<T2> Rhs; // Composite type of the right-hand side sparse vector expression
+ typedef RemoveReference_<Lhs> X1; // Auxiliary type for the left-hand side composite type
+ typedef RemoveReference_<Rhs> X2; // Auxiliary type for the right-hand side composite type
+ typedef ElementType_<X1> E1; // Element type of the left-hand side sparse vector expression
+ typedef ElementType_<X2> E2; // Element type of the right-hand side sparse vector expression
+ typedef MultTrait_<E1,E2> MultType; // Multiplication result type
+ typedef ConstIterator_<X1> LeftIterator; // Iterator type of the left-hand sparse vector expression
+ typedef ConstIterator_<X2> RightIterator; // Iterator type of the right-hand sparse vector expression
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( T1 );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( T2 );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( T1 );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE( T2 );
+
+ if( (~lhs).size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ Lhs left ( ~lhs ); // Evaluation of the left-hand side sparse vector operand
+ Rhs right( ~rhs ); // Evaluation of the right-hand side sparse vector operand
+
+ BLAZE_INTERNAL_ASSERT( left.size() == (~lhs).size(), "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( right.size() == (~rhs).size(), "Invalid vector size" );
+
+ MultType sp{};
+
+ if( IsOpposedView<T1>::value && IsOpposedView<T2>::value )
+ {
+ if( left.size() == 0UL ) return sp;
+
+ sp = left[0UL] * right[0UL];
+ for( size_t i=1UL; i<left.size(); ++i ) {
+ sp += left[i] * right[i];
+ }
+ }
+ else if( IsOpposedView<T1>::value )
+ {
+ const RightIterator rend( right.end() );
+ RightIterator r( right.begin() );
+
+ if( r == rend ) return sp;
+
+ sp = left[r->index()] * r->value();
+ ++r;
+ for( ; r!=rend; ++r ) {
+ sp += left[r->index()] * r->value();
+ }
+ }
+ else if( IsOpposedView<T2>::value )
+ {
+ const LeftIterator lend( left.end() );
+ LeftIterator l( left.begin() );
+
+ if( l == lend ) return sp;
+
+ sp = l->value() * right[l->index()];
+ ++l;
+ for( ; l!=lend; ++l ) {
+ sp += l->value() * right[l->index()];
+ }
+ }
+ else
+ {
+ const LeftIterator lend( left.end() );
+ const RightIterator rend( right.end() );
+ LeftIterator l( left.begin() );
+ RightIterator r( right.begin() );
+
+ if( l == lend || r == rend ) return sp;
+
+ while( true ) {
+ if( l->index() < r->index() ) {
+ ++l;
+ if( l == lend ) break;
+ }
+ else if( r->index() < l->index() ) {
+ ++r;
+ if( r == rend ) break;
+ }
+ else {
+ sp = l->value() * r->value();
+ ++l;
+ ++r;
+ break;
+ }
+ }
+
+ if( l != lend && r != rend )
+ {
+ while( true ) {
+ if( l->index() < r->index() ) {
+ ++l;
+ if( l == lend ) break;
+ }
+ else if( r->index() < l->index() ) {
+ ++r;
+ if( r == rend ) break;
+ }
+ else {
+ sp += l->value() * r->value();
+ ++l;
+ if( l == lend ) break;
+ ++r;
+ if( r == rend ) break;
+ }
+ }
+ }
+ }
+
+ return sp;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSVecTDMatMultExpr.h b/src/cpu/blaze/math/expressions/TSVecTDMatMultExpr.h
new file mode 100644
index 00000000..4136571f
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSVecTDMatMultExpr.h
@@ -0,0 +1,981 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSVecTDMatMultExpr.h
+// \brief Header file for the transpose sparse vector/transpose dense matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSVECTDMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSVECTDMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSVECDMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for transpose sparse vector-transpose dense matrix multiplications.
+// \ingroup dense_vector_expression
+//
+// The TSVecTDMatMultExpr class represents the compile time expression for multiplications
+// between transpose sparse vectors and column-major dense matrices.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename MT > // Type of the right-hand side dense matrix
+class TSVecTDMatMultExpr : public DenseVector< TSVecTDMatMultExpr<VT,MT>, true >
+ , private TVecMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side dense matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side dense matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side dense matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the evaluation strategy of the multiplication expression.
+ /*! The \a useAssign compile time constant expression represents a compilation switch for
+ the evaluation strategy of the multiplication expression. In case either the vector or
+ the matrix operand requires an intermediate evaluation or the sparse vector expression
+ is a compound expression, \a useAssign will be set to \a true and the multiplication
+ expression will be evaluated via the \a assign function family. Otherwise \a useAssign
+ will be set to \a false and the expression will be evaluated via the subscript operator. */
+ enum : bool { useAssign = ( evaluateVector || evaluateMatrix ) };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct UseAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the vector or the matrix operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = useAssign };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSVecTDMatMultExpr<VT,MT> This; //!< Type of this TSVecTDMatMultExpr instance.
+ typedef MultTrait_<VRT,MRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+
+ //! Data type for composite expression templates.
+ typedef IfTrue_< useAssign, const ResultType, const TSVecTDMatMultExpr& > CompositeType;
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Type for the assignment of the left-hand side dense matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSVecTDMatMultExpr class.
+ //
+ // \param vec The left-hand side sparse vector operand of the multiplication expression.
+ // \param mat The right-hand side dense matrix operand of the multiplication expression.
+ */
+ explicit inline TSVecTDMatMultExpr( const VT& vec, const MT& mat ) noexcept
+ : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
+ , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
+
+ if( IsDiagonal<MT>::value )
+ {
+ return vec_[index] * mat_(index,index);
+ }
+ else if( IsLower<MT>::value )
+ {
+ const size_t begin( IsStrictlyLower<MT>::value ? index+1UL : index );
+ const size_t n ( mat_.rows() - begin );
+ return subvector( vec_, begin, n ) * subvector( column( mat_, index ), begin, n );
+ }
+ else if( IsUpper<MT>::value )
+ {
+ const size_t n( IsStrictlyUpper<MT>::value ? index : index+1UL );
+ return subvector( vec_, 0UL, n ) * subvector( column( mat_, index ), 0UL, n );
+ }
+ else
+ {
+ return vec_ * column( mat_, index );
+ }
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose dense matrix operand.
+ //
+ // \return The right-hand side transpose dense matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return vec_.isAliased( alias ) || mat_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vec_.isAliased( alias ) || mat_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the operands of the expression are properly aligned in memory.
+ //
+ // \return \a true in case the operands are aligned, \a false if not.
+ */
+ inline bool isAligned() const noexcept {
+ return mat_.isAligned();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_TSVECTDMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vec_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand mat_; //!< Right-hand side dense matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse vector-transpose dense matrix multiplication to
+ // a dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse vector-
+ // transpose dense matrix multiplication expression to a dense vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either the left-hand side matrix operand requires an intermediate evaluation or
+ // the right-hand side vector operand is a compound expression.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ assign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse vector-transpose dense matrix multiplication to
+ // a sparse vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse vector-
+ // transpose dense matrix multiplication expression to a sparse vector. Due to the explicit
+ // application of the SFINAE principle, this function can only be selected by the compiler
+ // in case either the left-hand side matrix operand requires an intermediate evaluation or
+ // the right-hand side vector operand is a compound expression.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ assign( SparseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ assign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*!\brief Addition assignment of a transpose sparse vector-transpose dense matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose
+ // sparse vector-transpose dense matrix multiplication expression to a dense vector. Due
+ // to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case either the left-hand side matrix operand requires an intermediate
+ // evaluation or the right-hand side vector operand is a compound expression.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ addAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ addAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*!\brief Subtraction assignment of a transpose sparse vector-transpose dense matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse vector-transpose dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either the left-hand side matrix operand requires an intermediate
+ // evaluation or the right-hand side vector operand is a compound expression.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ subAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ subAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*!\brief Multiplication assignment of a transpose sparse vector-transpose dense matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // sparse vector-transpose dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either the left-hand side matrix operand requires an intermediate
+ // evaluation or the right-hand side vector operand is a compound expression.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ multAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Division assignment to dense vectors********************************************************
+ /*!\brief Division assignment of a transpose sparse vector-transpose dense matrix multiplication
+ // to a dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized division assignment of a transpose
+ // sparse vector-transpose dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case either the left-hand side matrix operand requires an intermediate
+ // evaluation or the right-hand side vector operand is a compound expression.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseAssign<VT2> >
+ divAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ divAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**Division assignment to sparse vectors*******************************************************
+ // No special implementation for the division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse vector-transpose dense matrix multiplication to
+ // a dense vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // vector-transpose dense matrix multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) {
+ reset( ~lhs );
+ return;
+ }
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ smpAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse vector-transpose dense matrix multiplication to
+ // a sparse vector (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // vector-transpose dense matrix multiplication expression to a sparse vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target sparse vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAssign( SparseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*!\brief SMP addition assignment of a transpose sparse vector-transpose dense matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse vector-transpose dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpAddAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ smpAddAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*!\brief SMP subtraction assignment of a transpose sparse vector-transpose dense matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a
+ // transpose sparse vector-transpose dense matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpSubAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side dense matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-dense matrix multiplication
+ smpSubAssign( ~lhs, x * A );
+ }
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*!\brief SMP multiplication assignment of a transpose sparse vector-transpose dense matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T*=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose sparse vector-transpose dense matrix multiplication expression to a dense
+ // vector. Due to the explicit application of the SFINAE principle, this function can only
+ // be selected by the compiler in case the expression specific parallel evaluation strategy
+ // is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpMultAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP division assignment to dense vectors****************************************************
+ /*!\brief SMP division assignment of a transpose sparse vector-transpose dense matrix
+ // multiplication to a dense vector (\f$ \vec{y}^T/=\vec{x}^T*A \f$).
+ // \ingroup dense_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression divisor.
+ // \return void
+ //
+ // This function implements the performance optimized SMP division assignment of a transpose
+ // sparse vector-transpose dense matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT2 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT2> >
+ smpDivAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpDivAssign( ~lhs, tmp );
+ }
+ //**********************************************************************************************
+
+ //**SMP division assignment to sparse vectors***************************************************
+ // No special implementation for the SMP division assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR( VT, MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector and a
+// column-major dense matrix (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side transpose sparse vector for the multiplication.
+// \param mat The right-hand side column-major dense matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator represents the multiplication between a transpose sparse vector and a column-major
+// dense matrix:
+
+ \code
+ using blaze::rowVector;
+ using blaze::columnMajor;
+
+ blaze::CompressedVector<double,rowVector> x, y;
+ blaze::DynamicMatrix<double,columnMajor> A;
+ // ... Resizing and initialization
+ y = x * A;
+ \endcode
+
+// The operator returns an expression representing a transpose sparse vector of the higher-order
+// element type of the two involved element types \a T1::ElementType and \a T2::ElementType.
+// Both the dense matrix type \a T1 and the dense vector type \a T2 as well as the two element
+// types \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of rows of
+// the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1, typename T2 >
+inline const DisableIf_< Or< IsSymmetric<T2>, IsMatMatMultExpr<T2> >, TSVecTDMatMultExpr<T1,T2> >
+ operator*( const SparseVector<T1,true>& vec, const DenseMatrix<T2,true>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return TSVecTDMatMultExpr<T1,T2>( ~vec, ~mat );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector and a
+// symmetric column-major dense matrix (\f$ \vec{a}=B*\vec{c} \f$).
+// \ingroup dense_vector
+//
+// \param vec The left-hand side transpose sparse vector for the multiplication.
+// \param mat The right-hand side column-major dense matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// transpose sparse vector and a symmetric column-major dense matrix. It restructures the
+// expression \f$ \vec{y}^T=\vec{x}^T*A^T \f$ to the expression \f$ \vec{y}^T=\vec{x}^T*A \f$.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 > // Type of the right-hand side dense matrix
+inline const EnableIf_< IsSymmetric<T2>, MultExprTrait_<T1,T2> >
+ operator*( const SparseVector<T1,true>& vec, const DenseMatrix<T2,true>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATMULTEXPR_TYPE( T2 );
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return (~vec) * trans( ~mat );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct Size< TSVecTDMatMultExpr<VT,MT> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct IsAligned< TSVecTDMatMultExpr<VT,MT> >
+ : public BoolConstant< IsAligned<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, bool AF >
+struct SubvectorExprTrait< TSVecTDMatMultExpr<VT,MT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>
+ , SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TSVecTSMatMultExpr.h b/src/cpu/blaze/math/expressions/TSVecTSMatMultExpr.h
new file mode 100644
index 00000000..d72cd20b
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TSVecTSMatMultExpr.h
@@ -0,0 +1,1052 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TSVecTSMatMultExpr.h
+// \brief Header file for the transpose sparse vector/transpose sparse matrix multiplication expression
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TSVECTSMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TSVECTSMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/MatMatMultExpr.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/TVecMatMultExpr.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/Columns.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/typetraits/Size.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TSVECTSMATMULTEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for sparse vector-sparse matrix multiplications.
+// \ingroup sparse_vector_expression
+//
+// The TSVecTSMatMultExpr class represents the compile time expression for multiplications
+// between transpose sparse vectors and column-major sparse matrices.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename MT > // Type of the right-hand side sparse matrix
+class TSVecTSMatMultExpr : public SparseVector< TSVecTSMatMultExpr<VT,MT>, true >
+ , private TVecMatMultExpr
+ , private Computation
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> VRT; //!< Result type of the left-hand side sparse vector expression.
+ typedef ResultType_<MT> MRT; //!< Result type of the right-hand side sparse matrix expression.
+ typedef CompositeType_<VT> VCT; //!< Composite type of the left-hand side sparse vector expression.
+ typedef CompositeType_<MT> MCT; //!< Composite type of the right-hand side sparse matrix expression.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the left-hand side sparse vector expression.
+ enum : bool { evaluateVector = IsComputation<VT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Compilation switch for the composite type of the right-hand side sparse matrix expression.
+ enum : bool { evaluateMatrix = RequiresEvaluation<MT>::value };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ //! Helper structure for the explicit application of the SFINAE principle.
+ /*! The UseSMPAssign struct is a helper struct for the selection of the parallel evaluation
+ strategy. In case either the matrix or the vector operand requires an intermediate
+ evaluation, the nested \value will be set to 1, otherwise it will be 0. */
+ template< typename T1 >
+ struct UseSMPAssign {
+ enum : bool { value = ( evaluateVector || evaluateMatrix ) };
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TSVecTSMatMultExpr<VT,MT> This; //!< Type of this TSVecTSMatMultExpr instance.
+ typedef MultTrait_<VRT,MRT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<ResultType> ElementType; //!< Resulting element type.
+ typedef const ElementType ReturnType; //!< Return type for expression template evaluations.
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+
+ //! Composite type of the left-hand side sparse vector expression.
+ typedef If_< IsExpression<VT>, const VT, const VT& > LeftOperand;
+
+ //! Composite type of the right-hand side sparse matrix expression.
+ typedef If_< IsExpression<MT>, const MT, const MT& > RightOperand;
+
+ //! Type for the assignment of the left-hand side sparse vector operand.
+ typedef IfTrue_< evaluateVector, const VRT, VCT > LT;
+
+ //! Type for the assignment of the right-hand side sparse matrix operand.
+ typedef IfTrue_< evaluateMatrix, const MRT, MCT > RT;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = !evaluateVector && VT::smpAssignable &&
+ !evaluateMatrix && MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the TSVecTSMatMultExpr class.
+ //
+ // \param vec The left-hand side sparse vector operand of the multiplication expression.
+ // \param mat The right-hand side sparse matrix operand of the multiplication expression.
+ */
+ explicit inline TSVecTSMatMultExpr( const VT& vec, const MT& mat ) noexcept
+ : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
+ , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
+ {
+ BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
+ }
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
+ return vec_ * column( mat_, index );
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= mat_.columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**NonZeros function***************************************************************************
+ /*!\brief Returns an estimation for the number of non-zero elements in the sparse vector.
+ //
+ // \return The estimate for the number of non-zero elements in the sparse vector.
+ */
+ inline size_t nonZeros() const {
+ return mat_.columns();
+ }
+ //**********************************************************************************************
+
+ //**Left operand access*************************************************************************
+ /*!\brief Returns the left-hand side sparse vector operand.
+ //
+ // \return The left-hand side sparse vector operand.
+ */
+ inline LeftOperand leftOperand() const noexcept {
+ return vec_;
+ }
+ //**********************************************************************************************
+
+ //**Right operand access************************************************************************
+ /*!\brief Returns the right-hand side transpose sparse matrix operand.
+ //
+ // \return The right-hand side transpose sparse matrix operand.
+ */
+ inline RightOperand rightOperand() const noexcept {
+ return mat_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can be used in SMP assignments.
+ //
+ // \return \a true in case the expression can be used in SMP assignments, \a false if not.
+ */
+ inline bool canSMPAssign() const noexcept {
+ return ( size() > SMP_TSVECSMATMULT_THRESHOLD );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ LeftOperand vec_; //!< Left-hand side sparse vector of the multiplication expression.
+ RightOperand mat_; //!< Right-hand side sparse matrix of the multiplication expression.
+ //**********************************************************************************************
+
+ //**Assignment to dense vectors*****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse vector-transpose sparse matrix multiplication to
+ // a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse vector-
+ // transpose sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void assign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Resetting the left-hand side target dense vector
+ reset( ~lhs );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ TSVecTSMatMultExpr::selectAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default assignment to dense vectors*********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default assignment of a transpose sparse vector-transpose sparse matrix multiplication
+ // (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the serial assignment kernel for the transpose sparse vector-
+ // transpose sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+
+ const VectorIterator vend( x.end() );
+
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ const MatrixIterator mend ( A.end(j) );
+ MatrixIterator melem( A.begin(j) );
+
+ if( melem == mend ) continue;
+
+ VectorIterator velem( x.begin() );
+
+ while( true ) {
+ if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else {
+ y[j] = velem->value() * melem->value();
+ ++velem;
+ ++melem;
+ break;
+ }
+ }
+
+ if( velem != vend && melem != mend )
+ {
+ while( true ) {
+ if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else {
+ y[j] += velem->value() * melem->value();
+ ++velem;
+ if( velem == vend ) break;
+ ++melem;
+ if( melem == mend ) break;
+ }
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Assignment to sparse vectors****************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Assignment of a transpose sparse vector-transpose sparse matrix multiplication to
+ // a sparse vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side sparse vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized assignment of a transpose sparse vector-
+ // transpose sparse matrix multiplication expression to a sparse vector.
+ */
+ template< typename VT1 > // Type of the target sparse vector
+ friend inline void assign( SparseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ typedef ConstIterator_< RemoveReference_<LT> > VectorIterator;
+ typedef ConstIterator_< RemoveReference_<RT> > MatrixIterator;
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ ElementType accu;
+ const VectorIterator vend( x.end() );
+
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ const MatrixIterator mend ( A.end(j) );
+ MatrixIterator melem( A.begin(j) );
+
+ if( melem == mend ) continue;
+
+ VectorIterator velem( x.begin() );
+
+ reset( accu );
+
+ while( true ) {
+ if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else {
+ accu = velem->value() * melem->value();
+ ++velem;
+ ++melem;
+ break;
+ }
+ }
+
+ if( velem != vend && melem != mend )
+ {
+ while( true ) {
+ if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else {
+ accu += velem->value() * melem->value();
+ ++velem;
+ if( velem == vend ) break;
+ ++melem;
+ if( melem == mend ) break;
+ }
+ }
+ }
+
+ if( !isDefault( accu ) )
+ (~lhs).insert( j, accu );
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to dense vectors********************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Addition assignment of a transpose sparse vector-transpose sparse matrix multiplication
+ // to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized addition assignment of a transpose sparse
+ // vector-transpose sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void addAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ TSVecTSMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default addition assignment to dense vectors************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default addition assignment of a transpose sparse vector-transpose sparse matrix
+ // multiplication (\f$ \vec{y}^T+=\vec{x}^T*A \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default addition assignment kernel for the transpose sparse
+ // vector-transpose sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+
+ const VectorIterator vend( x.end() );
+
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ const MatrixIterator mend ( A.end(j) );
+ MatrixIterator melem( A.begin(j) );
+
+ if( melem == mend ) continue;
+
+ VectorIterator velem( x.begin() );
+
+ while( true ) {
+ if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else {
+ y[j] += velem->value() * melem->value();
+ ++velem;
+ if( velem == vend ) break;
+ ++melem;
+ if( melem == mend ) break;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Addition assignment to sparse vectors*******************************************************
+ // No special implementation for the addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Subtraction assignment to dense vectors*****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Subtraction assignment of a transpose sparse vector-transpose sparse matrix
+ // multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized subtraction assignment of a transpose
+ // sparse vector-transpose sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void subAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( serial( rhs.vec_ ) );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( serial( rhs.mat_ ) );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ TSVecTSMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Default subtraction assignment to dense vectors*********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Default subtraction assignment of a transpose sparse vector-transpose sparse matrix
+ // multiplication (\f$ \vec{y}^T-=\vec{x}^T*A \f$).
+ // \ingroup sparse_vector
+ //
+ // \param y The target left-hand side dense vector.
+ // \param x The left-hand side sparse vector operand.
+ // \param A The right-hand side sparse matrix operand.
+ // \return void
+ //
+ // This function implements the default subtraction assignment kernel for the transpose sparse
+ // vector-transpose sparse matrix multiplication.
+ */
+ template< typename VT1 // Type of the left-hand side target vector
+ , typename VT2 // Type of the left-hand side vector operand
+ , typename MT1 > // Type of the right-hand side matrix operand
+ static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
+ {
+ typedef ConstIterator_< RemoveReference_<VT2> > VectorIterator;
+ typedef ConstIterator_< RemoveReference_<MT1> > MatrixIterator;
+
+ const VectorIterator vend( x.end() );
+
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ const MatrixIterator mend ( A.end(j) );
+ MatrixIterator melem( A.begin(j) );
+
+ if( melem == mend ) continue;
+
+ VectorIterator velem( x.begin() );
+
+ while( true ) {
+ if( velem->index() < melem->index() ) {
+ ++velem;
+ if( velem == vend ) break;
+ }
+ else if( melem->index() < velem->index() ) {
+ ++melem;
+ if( melem == mend ) break;
+ }
+ else {
+ y[j] -= velem->value() * melem->value();
+ ++velem;
+ if( velem == vend ) break;
+ ++melem;
+ if( melem == mend ) break;
+ }
+ }
+ }
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Subtraction assignment to sparse vectors****************************************************
+ // No special implementation for the subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Multiplication assignment to dense vectors**************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Multiplication assignment of a transpose sparse vector-transpose sparse matrix
+ // multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized multiplication assignment of a transpose
+ // sparse vector-transpose sparse matrix multiplication expression to a dense vector.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline void multAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( rhs ) );
+ multAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Multiplication assignment to sparse vectors*************************************************
+ // No special implementation for the multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP assignment to dense vectors*************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP assignment of a transpose sparse vector-transpose sparse matrix multiplication
+ // to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be assigned.
+ // \return void
+ //
+ // This function implements the performance optimized SMP assignment of a transpose sparse
+ // vector-transpose sparse matrix multiplication expression to a dense vector. Due to the
+ // explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Resetting the left-hand side target dense vector
+ reset( ~lhs );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse vector-sparse matrix multiplication
+ smpAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP assignment to sparse vectors************************************************************
+ // No special implementation for the SMP assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP addition assignment to dense vectors****************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP addition assignment of a transpose sparse vector-transpose sparse matrix
+ // multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be added.
+ // \return void
+ //
+ // This function implements the performance optimized SMP addition assignment of a transpose
+ // sparse vector-transpose sparse matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by
+ // the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpAddAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ smpAddAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP addition assignment to sparse vectors***************************************************
+ // No special implementation for the SMP addition assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to dense vectors*************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP subtraction assignment of a transpose sparse vector-transpose sparse matrix
+ // multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be subtracted.
+ // \return void
+ //
+ // This function implements the performance optimized SMP subtraction assignment of a transpose
+ // sparse vector-transpose sparse matrix multiplication expression to a dense vector. Due to
+ // the explicit application of the SFINAE principle, this function can only be selected by the
+ // compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpSubAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ // Evaluation of the left-hand side sparse vector operand
+ LT x( rhs.vec_ );
+ if( x.nonZeros() == 0UL ) return;
+
+ // Evaluation of the right-hand side sparse matrix operand
+ RT A( rhs.mat_ );
+
+ // Checking the evaluated operands
+ BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
+ BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
+
+ // Performing the sparse matrix-sparse vector multiplication
+ smpSubAssign( ~lhs, x * A );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP subtraction assignment to sparse vectors************************************************
+ // No special implementation for the SMP subtraction assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to dense vectors**********************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief SMP multiplication assignment of a transpose sparse vector-transpose sparse matrix
+ // multiplication to a dense vector.
+ // \ingroup sparse_vector
+ //
+ // \param lhs The target left-hand side dense vector.
+ // \param rhs The right-hand side multiplication expression to be multiplied.
+ // \return void
+ //
+ // This function implements the performance optimized SMP multiplication assignment of a
+ // transpose sparse vector-transpose sparse matrix multiplication expression to a dense vector.
+ // Due to the explicit application of the SFINAE principle, this function can only be selected
+ // by the compiler in case the expression specific parallel evaluation strategy is selected.
+ */
+ template< typename VT1 > // Type of the target dense vector
+ friend inline EnableIf_< UseSMPAssign<VT1> >
+ smpMultAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<ResultType> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
+
+ const ResultType tmp( rhs );
+ smpMultAssign( ~lhs, tmp );
+ }
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**SMP multiplication assignment to sparse vectors*********************************************
+ // No special implementation for the SMP multiplication assignment to sparse vectors.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR( VT, MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector and a
+// column-major sparse matrix (\f$ \vec{y}^T=\vec{x}^T*A \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side transpose sparse vector for the multiplication.
+// \param mat The right-hand side column-major sparse matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator represents the multiplication between a transpose sparse vector and a column-major
+// sparse matrix:
+
+ \code
+ using blaze::rowVector;
+ using blaze::columnMajor;
+
+ blaze::CompressedVector<double,rowVector> x, y;
+ blaze::CompressedMatrix<double,columnMajor> A;
+ // ... Resizing and initialization
+ y = x * A;
+ \endcode
+
+// The operator returns an expression representing a transpose sparse vector of the higher-order
+// element type of the two involved element types \a T1::ElementType and \a T2::ElementType.
+// Both the sparse vector type \a T1 and the sparse matrix type \a T2 as well as the two element
+// types \a T1::ElementType and \a T2::ElementType have to be supported by the MultTrait class
+// template.\n
+// In case the current size of the vector \a vec doesn't match the current number of rows of
+// the matrix \a mat, a \a std::invalid_argument is thrown.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const DisableIf_< Or< IsSymmetric<T2>, IsMatMatMultExpr<T2> >, TSVecTSMatMultExpr<T1,T2> >
+ operator*( const SparseVector<T1,true>& vec, const SparseMatrix<T2,true>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return TSVecTSMatMultExpr<T1,T2>( ~vec, ~mat );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication operator for the multiplication of a transpose sparse vector and a
+// symmetric column-major sparse matrix (\f$ \vec{a}=B*\vec{c} \f$).
+// \ingroup sparse_vector
+//
+// \param vec The left-hand side transpose sparse vector for the multiplication.
+// \param mat The right-hand side column-major sparse matrix for the multiplication.
+// \return The resulting transpose vector.
+// \exception std::invalid_argument Vector and matrix sizes do not match.
+//
+// This operator implements the performance optimized treatment of the multiplication of a
+// transpose sparse vector and a symmetric column-major sparse matrix. It restructures the
+// expression \f$ \vec{y}^T=\vec{x}^T*A^T \f$ to the expression \f$ \vec{y}^T=\vec{x}^T*A \f$.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline const EnableIf_< IsSymmetric<T2>, MultExprTrait_<T1,T2> >
+ operator*( const SparseVector<T1,true>& vec, const SparseMatrix<T2,true>& mat )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATMULTEXPR_TYPE( T2 );
+
+ if( (~vec).size() != (~mat).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" );
+ }
+
+ return (~vec) * trans( ~mat );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT >
+struct Size< TSVecTSMatMultExpr<VT,MT> > : public Columns<MT>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, typename MT, bool AF >
+struct SubvectorExprTrait< TSVecTSMatMultExpr<VT,MT>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = MultExprTrait_< SubvectorExprTrait_<const VT,AF>
+ , SubmatrixExprTrait_<const MT,AF> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TVecMatMultExpr.h b/src/cpu/blaze/math/expressions/TVecMatMultExpr.h
new file mode 100644
index 00000000..365fbfb7
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TVecMatMultExpr.h
@@ -0,0 +1,72 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TVecMatMultExpr.h
+// \brief Header file for the TVecMatMultExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TVECMATMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TVECMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector/matrix multiplication expression templates.
+// \ingroup math
+//
+// The TVecMatMultExpr class serves as a tag for all expression templates that implement a
+// vector/matrix multiplication. All classes, that represent a vector/matrix multiplication
+// and that are used within the expression template environment of the Blaze library have
+// to derive from this class in order to qualify as vector/matrix multiplication expression
+// template. Only in case a class is derived from the TVecMatMultExpr base class, the
+// IsTVecMatMultExpr type trait recognizes the class as valid vector/matrix multiplication
+// expression template.
+*/
+struct TVecMatMultExpr : private MultExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/TransExpr.h b/src/cpu/blaze/math/expressions/TransExpr.h
new file mode 100644
index 00000000..c4e9b8b8
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/TransExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/TransExpr.h
+// \brief Header file for the TransExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_TRANSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_TRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all transposition expression templates.
+// \ingroup math
+//
+// The TransExpr class serves as a tag for all expression templates that implement mathematical
+// transpositions. All classes, that represent a mathematical transposition (vector transpositions
+// and matrix transpositions) and that are used within the expression template environment of the
+// Blaze library have to derive from this class in order to qualify as transposition expression
+// template. Only in case a class is derived from the TransExpr base class, the IsTransExpr type
+// trait recognizes the class as valid transposition expression template.
+*/
+struct TransExpr : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecEvalExpr.h b/src/cpu/blaze/math/expressions/VecEvalExpr.h
new file mode 100644
index 00000000..d435f27c
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecEvalExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecEvalExpr.h
+// \brief Header file for the VecEvalExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECEVALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/EvalExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector evaluation expression templates.
+// \ingroup math
+//
+// The VecEvalExpr class serves as a tag for all expression templates that implement a vector
+// evaluation operation. All classes, that represent a vector evaluation operation and that
+// are used within the expression template environment of the Blaze library have to derive
+// from this class in order to qualify as vector evaluation expression template. Only in case
+// a class is derived from the VecEvalExpr base class, the IsVecEvalExpr type trait recognizes
+// the class as valid vector evaluation expression template.
+*/
+struct VecEvalExpr : private EvalExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecForEachExpr.h b/src/cpu/blaze/math/expressions/VecForEachExpr.h
new file mode 100644
index 00000000..023997ab
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecForEachExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecForEachExpr.h
+// \brief Header file for the VecForEachExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECFOREACHEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/ForEachExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector for-each expression templates.
+// \ingroup math
+//
+// The VecForEachExpr class serves as a tag for all expression templates that represent a unary,
+// custom operation on a vector. All classes, that represent a vector custom operation and that
+// are used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as vector for-each expression template. Only in case a class
+// is derived from the VecForEachExpr base class, the IsVecForEachExpr type trait recognizes the
+// class as valid vector for-each expression template.
+*/
+struct VecForEachExpr : private ForEachExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecScalarDivExpr.h b/src/cpu/blaze/math/expressions/VecScalarDivExpr.h
new file mode 100644
index 00000000..b2c7a951
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecScalarDivExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecScalarDivExpr.h
+// \brief Header file for the VecScalarDivExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECSCALARDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DivExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector/scalar division expression templates.
+// \ingroup math
+//
+// The VecScalarDivExpr class serves as a tag for all expression templates that implement a
+// vector/scalar division. All classes, that represent a vector/scalar division and that are
+// used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as vector/scalar division expression template. Only in case
+// a class is derived from the VecScalarDivExpr base class, the IsVecScalarDivExpr type trait
+// recognizes the class as valid vector/scalar division expression template.
+*/
+struct VecScalarDivExpr : private DivExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecScalarMultExpr.h b/src/cpu/blaze/math/expressions/VecScalarMultExpr.h
new file mode 100644
index 00000000..d616de1b
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecScalarMultExpr.h
@@ -0,0 +1,72 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecScalarMultExpr.h
+// \brief Header file for the VecScalarMultExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECSCALARMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector/scalar multiplication expression templates.
+// \ingroup math
+//
+// The VecScalarMultExpr class serves as a tag for all expression templates that implement a
+// vector/scalar multiplication. All classes, that represent a vector/scalar multiplication
+// and that are used within the expression template environment of the Blaze library have
+// to derive from this class in order to qualify as vector/scalar multiplication expression
+// template. Only in case a class is derived from the VecScalarMultExpr base class, the
+// IsVecScalarMultExpr type trait recognizes the class as valid vector/scalar multiplication
+// expression template.
+*/
+struct VecScalarMultExpr : private MultExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecSerialExpr.h b/src/cpu/blaze/math/expressions/VecSerialExpr.h
new file mode 100644
index 00000000..32c77c16
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecSerialExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecSerialExpr.h
+// \brief Header file for the VecSerialExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECSERIALEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SerialExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector serial evaluation expression templates.
+// \ingroup math
+//
+// The VecSerialExpr class serves as a tag for all expression templates that enforce a serial
+// evaluation of a vector. All classes, that represent a vector serialization operation and that
+// are used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as vector serial evaluation expression template. Only in case
+// a class is derived from the VecSerialExpr base class, the IsVecSerialExpr type trait recognizes
+// the class as valid vector serial evaluation expression template.
+*/
+struct VecSerialExpr : private SerialExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecTVecMultExpr.h b/src/cpu/blaze/math/expressions/VecTVecMultExpr.h
new file mode 100644
index 00000000..7e9b7172
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecTVecMultExpr.h
@@ -0,0 +1,72 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecTVecMultExpr.h
+// \brief Header file for the VecTVecMultExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECTVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECTVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all outer product expression templates.
+// \ingroup math
+//
+// The VecTVecMultExpr class serves as a tag for all expression templates that implement
+// mathematical outer products (i.e. multiplications between a column vector and a row vector).
+// All classes, that represent a mathematical outer product and that are used within the
+// expression template environment of the Blaze library have to derive from this class in order
+// to qualify as outer product expression template. Only in case a class is derived from the
+// VecTVecMultExpr base class, the IsVecTVecMultExpr type trait recognizes the class as valid
+// outer product expression template.
+*/
+struct VecTVecMultExpr : private MultExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecTransExpr.h b/src/cpu/blaze/math/expressions/VecTransExpr.h
new file mode 100644
index 00000000..9325f3ec
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecTransExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecTransExpr.h
+// \brief Header file for the VecTransExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECTRANSEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/TransExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector transposition expression templates.
+// \ingroup math
+//
+// The VecTransExpr class serves as a tag for all expression templates that implement a vector
+// transposition operation. All classes, that represent a vector transposition operation and
+// that are used within the expression template environment of the Blaze library have to derive
+// from this class in order to qualify as vector transposition expression template. Only in case
+// a class is derived from the VecTransExpr base class, the IsVecTransExpr type trait recognizes
+// the class as valid vector transposition expression template.
+*/
+struct VecTransExpr : private TransExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecVecAddExpr.h b/src/cpu/blaze/math/expressions/VecVecAddExpr.h
new file mode 100644
index 00000000..ca2f43e0
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecVecAddExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecVecAddExpr.h
+// \brief Header file for the VecVecAddExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECVECADDEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECVECADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/AddExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector/vector addition expression templates.
+// \ingroup math
+//
+// The VecVecAddExpr class serves as a tag for all expression templates that implement a
+// vector/vector addition. All classes, that represent a vector addition and that are used
+// within the expression template environment of the Blaze library have to derive from this
+// class in order to qualify as vector addition expression template. Only in case a class is
+// derived from the VecVecAddExpr base class, the IsVecVecAddExpr type trait recognizes the
+// class as valid vector addition expression template.
+*/
+struct VecVecAddExpr : private AddExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecVecDivExpr.h b/src/cpu/blaze/math/expressions/VecVecDivExpr.h
new file mode 100644
index 00000000..157827ad
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecVecDivExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecVecDivExpr.h
+// \brief Header file for the VecVecDivExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECVECDIVEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECVECDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DivExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector/vector division expression templates.
+// \ingroup math
+//
+// The VecVecDivExpr class serves as a tag for all expression templates that implement a
+// vector/vector division. All classes, that represent a vector division and that are used
+// within the expression template environment of the Blaze library have to derive from this
+// class in order to qualify as vector division expression template. Only in case a class
+// is derived from the VecVecDivExpr base class, the IsVecVecDivExpr type trait recognizes
+// the class as valid vector division expression template.
+*/
+struct VecVecDivExpr : private DivExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecVecMultExpr.h b/src/cpu/blaze/math/expressions/VecVecMultExpr.h
new file mode 100644
index 00000000..156d7047
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecVecMultExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecVecMultExpr.h
+// \brief Header file for the VecVecMultExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECVECMULTEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MultExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector/vector multiplication expression templates.
+// \ingroup math
+//
+// The VecVecMultExpr class serves as a tag for all expression templates that implement a
+// vector/vector multiplication. All classes, that represent a vector multiplication and that are
+// used within the expression template environment of the Blaze library have to derive from this
+// class in order to qualify as vector multiplication expression template. Only in case a class
+// is derived from the VecVecMultExpr base class, the IsVecVecMultExpr type trait recognizes the
+// class as valid vector multiplication expression template.
+*/
+struct VecVecMultExpr : private MultExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/VecVecSubExpr.h b/src/cpu/blaze/math/expressions/VecVecSubExpr.h
new file mode 100644
index 00000000..7d17d1ad
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/VecVecSubExpr.h
@@ -0,0 +1,71 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/VecVecSubExpr.h
+// \brief Header file for the VecVecSubExpr base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECVECSUBEXPR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECVECSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SubExpr.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all vector/vector subtraction expression templates.
+// \ingroup math
+//
+// The VecVecSubExpr class serves as a tag for all expression templates that implement a
+// vector/vector subtraction. All classes, that represent a vector subtraction and that are
+// used within the expression template environment of the Blaze library have to derive from
+// this class in order to qualify as vector subtraction expression template. Only in case a
+// class is derived from the VecVecSubExpr base class, the IsVecVecSubExpr type trait
+// recognizes the class as valid vector subtraction expression template.
+*/
+struct VecVecSubExpr : private SubExpr
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/Vector.h b/src/cpu/blaze/math/expressions/Vector.h
new file mode 100644
index 00000000..8ca532c9
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/Vector.h
@@ -0,0 +1,770 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/Vector.h
+// \brief Header file for the Vector CRTP base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VECTOR_H_
+#define _BLAZE_MATH_EXPRESSIONS_VECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Exception.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup vector Vectors
+// \ingroup math
+*/
+/*!\brief Base class for N-dimensional vectors.
+// \ingroup vector
+//
+// The Vector class is a base class for all arbitrarily sized (N-dimensional) dense and sparse
+// vector classes within the Blaze library. It provides an abstraction from the actual type of
+// the vector, but enables a conversion back to this type via the 'Curiously Recurring Template
+// Pattern' (CRTP).
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag
+struct Vector
+{
+ //**Type definitions****************************************************************************
+ typedef VT VectorType; //!< Type of the vector.
+ //**********************************************************************************************
+
+ //**Non-const conversion operator***************************************************************
+ /*!\brief Conversion operator for non-constant vectors.
+ //
+ // \return Reference of the actual type of the vector.
+ */
+ BLAZE_ALWAYS_INLINE VectorType& operator~() noexcept {
+ return *static_cast<VectorType*>( this );
+ }
+ //**********************************************************************************************
+
+ //**Const conversion operators******************************************************************
+ /*!\brief Conversion operator for constant vectors.
+ //
+ // \return Const reference of the actual type of the vector.
+ */
+ BLAZE_ALWAYS_INLINE const VectorType& operator~() const noexcept {
+ return *static_cast<const VectorType*>( this );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Vector global functions */
+//@{
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE typename VT::Iterator begin( Vector<VT,TF>& vector );
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE typename VT::ConstIterator begin( const Vector<VT,TF>& vector );
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE typename VT::ConstIterator cbegin( const Vector<VT,TF>& vector );
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE typename VT::Iterator end( Vector<VT,TF>& vector );
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE typename VT::ConstIterator end( const Vector<VT,TF>& vector );
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE typename VT::ConstIterator cend( const Vector<VT,TF>& vector );
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE size_t size( const Vector<VT,TF>& vector ) noexcept;
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE size_t capacity( const Vector<VT,TF>& vector ) noexcept;
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const Vector<VT,TF>& vector );
+
+template< typename VT, bool TF >
+BLAZE_ALWAYS_INLINE void resize( Vector<VT,TF>& vector, size_t n, bool preserve=true );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+BLAZE_ALWAYS_INLINE bool isSame( const Vector<VT1,TF1>& a, const Vector<VT2,TF2>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the given vector.
+// \ingroup vector
+//
+// \param vector The given dense or sparse vector.
+// \return Iterator to the first element of the given vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE typename VT::Iterator begin( Vector<VT,TF>& vector )
+{
+ return (~vector).begin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the given vector.
+// \ingroup vector
+//
+// \param vector The given dense or sparse vector.
+// \return Iterator to the first element of the given vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE typename VT::ConstIterator begin( const Vector<VT,TF>& vector )
+{
+ return (~vector).begin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the given vector.
+// \ingroup vector
+//
+// \param vector The given dense or sparse vector.
+// \return Iterator to the first element of the given vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE typename VT::ConstIterator cbegin( const Vector<VT,TF>& vector )
+{
+ return (~vector).begin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the given vector.
+// \ingroup vector
+//
+// \param vector The given dense or sparse vector.
+// \return Iterator just past the last element of the given vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE typename VT::Iterator end( Vector<VT,TF>& vector )
+{
+ return (~vector).end();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the given vector.
+// \ingroup vector
+//
+// \param vector The given dense or sparse vector.
+// \return Iterator just past the last element of the given vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE typename VT::ConstIterator end( const Vector<VT,TF>& vector )
+{
+ return (~vector).end();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the given vector.
+// \ingroup vector
+//
+// \param vector The given dense or sparse vector.
+// \return Iterator just past the last element of the given vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE typename VT::ConstIterator cend( const Vector<VT,TF>& vector )
+{
+ return (~vector).end();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the vector.
+// \ingroup vector
+//
+// \param vector The given vector.
+// \return The size of the vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE size_t size( const Vector<VT,TF>& vector ) noexcept
+{
+ return (~vector).size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the vector.
+// \ingroup vector
+//
+// \param vector The given vector.
+// \return The capacity of the vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE size_t capacity( const Vector<VT,TF>& vector ) noexcept
+{
+ return (~vector).capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the vector.
+// \ingroup vector
+//
+// \param vector The given vector.
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE size_t nonZeros( const Vector<VT,TF>& vector )
+{
+ return (~vector).nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for non-resizable vectors.
+// \ingroup vector
+//
+// \param vector The given vector to be resized.
+// \param n The new size of the vector.
+// \return void
+// \exception std::invalid_argument Vector cannot be resized.
+//
+// This function tries to change the number of rows and columns of a non-resizable vector. Since
+// the vector cannot be resized, in case the specified size is not identical to the current size
+// of the vector, a \a std::invalid_argument exception is thrown.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE DisableIf_< IsResizable<VT> >
+ resize_backend( Vector<VT,TF>& vector, size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+
+ if( (~vector).size() != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector cannot be resized" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for resizable vectors.
+// \ingroup vector
+//
+// \param vector The given vector to be resized.
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+//
+// This function changes the size of the given resizable vector.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE EnableIf_< IsResizable<VT> >
+ resize_backend( Vector<VT,TF>& vector, size_t n, bool preserve )
+{
+ (~vector).resize( n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the vector.
+// \ingroup vector
+//
+// \param vector The given vector to be resized.
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Vector cannot be resized.
+//
+// This function provides a unified interface to resize dense and sparse vectors. In contrast
+// to the \c resize() member function, which is only available on resizable vector types, this
+// function can be used on both resizable and non-resizable vectors. In case the given vector
+// type \a VT is resizable (i.e. provides a \c resize() function), the type-specific \c resize()
+// member function is called. Depending on the type \a VT, this may result in the allocation of
+// new dynamic memory and the invalidation of existing views (subvectors, ...). In case \a VT is
+// non-resizable (i.e. does not provide a \c resize() function) and if the specified size is not
+// identical to the current size of the vector, a \a std::invalid_argument exception is thrown.
+
+ \code
+ blaze::DynamicVector<int> a( 3UL );
+ resize( a, 5UL ); // OK: regular resize operation
+
+ blaze::StaticVector<int,3UL> b;
+ resize( b, 3UL ); // OK: No resize necessary
+ resize( b, 5UL ); // Error: Vector cannot be resized!
+ \endcode
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE void resize( Vector<VT,TF>& vector, size_t n, bool preserve )
+{
+ resize_backend( vector, n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the two given vectors represent the same observable state.
+// \ingroup vector
+//
+// \param a The first vector to be tested for its state.
+// \param b The second vector to be tested for its state.
+// \return \a true in case the two vectors share a state, \a false otherwise.
+//
+// The isSame function provides an abstract interface for testing if the two given vectors
+// represent the same observable state. This happens for instance in case \c a and \c b refer
+// to the same vector or in case \c a and \c b are aliases for the same vector. In case both
+// vectors represent the same observable state, the function returns \a true, other it returns
+// \a false.
+
+ \code
+ typedef blaze::DynamicVector<int> VectorType;
+ typedef blaze::Subvector<VectorType> SubvectorType;
+
+ VectorType vec1( 4UL ); // Setup of a 4-dimensional dynamic vector
+ VectorType vec2( 4UL ); // Setup of a second 4-dimensional dynamic vector
+
+ SubvectorType sub1 = subvector( vec1, 0UL, 4UL ); // Subvector of vec1 for the entire range
+ SubvectorType sub2 = subvector( vec1, 1UL, 2UL ); // Subvector of vec1 for the range [1..3]
+ SubvectorType sub3 = subvector( vec1, 1UL, 2UL ); // Second subvector of vec1 for the range [1..3]
+
+ isSame( vec1, vec1 ); // returns true since both objects refer to the same vector
+ isSame( vec1, vec2 ); // returns false since vec1 and vec2 are two different vectors
+ isSame( vec1, sub1 ); // returns true since sub1 represents the same observable state as vec1
+ isSame( vec1, sub3 ); // returns false since sub3 only covers part of the range of vec1
+ isSame( sub2, sub3 ); // returns true since sub1 and sub2 refer to exactly the same range of vec1
+ isSame( sub1, sub3 ); // returns false since sub1 and sub3 refer to different ranges of vec1
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool isSame( const Vector<VT1,TF1>& a, const Vector<VT2,TF2>& b ) noexcept
+{
+ return ( IsSame<VT1,VT2>::value &&
+ reinterpret_cast<const void*>( &a ) == reinterpret_cast<const void*>( &b ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default assignment of a vector to another vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE void assign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ (~lhs).assign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector to be added.
+// \return void
+//
+// This function implements the default addition assignment of a vector to a vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE void addAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ (~lhs).addAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector to be subtracted.
+// \return void
+//
+// This function implements the default subtraction assignment of a vector to a vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE void subAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ (~lhs).subAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector to be multiplied.
+// \return void
+//
+// This function implements the default multiplication assignment of a vector to a vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE void multAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ (~lhs).multAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector divisor.
+// \return void
+//
+// This function implements the default division assignment of a vector to a vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE void divAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ (~lhs).divAssign( ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector to be assigned.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool tryAssign( const Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= (~lhs).size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= (~lhs).size() - index, "Invalid vector size" );
+
+ UNUSED_PARAMETER( lhs, rhs, index );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector to be added.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool tryAddAssign( const Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= (~lhs).size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= (~lhs).size() - index, "Invalid vector size" );
+
+ UNUSED_PARAMETER( lhs, rhs, index );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector to be subtracted.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool trySubAssign( const Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= (~lhs).size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= (~lhs).size() - index, "Invalid vector size" );
+
+ UNUSED_PARAMETER( lhs, rhs, index );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector to be multiplied.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool tryMultAssign( const Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= (~lhs).size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= (~lhs).size() - index, "Invalid vector size" );
+
+ UNUSED_PARAMETER( lhs, rhs, index );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the division assignment of a vector to a vector.
+// \ingroup vector
+//
+// \param lhs The target left-hand side vector.
+// \param rhs The right-hand side vector divisor.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side vector
+ , bool TF1 // Transpose flag of the left-hand side vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+BLAZE_ALWAYS_INLINE bool tryDivAssign( const Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= (~lhs).size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= (~lhs).size() - index, "Invalid vector size" );
+
+ UNUSED_PARAMETER( lhs, rhs, index );
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removal of all restrictions on the data access to the given vector.
+// \ingroup vector
+//
+// \param vector The vector to be derestricted.
+// \return Reference to the vector without access restrictions.
+//
+// This function removes all restrictions on the data access to the given vector. It returns a
+// reference to the vector that does provide the same interface but does not have any restrictions
+// on the data access.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag of the vector
+BLAZE_ALWAYS_INLINE VT& derestrict( Vector<VT,TF>& vector )
+{
+ return ~vector;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/expressions/View.h b/src/cpu/blaze/math/expressions/View.h
new file mode 100644
index 00000000..b987802b
--- /dev/null
+++ b/src/cpu/blaze/math/expressions/View.h
@@ -0,0 +1,70 @@
+//=================================================================================================
+/*!
+// \file blaze/math/expressions/View.h
+// \brief Header file for the View base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_EXPRESSIONS_VIEW_H_
+#define _BLAZE_MATH_EXPRESSIONS_VIEW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all views.
+// \ingroup math
+//
+// The View class serves as a tag for all views (subvectors, submatrices, rows, columns, ...).
+// All classes that represent a view and that are used within the expression template environment
+// of the Blaze library have to derive from this class in order to qualify as a view. Only in
+// case a class is derived from the View base class, the IsView type trait recognizes the class
+// as valid view.
+*/
+struct View : private Expression
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Abs.h b/src/cpu/blaze/math/functors/Abs.h
new file mode 100644
index 00000000..0ed09c5c
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Abs.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Abs.h
+// \brief Header file for the Abs functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ABS_H_
+#define _BLAZE_MATH_FUNCTORS_ABS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Abs.h>
+#include <blaze/math/simd/Abs.h>
+#include <blaze/math/typetraits/HasSIMDAbs.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the abs() function.
+// \ingroup functors
+*/
+struct Abs
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the abs() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the abs() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( abs( a ) )
+ {
+ return abs( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDAbs<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the abs() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the abs() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( abs( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return abs( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Acos.h b/src/cpu/blaze/math/functors/Acos.h
new file mode 100644
index 00000000..f12f310b
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Acos.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Acos.h
+// \brief Header file for the Acos functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ACOS_H_
+#define _BLAZE_MATH_FUNCTORS_ACOS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Acos.h>
+#include <blaze/math/simd/Acos.h>
+#include <blaze/math/typetraits/HasSIMDAcos.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the acos() function.
+// \ingroup functors
+*/
+struct Acos
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the acos() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the acos() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( acos( a ) )
+ {
+ return acos( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDAcos<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the acos() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the acos() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( acos( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return acos( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Acosh.h b/src/cpu/blaze/math/functors/Acosh.h
new file mode 100644
index 00000000..0432d517
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Acosh.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Acosh.h
+// \brief Header file for the Acosh functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ACOSH_H_
+#define _BLAZE_MATH_FUNCTORS_ACOSH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Acosh.h>
+#include <blaze/math/simd/Acosh.h>
+#include <blaze/math/typetraits/HasSIMDAcosh.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the acosh() function.
+// \ingroup functors
+*/
+struct Acosh
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the acosh() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the acosh() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( acosh( a ) )
+ {
+ return acosh( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDAcosh<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the acosh() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the acosh() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( acosh( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return acosh( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Asin.h b/src/cpu/blaze/math/functors/Asin.h
new file mode 100644
index 00000000..9f283138
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Asin.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Asin.h
+// \brief Header file for the Asin functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ASIN_H_
+#define _BLAZE_MATH_FUNCTORS_ASIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Asin.h>
+#include <blaze/math/simd/Asin.h>
+#include <blaze/math/typetraits/HasSIMDAsin.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the asin() function.
+// \ingroup functors
+*/
+struct Asin
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the asin() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the asin() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( asin( a ) )
+ {
+ return asin( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDAsin<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the asin() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the asin() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( asin( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return asin( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Asinh.h b/src/cpu/blaze/math/functors/Asinh.h
new file mode 100644
index 00000000..a47789dc
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Asinh.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Asinh.h
+// \brief Header file for the Asinh functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ASINH_H_
+#define _BLAZE_MATH_FUNCTORS_ASINH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Asinh.h>
+#include <blaze/math/simd/Asinh.h>
+#include <blaze/math/typetraits/HasSIMDAsinh.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the asinh() function.
+// \ingroup functors
+*/
+struct Asinh
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the asinh() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the asinh() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( asinh( a ) )
+ {
+ return asinh( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDAsinh<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the asinh() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the asinh() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( asinh( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return asinh( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Atan.h b/src/cpu/blaze/math/functors/Atan.h
new file mode 100644
index 00000000..5e6642e6
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Atan.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Atan.h
+// \brief Header file for the Atan functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ATAN_H_
+#define _BLAZE_MATH_FUNCTORS_ATAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Atan.h>
+#include <blaze/math/simd/Atan.h>
+#include <blaze/math/typetraits/HasSIMDAtan.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the atan() function.
+// \ingroup functors
+*/
+struct Atan
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the atan() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the atan() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( atan( a ) )
+ {
+ return atan( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDAtan<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the atan() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the atan() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( atan( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return atan( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Atanh.h b/src/cpu/blaze/math/functors/Atanh.h
new file mode 100644
index 00000000..6ae9fc0b
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Atanh.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Atanh.h
+// \brief Header file for the Atanh functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ATANH_H_
+#define _BLAZE_MATH_FUNCTORS_ATANH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Atanh.h>
+#include <blaze/math/simd/Atanh.h>
+#include <blaze/math/typetraits/HasSIMDAtanh.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the atanh() function.
+// \ingroup functors
+*/
+struct Atanh
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the atanh() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the atanh() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( atanh( a ) )
+ {
+ return atanh( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDAtanh<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the atanh() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the atanh() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( atanh( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return atanh( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/CTrans.h b/src/cpu/blaze/math/functors/CTrans.h
new file mode 100644
index 00000000..a75d17a7
--- /dev/null
+++ b/src/cpu/blaze/math/functors/CTrans.h
@@ -0,0 +1,77 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/CTrans.h
+// \brief Header file for the CTrans functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_CTRANS_H_
+#define _BLAZE_MATH_FUNCTORS_CTRANS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the ctrans() function.
+// \ingroup functors
+*/
+struct CTrans
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the ctrans() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the ctrans() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( ctrans( a ) )
+ {
+ return ctrans( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Cbrt.h b/src/cpu/blaze/math/functors/Cbrt.h
new file mode 100644
index 00000000..175d7428
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Cbrt.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Cbrt.h
+// \brief Header file for the Cbrt functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_CBRT_H_
+#define _BLAZE_MATH_FUNCTORS_CBRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Cbrt.h>
+#include <blaze/math/simd/Cbrt.h>
+#include <blaze/math/typetraits/HasSIMDCbrt.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the cbrt() function.
+// \ingroup functors
+*/
+struct Cbrt
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the cbrt() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the cbrt() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( cbrt( a ) )
+ {
+ return cbrt( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDCbrt<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the cbrt() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the cbrt() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( cbrt( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return cbrt( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Ceil.h b/src/cpu/blaze/math/functors/Ceil.h
new file mode 100644
index 00000000..1ab61cb9
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Ceil.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Ceil.h
+// \brief Header file for the Ceil functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_CEIL_H_
+#define _BLAZE_MATH_FUNCTORS_CEIL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Ceil.h>
+#include <blaze/math/simd/Ceil.h>
+#include <blaze/math/typetraits/HasSIMDCeil.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the ceil() function.
+// \ingroup functors
+*/
+struct Ceil
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the ceil() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the ceil() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( ceil( a ) )
+ {
+ return ceil( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDCeil<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the ceil() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the ceil() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( ceil( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return ceil( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Conj.h b/src/cpu/blaze/math/functors/Conj.h
new file mode 100644
index 00000000..fabd57f2
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Conj.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Conj.h
+// \brief Header file for the Conj functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_CONJ_H_
+#define _BLAZE_MATH_FUNCTORS_CONJ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/simd/Conj.h>
+#include <blaze/math/typetraits/HasSIMDConj.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the conj() function.
+// \ingroup functors
+*/
+struct Conj
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the conj() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the conj() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( conj( a ) )
+ {
+ return conj( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDConj<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the conj() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the conj() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( conj( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return conj( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Cos.h b/src/cpu/blaze/math/functors/Cos.h
new file mode 100644
index 00000000..8b14ce6e
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Cos.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Cos.h
+// \brief Header file for the Cos functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_COS_H_
+#define _BLAZE_MATH_FUNCTORS_COS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Cos.h>
+#include <blaze/math/simd/Cos.h>
+#include <blaze/math/typetraits/HasSIMDCos.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the cos() function.
+// \ingroup functors
+*/
+struct Cos
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the cos() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the cos() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( cos( a ) )
+ {
+ return cos( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDCos<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the cos() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the cos() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( cos( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return cos( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Cosh.h b/src/cpu/blaze/math/functors/Cosh.h
new file mode 100644
index 00000000..44973034
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Cosh.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Cosh.h
+// \brief Header file for the Cosh functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_COSH_H_
+#define _BLAZE_MATH_FUNCTORS_COSH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Cosh.h>
+#include <blaze/math/simd/Cosh.h>
+#include <blaze/math/typetraits/HasSIMDCosh.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the cosh() function.
+// \ingroup functors
+*/
+struct Cosh
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the cosh() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the cosh() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( cosh( a ) )
+ {
+ return cosh( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDCosh<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the cosh() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the cosh() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( cosh( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return cosh( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Erf.h b/src/cpu/blaze/math/functors/Erf.h
new file mode 100644
index 00000000..316102d8
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Erf.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Erf.h
+// \brief Header file for the Erf functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ERF_H_
+#define _BLAZE_MATH_FUNCTORS_ERF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Erf.h>
+#include <blaze/math/simd/Erf.h>
+#include <blaze/math/typetraits/HasSIMDErf.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the erf() function.
+// \ingroup functors
+*/
+struct Erf
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the erf() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the erf() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( erf( a ) )
+ {
+ return erf( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDErf<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the erf() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the erf() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( erf( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return erf( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Erfc.h b/src/cpu/blaze/math/functors/Erfc.h
new file mode 100644
index 00000000..aeace2dd
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Erfc.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Erfc.h
+// \brief Header file for the Erfc functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_ERFC_H_
+#define _BLAZE_MATH_FUNCTORS_ERFC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Erfc.h>
+#include <blaze/math/simd/Erfc.h>
+#include <blaze/math/typetraits/HasSIMDErfc.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the erfc() function.
+// \ingroup functors
+*/
+struct Erfc
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the erfc() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the erfc() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( erfc( a ) )
+ {
+ return erfc( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDErfc<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the erfc() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the erfc() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( erfc( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return erfc( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Eval.h b/src/cpu/blaze/math/functors/Eval.h
new file mode 100644
index 00000000..aec2322a
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Eval.h
@@ -0,0 +1,77 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Eval.h
+// \brief Header file for the Eval functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_EVAL_H_
+#define _BLAZE_MATH_FUNCTORS_EVAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the eval() function.
+// \ingroup functors
+*/
+struct Eval
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the eval() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the eval() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( eval( a ) )
+ {
+ return eval( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Exp.h b/src/cpu/blaze/math/functors/Exp.h
new file mode 100644
index 00000000..16077866
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Exp.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Exp.h
+// \brief Header file for the Exp functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_EXP_H_
+#define _BLAZE_MATH_FUNCTORS_EXP_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Exp.h>
+#include <blaze/math/simd/Exp.h>
+#include <blaze/math/typetraits/HasSIMDExp.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the exp() function.
+// \ingroup functors
+*/
+struct Exp
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the exp() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the exp() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( exp( a ) )
+ {
+ return exp( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDExp<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the exp() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the exp() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( exp( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return exp( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Floor.h b/src/cpu/blaze/math/functors/Floor.h
new file mode 100644
index 00000000..e40a8359
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Floor.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Floor.h
+// \brief Header file for the Floor functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_FLOOR_H_
+#define _BLAZE_MATH_FUNCTORS_FLOOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Floor.h>
+#include <blaze/math/simd/Floor.h>
+#include <blaze/math/typetraits/HasSIMDFloor.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the floor() function.
+// \ingroup functors
+*/
+struct Floor
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the floor() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the floor() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( floor( a ) )
+ {
+ return floor( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDFloor<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the floor() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the floor() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( floor( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return floor( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Forward.h b/src/cpu/blaze/math/functors/Forward.h
new file mode 100644
index 00000000..d58cc5e2
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Forward.h
@@ -0,0 +1,83 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Forward.h
+// \brief Header file for all functor forward declarations
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_FORWARD_H_
+#define _BLAZE_MATH_FUNCTORS_FORWARD_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+struct Abs;
+struct Acos;
+struct Acosh;
+struct Asin;
+struct Asinh;
+struct Atan;
+struct Atanh;
+struct Cbrt;
+struct Ceil;
+struct Conj;
+struct Cos;
+struct Cosh;
+struct CTrans;
+struct Erf;
+struct Erfc;
+struct Eval;
+struct Exp;
+struct Floor;
+struct Imag;
+struct Inv;
+struct InvCbrt;
+struct InvSqrt;
+struct Log;
+struct Log10;
+template< typename > struct Pow;
+struct Real;
+struct Serial;
+struct Sin;
+struct Sinh;
+struct Sqrt;
+struct Tan;
+struct Tanh;
+struct Trans;
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Functors.h b/src/cpu/blaze/math/functors/Functors.h
new file mode 100644
index 00000000..a702bc4b
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Functors.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Functors.h
+// \brief Mathematical functors module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_FUNCTORS_H_
+#define _BLAZE_MATH_FUNCTORS_FUNCTORS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup functors Functors
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Imag.h b/src/cpu/blaze/math/functors/Imag.h
new file mode 100644
index 00000000..7f2394c0
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Imag.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Imag.h
+// \brief Header file for the Imag functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_IMAG_H_
+#define _BLAZE_MATH_FUNCTORS_IMAG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Imaginary.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the imag() function.
+// \ingroup functors
+*/
+struct Imag
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the imag() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the imag() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( imag( a ) )
+ {
+ return imag( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Inv.h b/src/cpu/blaze/math/functors/Inv.h
new file mode 100644
index 00000000..74e62799
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Inv.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Inv.h
+// \brief Header file for the Inv functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_INV_H_
+#define _BLAZE_MATH_FUNCTORS_INV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Invert.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the inv() function.
+// \ingroup functors
+*/
+struct Inv
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the inv() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the inv() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( inv( a ) )
+ {
+ return inv( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/InvCbrt.h b/src/cpu/blaze/math/functors/InvCbrt.h
new file mode 100644
index 00000000..99b1f917
--- /dev/null
+++ b/src/cpu/blaze/math/functors/InvCbrt.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/InvCbrt.h
+// \brief Header file for the InvCbrt functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_INVCBRT_H_
+#define _BLAZE_MATH_FUNCTORS_INVCBRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/InvCbrt.h>
+#include <blaze/math/simd/InvCbrt.h>
+#include <blaze/math/typetraits/HasSIMDInvCbrt.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the invcbrt() function.
+// \ingroup functors
+*/
+struct InvCbrt
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the invcbrt() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the invcbrt() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( invcbrt( a ) )
+ {
+ return invcbrt( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDInvCbrt<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the invcbrt() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the invcbrt() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( invcbrt( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return invcbrt( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/InvSqrt.h b/src/cpu/blaze/math/functors/InvSqrt.h
new file mode 100644
index 00000000..0ae64aab
--- /dev/null
+++ b/src/cpu/blaze/math/functors/InvSqrt.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/InvSqrt.h
+// \brief Header file for the InvSqrt functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_INVSQRT_H_
+#define _BLAZE_MATH_FUNCTORS_INVSQRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/InvSqrt.h>
+#include <blaze/math/simd/InvSqrt.h>
+#include <blaze/math/typetraits/HasSIMDInvSqrt.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the invsqrt() function.
+// \ingroup functors
+*/
+struct InvSqrt
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the invsqrt() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the invsqrt() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( invsqrt( a ) )
+ {
+ return invsqrt( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDInvSqrt<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the invsqrt() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the invsqrt() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( invsqrt( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return invsqrt( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Log.h b/src/cpu/blaze/math/functors/Log.h
new file mode 100644
index 00000000..87c40125
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Log.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Log.h
+// \brief Header file for the Log functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_LOG_H_
+#define _BLAZE_MATH_FUNCTORS_LOG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Log.h>
+#include <blaze/math/simd/Log.h>
+#include <blaze/math/typetraits/HasSIMDLog.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the log() function.
+// \ingroup functors
+*/
+struct Log
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the log() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the log() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( log( a ) )
+ {
+ return log( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDLog<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the log() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the log() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( log( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return log( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Log10.h b/src/cpu/blaze/math/functors/Log10.h
new file mode 100644
index 00000000..f1c4fae3
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Log10.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Log10.h
+// \brief Header file for the Log10 functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_LOG10_H_
+#define _BLAZE_MATH_FUNCTORS_LOG10_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Log10.h>
+#include <blaze/math/simd/Log10.h>
+#include <blaze/math/typetraits/HasSIMDLog10.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the log10() function.
+// \ingroup functors
+*/
+struct Log10
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the log10() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the log10() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( log10( a ) )
+ {
+ return log10( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDLog10<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the log10() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the log10() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( log10( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return log10( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Pow.h b/src/cpu/blaze/math/functors/Pow.h
new file mode 100644
index 00000000..125d4f64
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Pow.h
@@ -0,0 +1,139 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Pow.h
+// \brief Header file for the Pow functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_POW_H_
+#define _BLAZE_MATH_FUNCTORS_POW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Pow.h>
+#include <blaze/math/simd/Pow.h>
+#include <blaze/math/simd/SIMDTrait.h>
+#include <blaze/math/typetraits/HasSIMDPow.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the pow() function.
+// \ingroup functors
+*/
+template< typename ET > // Type of the exponent
+struct Pow
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef SIMDTrait_<ET> SIMDET; //!< The SIMD exponent type.
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Constructor of the Pow functor.
+ //
+ // \param exp The exponent.
+ */
+ explicit inline Pow( ET exp )
+ : exp_ ( exp ) // The scalar exponent
+ , simdExp_( set( exp_ ) ) // The SIMD exponent
+ {}
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the pow() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the pow() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const
+ -> decltype( pow( a, std::declval<ET>() ) )
+ {
+ return pow( a, exp_ );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return IsSame<T,ET>::value && HasSIMDPow<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the pow() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the pow() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const
+ -> decltype( pow( a, std::declval<SIMDET>() ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return pow( a, simdExp_ );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ ET exp_; //!< The scalar exponent.
+ SIMDET simdExp_; //!< The SIMD exponent.
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Real.h b/src/cpu/blaze/math/functors/Real.h
new file mode 100644
index 00000000..af2ce573
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Real.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Real.h
+// \brief Header file for the Real functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_REAL_H_
+#define _BLAZE_MATH_FUNCTORS_REAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Real.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the real() function.
+// \ingroup functors
+*/
+struct Real
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the real() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the real() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( real( a ) )
+ {
+ return real( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Serial.h b/src/cpu/blaze/math/functors/Serial.h
new file mode 100644
index 00000000..736e0094
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Serial.h
@@ -0,0 +1,77 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Serial.h
+// \brief Header file for the Serial functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_SERIAL_H_
+#define _BLAZE_MATH_FUNCTORS_SERIAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the Serial() function.
+// \ingroup functors
+*/
+struct Serial
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the serial() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the serial() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( serial( a ) )
+ {
+ return serial( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Sin.h b/src/cpu/blaze/math/functors/Sin.h
new file mode 100644
index 00000000..9acda28c
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Sin.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Sin.h
+// \brief Header file for the Sin functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_SIN_H_
+#define _BLAZE_MATH_FUNCTORS_SIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Sin.h>
+#include <blaze/math/simd/Sin.h>
+#include <blaze/math/typetraits/HasSIMDSin.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the sin() function.
+// \ingroup functors
+*/
+struct Sin
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the sin() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the sin() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( sin( a ) )
+ {
+ return sin( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDSin<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the sin() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the sin() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( sin( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return sin( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Sinh.h b/src/cpu/blaze/math/functors/Sinh.h
new file mode 100644
index 00000000..6b4d8b67
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Sinh.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Sinh.h
+// \brief Header file for the Sinh functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_SINH_H_
+#define _BLAZE_MATH_FUNCTORS_SINH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Sinh.h>
+#include <blaze/math/simd/Sinh.h>
+#include <blaze/math/typetraits/HasSIMDSinh.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the sinh() function.
+// \ingroup functors
+*/
+struct Sinh
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the sinh() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the sinh() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( sinh( a ) )
+ {
+ return sinh( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDSinh<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the sinh() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the sinh() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( sinh( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return sinh( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Sqrt.h b/src/cpu/blaze/math/functors/Sqrt.h
new file mode 100644
index 00000000..b493ab49
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Sqrt.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Sqrt.h
+// \brief Header file for the Sqrt functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_SQRT_H_
+#define _BLAZE_MATH_FUNCTORS_SQRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Sqrt.h>
+#include <blaze/math/simd/Sqrt.h>
+#include <blaze/math/typetraits/HasSIMDSqrt.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the sqrt() function.
+// \ingroup functors
+*/
+struct Sqrt
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the sqrt() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the sqrt() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( sqrt( a ) )
+ {
+ return sqrt( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDSqrt<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the sqrt() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the sqrt() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( sqrt( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return sqrt( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Tan.h b/src/cpu/blaze/math/functors/Tan.h
new file mode 100644
index 00000000..7b8e13d7
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Tan.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Tan.h
+// \brief Header file for the Tan functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_TAN_H_
+#define _BLAZE_MATH_FUNCTORS_TAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Tan.h>
+#include <blaze/math/simd/Tan.h>
+#include <blaze/math/typetraits/HasSIMDTan.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the tan() function.
+// \ingroup functors
+*/
+struct Tan
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the tan() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the tan() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( tan( a ) )
+ {
+ return tan( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDTan<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the tan() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the tan() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( tan( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return tan( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Tanh.h b/src/cpu/blaze/math/functors/Tanh.h
new file mode 100644
index 00000000..165e8213
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Tanh.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Tanh.h
+// \brief Header file for the Tanh functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_TANH_H_
+#define _BLAZE_MATH_FUNCTORS_TANH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/constraints/SIMDPack.h>
+#include <blaze/math/shims/Tanh.h>
+#include <blaze/math/simd/Tanh.h>
+#include <blaze/math/typetraits/HasSIMDTanh.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the tanh() function.
+// \ingroup functors
+*/
+struct Tanh
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the tanh() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the tanh() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( tanh( a ) )
+ {
+ return tanh( a );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether SIMD is enabled for the specified data type \a T.
+ //
+ // \return \a true in case SIMD is enabled for the data type \a T, \a false if not.
+ */
+ template< typename T >
+ static constexpr bool simdEnabled() { return HasSIMDTanh<T>::value; }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns the result of the tanh() function for the given SIMD vector.
+ //
+ // \param a The given SIMD vector.
+ // \return The result of the tanh() function for the given SIMD vector.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto load( const T& a ) const -> decltype( tanh( a ) )
+ {
+ BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
+ return tanh( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/functors/Trans.h b/src/cpu/blaze/math/functors/Trans.h
new file mode 100644
index 00000000..2d0f4b04
--- /dev/null
+++ b/src/cpu/blaze/math/functors/Trans.h
@@ -0,0 +1,77 @@
+//=================================================================================================
+/*!
+// \file blaze/math/functors/Trans.h
+// \brief Header file for the Trans functor
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_FUNCTORS_TRANS_H_
+#define _BLAZE_MATH_FUNCTORS_TRANS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for the trans() function.
+// \ingroup functors
+*/
+struct Trans
+{
+ //**********************************************************************************************
+ /*!\brief Returns the result of the trans() function for the given object/value.
+ //
+ // \param a The given object/value.
+ // \return The result of the trans() function for the given object/value.
+ */
+ template< typename T >
+ BLAZE_ALWAYS_INLINE auto operator()( const T& a ) const -> decltype( trans( a ) )
+ {
+ return trans( a );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/LAPACK.h b/src/cpu/blaze/math/lapack/LAPACK.h
new file mode 100644
index 00000000..2368f683
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/LAPACK.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/Lapack.h
+// \brief LAPACK module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_LAPACK_H_
+#define _BLAZE_MATH_LAPACK_LAPACK_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup lapack LAPACK
+// \ingroup math
+*/
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\defgroup lapack_decomposition Matrix Decomposition
+// \ingroup lapack
+*/
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\defgroup lapack_inversion Matrix Inversion
+// \ingroup lapack
+*/
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\defgroup lapack_substitution Forward/Backward Substitution
+// \ingroup lapack
+*/
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\defgroup lapack_solver Linear System Solver
+// \ingroup lapack
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/gelqf.h b/src/cpu/blaze/math/lapack/clapack/gelqf.h
new file mode 100644
index 00000000..5449041c
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/gelqf.h
@@ -0,0 +1,326 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/gelqf.h
+// \brief Header file for the CLAPACK gelqf wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GELQF_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GELQF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgelqf_( int* m, int* n, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void dgelqf_( int* m, int* n, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+void cgelqf_( int* m, int* n, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void zgelqf_( int* m, int* n, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LQ DECOMPOSITION FUNCTIONS (GELQF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LQ decomposition functions (gelqf) */
+//@{
+inline void gelqf( int m, int n, float* A, int lda, float* tau,
+ float* work, int lwork, int* info );
+
+inline void gelqf( int m, int n, double* A, int lda, double* tau,
+ double* work, int lwork, int* info );
+
+inline void gelqf( int m, int n, complex<float>* A, int lda, complex<float>* tau,
+ complex<float>* work, int lwork, int* info );
+
+inline void gelqf( int m, int n, complex<double>* A, int lda, complex<double>* tau,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LQ decomposition of the given dense single precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix LQ decomposition of a general \a m-by-\a n single
+// precision column-major matrix based on the LAPACK sgelqf() function. The resulting decomposition
+// has the form
+
+ \f[ A = L \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) . . . H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:n)</tt> is stored on exit in <tt>A(i,i+1:n)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and below the diagonal of the matrix contain the
+// \a m-by-min(\a m,\a n) lower trapezoidal matrix \c L (\c L is lower triangular if \a m <= \a n);
+// the elements above the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgelqf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gelqf( int m, int n, float* A, int lda, float* tau,
+ float* work, int lwork, int* info )
+{
+ sgelqf_( &m, &n, A, &lda, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LQ decomposition of the given dense double precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix LQ decomposition of a general \a m-by-\a n double
+// precision column-major matrix based on the LAPACK sgelqf() function. The resulting decomposition
+// has the form
+
+ \f[ A = L \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) . . . H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:n)</tt> is stored on exit in <tt>A(i,i+1:n)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and below the diagonal of the matrix contain the
+// \a m-by-min(\a m,\a n) lower trapezoidal matrix \c L (\c L is lower triangular if \a m <= \a n);
+// the elements above the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgelqf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gelqf( int m, int n, double* A, int lda, double* tau,
+ double* work, int lwork, int* info )
+{
+ dgelqf_( &m, &n, A, &lda, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LQ decomposition of the given dense single precision complex
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix LQ decomposition of a general \a m-by-\a n single
+// precision complex column-major matrix based on the LAPACK sgelqf() function. The resulting
+// decomposition has the form
+
+ \f[ A = L \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) . . . H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:n)</tt> is stored on exit in <tt>A(i,i+1:n)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and below the diagonal of the matrix contain the
+// \a m-by-min(\a m,\a n) lower trapezoidal matrix \c L (\c L is lower triangular if \a m <= \a n);
+// the elements above the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgelqf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gelqf( int m, int n, complex<float>* A, int lda, complex<float>* tau,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cgelqf_( &m, &n, reinterpret_cast<float*>( A ), &lda, reinterpret_cast<float*>( tau ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LQ decomposition of the given dense double precision complex
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix LQ decomposition of a general \a m-by-\a n double
+// precision complex column-major matrix based on the LAPACK sgelqf() function. The resulting
+// decomposition has the form
+
+ \f[ A = L \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) . . . H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:n)</tt> is stored on exit in <tt>A(i,i+1:n)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and below the diagonal of the matrix contain the
+// \a m-by-min(\a m,\a n) lower trapezoidal matrix \c L (\c L is lower triangular if \a m <= \a n);
+// the elements above the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgelqf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gelqf( int m, int n, complex<double>* A, int lda, complex<double>* tau,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zgelqf_( &m, &n, reinterpret_cast<double*>( A ), &lda, reinterpret_cast<double*>( tau ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/geqlf.h b/src/cpu/blaze/math/lapack/clapack/geqlf.h
new file mode 100644
index 00000000..6ea1f3c3
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/geqlf.h
@@ -0,0 +1,330 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/geqlf.h
+// \brief Header file for the CLAPACK geqlf wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GEQLF_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GEQLF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgeqlf_( int* m, int* n, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void dgeqlf_( int* m, int* n, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+void cgeqlf_( int* m, int* n, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void zgeqlf_( int* m, int* n, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK QL DECOMPOSITION FUNCTIONS (GEQLF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK QL decomposition functions (geqlf) */
+//@{
+inline void geqlf( int m, int n, float* A, int lda, float* tau,
+ float* work, int lwork, int* info );
+
+inline void geqlf( int m, int n, double* A, int lda, double* tau,
+ double* work, int lwork, int* info );
+
+inline void geqlf( int m, int n, complex<float>* A, int lda, complex<float>* tau,
+ complex<float>* work, int lwork, int* info );
+
+inline void geqlf( int m, int n, complex<double>* A, int lda, complex<double>* tau,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QL decomposition of the given dense single precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QL decomposition of a general \a m-by-\a n single
+// precision column-major matrix based on the LAPACK sgeqlf() function. The resulting decomposition
+// has the form
+
+ \f[ A = Q \cdot L, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) ... H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(m-k+i+1:m) = 0</tt> and
+// <tt>v(m-k+i) = 1</tt>. <tt>v(1:m-k+i-1)</tt> is stored on exit in <tt>A(1:m-k+i-1,n-k+i)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m >= \a n, the lower triangle of the subarray
+// A(m-n+1:m,1:n) contains the \a n-by-\a n lower triangular matrix \c L and in case \a m <= \a n,
+// the elements on and below the (\a n-\a m)-th subdiagonal contain the \a m-by-\a n lower
+// trapezoidal matrix \c L; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgeqlf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqlf( int m, int n, float* A, int lda, float* tau,
+ float* work, int lwork, int* info )
+{
+ sgeqlf_( &m, &n, A, &lda, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QL decomposition of the given dense double precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QL decomposition of a general \a m-by-\a n double
+// precision column-major matrix based on the LAPACK sgeqlf() function. The resulting decomposition
+// has the form
+
+ \f[ A = Q \cdot L, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) ... H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(m-k+i+1:m) = 0</tt> and
+// <tt>v(m-k+i) = 1</tt>. <tt>v(1:m-k+i-1)</tt> is stored on exit in <tt>A(1:m-k+i-1,n-k+i)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m >= \a n, the lower triangle of the subarray
+// A(m-n+1:m,1:n) contains the \a n-by-\a n lower triangular matrix \c L and in case \a m <= \a n,
+// the elements on and below the (\a n-\a m)-th subdiagonal contain the \a m-by-\a n lower
+// trapezoidal matrix \c L; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgeqlf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqlf( int m, int n, double* A, int lda, double* tau,
+ double* work, int lwork, int* info )
+{
+ dgeqlf_( &m, &n, A, &lda, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QL decomposition of the given dense single precision complex
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QL decomposition of a general \a m-by-\a n single
+// precision complex column-major matrix based on the LAPACK sgeqlf() function. The resulting
+// decomposition has the form
+
+ \f[ A = Q \cdot L, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) ... H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(m-k+i+1:m) = 0</tt> and
+// <tt>v(m-k+i) = 1</tt>. <tt>v(1:m-k+i-1)</tt> is stored on exit in <tt>A(1:m-k+i-1,n-k+i)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m >= \a n, the lower triangle of the subarray
+// A(m-n+1:m,1:n) contains the \a n-by-\a n lower triangular matrix \c L and in case \a m <= \a n,
+// the elements on and below the (\a n-\a m)-th subdiagonal contain the \a m-by-\a n lower
+// trapezoidal matrix \c L; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgeqlf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqlf( int m, int n, complex<float>* A, int lda, complex<float>* tau,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cgeqlf_( &m, &n, reinterpret_cast<float*>( A ), &lda, reinterpret_cast<float*>( tau ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QL decomposition of the given dense double precision complex
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QL decomposition of a general \a m-by-\a n double
+// precision complex column-major matrix based on the LAPACK sgeqlf() function. The resulting
+// decomposition has the form
+
+ \f[ A = Q \cdot L, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) ... H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(m-k+i+1:m) = 0</tt> and
+// <tt>v(m-k+i) = 1</tt>. <tt>v(1:m-k+i-1)</tt> is stored on exit in <tt>A(1:m-k+i-1,n-k+i)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m >= \a n, the lower triangle of the subarray
+// A(m-n+1:m,1:n) contains the \a n-by-\a n lower triangular matrix \c L and in case \a m <= \a n,
+// the elements on and below the (\a n-\a m)-th subdiagonal contain the \a m-by-\a n lower
+// trapezoidal matrix \c L; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgeqlf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqlf( int m, int n, complex<double>* A, int lda, complex<double>* tau,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zgeqlf_( &m, &n, reinterpret_cast<double*>( A ), &lda, reinterpret_cast<double*>( tau ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/geqp3.h b/src/cpu/blaze/math/lapack/clapack/geqp3.h
new file mode 100644
index 00000000..17855930
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/geqp3.h
@@ -0,0 +1,194 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/geqp3.h
+// \brief Header file for the CLAPACK geqp3 wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GEQP3_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GEQP3_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgeqp3_( int* m, int* n, float* A, int* lda, int* jpvt, float* tau, float* work, int* lwork, int* info );
+void dgeqp3_( int* m, int* n, double* A, int* lda, int* jpvt, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK QR DECOMPOSITION FUNCTIONS (GEQP3)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK QR decomposition functions (geqp3) */
+//@{
+inline void geqp3( int m, int n, float* A, int lda, int* jpvt, float* tau,
+ float* work, int lwork, int* info );
+
+inline void geqp3( int m, int n, double* A, int lda, int* jpvt, double* tau,
+ double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QR decomposition of the given dense single precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param jpvt Auxiliary array for the pivot indices; size = \a n.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= \f$ 3*n+1 \f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QR decomposition of a general \a m-by-\a n single
+// precision column-major matrix based on the LAPACK sgeqp3() function. The resulting decomposition
+// has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:m)</tt> is stored on exit in <tt>A(i+1:m,i)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and above the diagonal of the matrix contain the
+// min(\a m,\a n)-by-\a n upper trapezoidal matrix \c R (\c R is upper triangular if \a m >= \a n);
+// the elements below the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgeqp3() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqp3( int m, int n, float* A, int lda, int* jpvt, float* tau,
+ float* work, int lwork, int* info )
+{
+ sgeqp3_( &m, &n, A, &lda, jpvt, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QR decomposition of the given dense double precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param jpvt Auxiliary array for the pivot indices; size = \a n.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= \f$ 3*n+1 \f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QR decomposition of a general \a m-by-\a n double
+// precision column-major matrix based on the LAPACK dgeqp3() function. The resulting decomposition
+// has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:m)</tt> is stored on exit in <tt>A(i+1:m,i)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and above the diagonal of the matrix contain the
+// min(\a m,\a n)-by-\a n upper trapezoidal matrix \c R (\c R is upper triangular if \a m >= \a n);
+// the elements below the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dgeqp3() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqp3( int m, int n, double* A, int lda, int* jpvt, double* tau,
+ double* work, int lwork, int* info )
+{
+ dgeqp3_( &m, &n, A, &lda, jpvt, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/geqrf.h b/src/cpu/blaze/math/lapack/clapack/geqrf.h
new file mode 100644
index 00000000..87b3453c
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/geqrf.h
@@ -0,0 +1,326 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/geqrf.h
+// \brief Header file for the CLAPACK geqrf wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GEQRF_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GEQRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgeqrf_( int* m, int* n, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void dgeqrf_( int* m, int* n, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+void cgeqrf_( int* m, int* n, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void zgeqrf_( int* m, int* n, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK QR DECOMPOSITION FUNCTIONS (GEQRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK QR decomposition functions (geqrf) */
+//@{
+inline void geqrf( int m, int n, float* A, int lda, float* tau,
+ float* work, int lwork, int* info );
+
+inline void geqrf( int m, int n, double* A, int lda, double* tau,
+ double* work, int lwork, int* info );
+
+inline void geqrf( int m, int n, complex<float>* A, int lda, complex<float>* tau,
+ complex<float>* work, int lwork, int* info );
+
+inline void geqrf( int m, int n, complex<double>* A, int lda, complex<double>* tau,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QR decomposition of the given dense single precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QR decomposition of a general \a m-by-\a n single
+// precision column-major matrix based on the LAPACK sgeqrf() function. The resulting decomposition
+// has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:m)</tt> is stored on exit in <tt>A(i+1:m,i)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and above the diagonal of the matrix contain the
+// min(\a m,\a n)-by-\a n upper trapezoidal matrix \c R (\c R is upper triangular if \a m >= \a n);
+// the elements below the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgeqrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqrf( int m, int n, float* A, int lda, float* tau,
+ float* work, int lwork, int* info )
+{
+ sgeqrf_( &m, &n, A, &lda, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QR decomposition of the given dense double precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QR decomposition of a general \a m-by-\a n double
+// precision column-major matrix based on the LAPACK dgeqrf() function. The resulting decomposition
+// has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:m)</tt> is stored on exit in <tt>A(i+1:m,i)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and above the diagonal of the matrix contain the
+// min(\a m,\a n)-by-\a n upper trapezoidal matrix \c R (\c R is upper triangular if \a m >= \a n);
+// the elements below the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dgeqrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqrf( int m, int n, double* A, int lda, double* tau,
+ double* work, int lwork, int* info )
+{
+ dgeqrf_( &m, &n, A, &lda, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QR decomposition of the given dense single precision complex
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QR decomposition of a general \a m-by-\a n single
+// precision complex column-major matrix based on the LAPACK cgeqrf() function. The resulting
+// decomposition has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:m)</tt> is stored on exit in <tt>A(i+1:m,i)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and above the diagonal of the matrix contain the
+// min(\a m,\a n)-by-\a n upper trapezoidal matrix \c R (\c R is upper triangular if \a m >= \a n);
+// the elements below the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cgeqrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqrf( int m, int n, complex<float>* A, int lda, complex<float>* tau,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cgeqrf_( &m, &n, reinterpret_cast<float*>( A ), &lda, reinterpret_cast<float*>( tau ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QR decomposition of the given dense double precision complex
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix QR decomposition of a general \a m-by-\a n double
+// precision complex column-major matrix based on the LAPACK zgeqrf() function. The resulting
+// decomposition has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:m)</tt> is stored on exit in <tt>A(i+1:m,i)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and above the diagonal of the matrix contain the
+// min(\a m,\a n)-by-\a n upper trapezoidal matrix \c R (\c R is upper triangular if \a m >= \a n);
+// the elements below the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zgeqrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void geqrf( int m, int n, complex<double>* A, int lda, complex<double>* tau,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zgeqrf_( &m, &n, reinterpret_cast<double*>( A ), &lda, reinterpret_cast<double*>( tau ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/gerqf.h b/src/cpu/blaze/math/lapack/clapack/gerqf.h
new file mode 100644
index 00000000..60a2e0d9
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/gerqf.h
@@ -0,0 +1,330 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/gerqf.h
+// \brief Header file for the CLAPACK gerqf wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GERQF_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GERQF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgerqf_( int* m, int* n, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void dgerqf_( int* m, int* n, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+void cgerqf_( int* m, int* n, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void zgerqf_( int* m, int* n, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK RQ DECOMPOSITION FUNCTIONS (GERQF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK RQ decomposition functions (gerqf) */
+//@{
+inline void gerqf( int m, int n, float* A, int lda, float* tau,
+ float* work, int lwork, int* info );
+
+inline void gerqf( int m, int n, double* A, int lda, double* tau,
+ double* work, int lwork, int* info );
+
+inline void gerqf( int m, int n, complex<float>* A, int lda, complex<float>* tau,
+ complex<float>* work, int lwork, int* info );
+
+inline void gerqf( int m, int n, complex<double>* A, int lda, complex<double>* tau,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the RQ decomposition of the given dense single precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix RQ decomposition of a general \a m-by-\a n single
+// precision column-major matrix based on the LAPACK sgerqf() function. The resulting decomposition
+// has the form
+
+ \f[ A = R \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(n-k+i+1:n) = 0</tt> and
+// <tt>v(n-k+i) = 1</tt>. <tt>v(1:n-k+i-1)</tt> is stored on exit in <tt>A(m-k+i,1:n-k+i-1)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m <= \a n, the upper triangle of the subarray
+// A(1:m,n-m+1:n) contains the \a m-by-\a m upper triangular matrix \c R and in case \a m >= \a n,
+// the elements on and above the (\a m-\a n)-th subdiagonal contain the \a m-by-\a n upper
+// trapezoidal matrix \c R; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sgerqf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gerqf( int m, int n, float* A, int lda, float* tau,
+ float* work, int lwork, int* info )
+{
+ sgerqf_( &m, &n, A, &lda, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the RQ decomposition of the given dense single precision column-major
+// matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix RQ decomposition of a general \a m-by-\a n double
+// precision column-major matrix based on the LAPACK dgerqf() function. The resulting decomposition
+// has the form
+
+ \f[ A = R \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(n-k+i+1:n) = 0</tt> and
+// <tt>v(n-k+i) = 1</tt>. <tt>v(1:n-k+i-1)</tt> is stored on exit in <tt>A(m-k+i,1:n-k+i-1)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m <= \a n, the upper triangle of the subarray
+// A(1:m,n-m+1:n) contains the \a m-by-\a m upper triangular matrix \c R and in case \a m >= \a n,
+// the elements on and above the (\a m-\a n)-th subdiagonal contain the \a m-by-\a n upper
+// trapezoidal matrix \c R; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dgerqf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gerqf( int m, int n, double* A, int lda, double* tau,
+ double* work, int lwork, int* info )
+{
+ dgerqf_( &m, &n, A, &lda, tau, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the RQ decomposition of the given dense single precision complex
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix RQ decomposition of a general \a m-by-\a n single
+// precision complex column-major matrix based on the LAPACK cgerqf() function. The resulting
+// decomposition has the form
+
+ \f[ A = R \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(n-k+i+1:n) = 0</tt> and
+// <tt>v(n-k+i) = 1</tt>. <tt>v(1:n-k+i-1)</tt> is stored on exit in <tt>A(m-k+i,1:n-k+i-1)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m <= \a n, the upper triangle of the subarray
+// A(1:m,n-m+1:n) contains the \a m-by-\a m upper triangular matrix \c R and in case \a m >= \a n,
+// the elements on and above the (\a m-\a n)-th subdiagonal contain the \a m-by-\a n upper
+// trapezoidal matrix \c R; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cgerqf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gerqf( int m, int n, complex<float>* A, int lda, complex<float>* tau,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cgerqf_( &m, &n, reinterpret_cast<float*>( A ), &lda, reinterpret_cast<float*>( tau ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the RQ decomposition of the given dense double precision complex
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix RQ decomposition of a general \a m-by-\a n double
+// precision complex column-major matrix based on the LAPACK zgerqf() function. The resulting
+// decomposition has the form
+
+ \f[ A = R \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(n-k+i+1:n) = 0</tt> and
+// <tt>v(n-k+i) = 1</tt>. <tt>v(1:n-k+i-1)</tt> is stored on exit in <tt>A(m-k+i,1:n-k+i-1)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m <= \a n, the upper triangle of the subarray
+// A(1:m,n-m+1:n) contains the \a m-by-\a m upper triangular matrix \c R and in case \a m >= \a n,
+// the elements on and above the (\a m-\a n)-th subdiagonal contain the \a m-by-\a n upper
+// trapezoidal matrix \c R; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zgerqf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gerqf( int m, int n, complex<double>* A, int lda, complex<double>* tau,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zgerqf_( &m, &n, reinterpret_cast<double*>( A ), &lda, reinterpret_cast<double*>( tau ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/gesv.h b/src/cpu/blaze/math/lapack/clapack/gesv.h
new file mode 100644
index 00000000..ac61bbed
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/gesv.h
@@ -0,0 +1,294 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/gesv.h
+// \brief Header file for the CLAPACK gesv wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GESV_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GESV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgesv_( int* n, int* nrhs, float* A, int* lda, int* ipiv, float* b, int* ldb, int* info );
+void dgesv_( int* n, int* nrhs, double* A, int* lda, int* ipiv, double* b, int* ldb, int* info );
+void cgesv_( int* n, int* nrhs, float* A, int* lda, int* ipiv, float* b, int* ldb, int* info );
+void zgesv_( int* n, int* nrhs, double* A, int* lda, int* ipiv, double* b, int* ldb, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK GENERAL LINEAR SYSTEM FUNCTIONS (GESV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK general linear system functions (gesv) */
+//@{
+inline void gesv( int n, int nrhs, float* A, int lda, int* ipiv, float* B, int ldb, int* info );
+
+inline void gesv( int n, int nrhs, double* A, int lda, int* ipiv, double* B, int ldb, int* info );
+
+inline void gesv( int n, int nrhs, complex<float>* A, int lda, int* ipiv, complex<float>* B, int ldb, int* info );
+
+inline void gesv( int n, int nrhs, complex<double>* A, int lda, int* ipiv, complex<double>* B, int ldb, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a general single precision linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK sgesv() function to compute the solution to the general system of
+// linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and \a B are n-by-nrhs
+// matrices.
+//
+// The LU decomposition with partial pivoting and row interchanges is used to factor \a A as
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix, and \c U is an upper
+// triangular matrix. The resulting decomposition is stored within \a A: \c L is stored in the
+// lower part of \a A and \c U is stored in the upper part. The unit diagonal elements of \c L
+// are not stored. The factored form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor U(i,i) is exactly
+// singular the solution could not be computed.
+//
+// For more information on the sgesv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gesv( int n, int nrhs, float* A, int lda, int* ipiv, float* B, int ldb, int* info )
+{
+ sgesv_( &n, &nrhs, A, &lda, ipiv, B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a general double precision linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK dgesv() function to compute the solution to the general system of
+// linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and \a B are n-by-nrhs
+// matrices.
+//
+// The LU decomposition with partial pivoting and row interchanges is used to factor \a A as
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix, and \c U is an upper
+// triangular matrix. The resulting decomposition is stored within \a A: \c L is stored in the
+// lower part of \a A and \c U is stored in the upper part. The unit diagonal elements of \c L
+// are not stored. The factored form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor U(i,i) is exactly
+// singular the solution could not be computed.
+//
+// For more information on the dgesv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gesv( int n, int nrhs, double* A, int lda, int* ipiv, double* B, int ldb, int* info )
+{
+ dgesv_( &n, &nrhs, A, &lda, ipiv, B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a general single precision complex linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK cgesv() function to compute the solution to the general system of
+// linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and \a B are n-by-nrhs
+// matrices.
+//
+// The LU decomposition with partial pivoting and row interchanges is used to factor \a A as
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix, and \c U is an upper
+// triangular matrix. The resulting decomposition is stored within \a A: \c L is stored in the
+// lower part of \a A and \c U is stored in the upper part. The unit diagonal elements of \c L
+// are not stored. The factored form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor U(i,i) is exactly
+// singular the solution could not be computed.
+//
+// For more information on the cgesv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gesv( int n, int nrhs, complex<float>* A, int lda, int* ipiv, complex<float>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cgesv_( &n, &nrhs, reinterpret_cast<float*>( A ), &lda, ipiv,
+ reinterpret_cast<float*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a general double precision complex linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK zgesv() function to compute the solution to the general system of
+// linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and \a B are n-by-nrhs
+// matrices.
+//
+// The LU decomposition with partial pivoting and row interchanges is used to factor \a A as
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix, and \c U is an upper
+// triangular matrix. The resulting decomposition is stored within \a A: \c L is stored in the
+// lower part of \a A and \c U is stored in the upper part. The unit diagonal elements of \c L
+// are not stored. The factored form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor U(i,i) is exactly
+// singular the solution could not be computed.
+//
+// For more information on the zgesv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void gesv( int n, int nrhs, complex<double>* A, int lda, int* ipiv, complex<double>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zgesv_( &n, &nrhs, reinterpret_cast<double*>( A ), &lda, ipiv,
+ reinterpret_cast<double*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/getrf.h b/src/cpu/blaze/math/lapack/clapack/getrf.h
new file mode 100644
index 00000000..c6e1fd7e
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/getrf.h
@@ -0,0 +1,272 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/getrf.h
+// \brief Header file for the CLAPACK getrf wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GETRF_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GETRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgetrf_( int* m, int* n, float* A, int* lda, int* ipiv, int* info );
+void dgetrf_( int* m, int* n, double* A, int* lda, int* ipiv, int* info );
+void cgetrf_( int* m, int* n, float* A, int* lda, int* ipiv, int* info );
+void zgetrf_( int* m, int* n, double* A, int* lda, int* ipiv, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LU DECOMPOSITION FUNCTIONS (GETRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LU decomposition functions (getrf) */
+//@{
+inline void getrf( int m, int n, float* A, int lda, int* ipiv, int* info );
+
+inline void getrf( int m, int n, double* A, int lda, int* ipiv, int* info );
+
+inline void getrf( int m, int n, complex<float>* A, int lda, int* ipiv, int* info );
+
+inline void getrf( int m, int n, complex<double>* A, int lda, int* ipiv, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LU decomposition of the given dense general single precision
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix LU decomposition of a general m-by-n single precision
+// column-major matrix based on the LAPACK sgetrf() function, which uses partial pivoting with row
+// interchanges. The resulting decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix (lower trapezoidal if
+// \a m > \a n), and \c U is an upper triangular matrix (upper trapezoidal if \a m < \a n). The
+// resulting decomposition is stored within the matrix \a A: \c L is stored in the lower part of
+// \a A and \c U is stored in the upper part. The unit diagonal elements of \c L are not stored.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but the factor U(i,i) is singular.
+//
+// For more information on the sgetrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getrf( int m, int n, float* A, int lda, int* ipiv, int* info )
+{
+ sgetrf_( &m, &n, A, &lda, ipiv, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LU decomposition of the given dense general double precision
+// column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix LU decomposition of a general m-by-n double precision
+// column-major matrix based on the LAPACK dgetrf() function, which uses partial pivoting with row
+// interchanges. The resulting decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix (lower trapezoidal if
+// \a m > \a n), and \c U is an upper triangular matrix (upper trapezoidal if \a m < \a n). The
+// resulting decomposition is stored within the matrix \a A: \c L is stored in the lower part of
+// \a A and \c U is stored in the upper part. The unit diagonal elements of \c L are not stored.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but the factor U(i,i) is singular.
+//
+// For more information on the dgetrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getrf( int m, int n, double* A, int lda, int* ipiv, int* info )
+{
+ dgetrf_( &m, &n, A, &lda, ipiv, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LU decomposition of the given dense general single precision
+// complex column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix LU decomposition of a general m-by-n single precision
+// complex column-major matrix based on the LAPACK cgetrf() function, which uses partial pivoting
+// with row interchanges. The resulting decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix (lower trapezoidal if
+// \a m > \a n), and \c U is an upper triangular matrix (upper trapezoidal if \a m < \a n). The
+// resulting decomposition is stored within the matrix \a A: \c L is stored in the lower part of
+// \a A and \c U is stored in the upper part. The unit diagonal elements of \c L are not stored.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but the factor U(i,i) is singular.
+//
+// For more information on the cgetrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getrf( int m, int n, complex<float>* A, int lda, int* ipiv, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cgetrf_( &m, &n, reinterpret_cast<float*>( A ), &lda, ipiv, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LU decomposition of the given dense general double precision
+// complex column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix LU decomposition of a general m-by-n double precision
+// complex column-major matrix based on the LAPACK zgetrf() function, which uses partial pivoting
+// with row interchanges. The resulting decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix (lower trapezoidal if
+// \a m > \a n), and \c U is an upper triangular matrix (upper trapezoidal if \a m < \a n). The
+// resulting decomposition is stored within the matrix \a A: \c L is stored in the lower part of
+// \a A and \c U is stored in the upper part. The unit diagonal elements of \c L are not stored.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but the factor U(i,i) is singular.
+//
+// For more information on the zgetrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getrf( int m, int n, complex<double>* A, int lda, int* ipiv, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zgetrf_( &m, &n, reinterpret_cast<double*>( A ), &lda, ipiv, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/getri.h b/src/cpu/blaze/math/lapack/clapack/getri.h
new file mode 100644
index 00000000..af2d65c7
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/getri.h
@@ -0,0 +1,270 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/getri.h
+// \brief Header file for the CLAPACK getri wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GETRI_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GETRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgetri_( int* n, float* A, int* lda, int* ipiv, float* work, int* lwork, int* info );
+void dgetri_( int* n, double* A, int* lda, int* ipiv, double* work, int* lwork, int* info );
+void cgetri_( int* n, float* A, int* lda, int* ipiv, float* work, int* lwork, int* info );
+void zgetri_( int* n, double* A, int* lda, int* ipiv, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LU-BASED INVERSION FUNCTIONS (GETRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LU-based inversion functions (getri) */
+//@{
+inline void getri( int n, float* A, int lda, const int* ipiv, float* work, int lwork, int* info );
+
+inline void getri( int n, double* A, int lda, const int* ipiv, double* work, int lwork, int* info );
+
+inline void getri( int n, complex<float>* A, int lda, const int* ipiv,
+ complex<float>* work, int lwork, int* info );
+
+inline void getri( int n, complex<double>* A, int lda, const int* ipiv,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense general single precision column-major
+// square matrix.
+// \ingroup lapack_inversion
+//
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK sgetri() function for
+// single precision column-major matrices that have already been factorized by the sgetrf()
+// function. The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the inversion could not be computed since U(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= N*NB, where NB is the
+// optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a workspace
+// query is assumed. The function only calculates the optimal size of the \a work array and
+// returns this value as the first entry of the \a work array.
+//
+// For more information on the sgetri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getri( int n, float* A, int lda, const int* ipiv, float* work, int lwork, int* info )
+{
+ sgetri_( &n, A, &lda, const_cast<int*>( ipiv ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense general double precision column-major
+// square matrix.
+// \ingroup lapack_inversion
+//
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK dgetri() function for
+// double precision column-major matrices that have already been factorized by the dgetrf()
+// function. The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the inversion could not be computed since U(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= N*NB, where NB is the
+// optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a workspace
+// query is assumed. The function only calculates the optimal size of the \a work array and
+// returns this value as the first entry of the \a work array.
+//
+// For more information on the sgetri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getri( int n, double* A, int lda, const int* ipiv, double* work, int lwork, int* info )
+{
+ dgetri_( &n, A, &lda, const_cast<int*>( ipiv ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense general single precision complex
+// column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK cgetri() function for
+// single precision complex column-major matrices that have already been factorized by the
+// cgetrf() function. The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the inversion could not be computed since U(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= N*NB, where NB is the
+// optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a workspace
+// query is assumed. The function only calculates the optimal size of the \a work array and
+// returns this value as the first entry of the \a work array.
+//
+// For more information on the sgetri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getri( int n, complex<float>* A, int lda, const int* ipiv,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cgetri_( &n, reinterpret_cast<float*>( A ), &lda, const_cast<int*>( ipiv ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense general double precision complex
+// column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK cgetri() function for
+// double precision complex column-major matrices that have already been factorized by the
+// zgetrf() function. The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the inversion could not be computed since U(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= N*NB, where NB is the
+// optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a workspace
+// query is assumed. The function only calculates the optimal size of the \a work array and
+// returns this value as the first entry of the \a work array.
+//
+// For more information on the sgetri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getri( int n, complex<double>* A, int lda, const int* ipiv,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zgetri_( &n, reinterpret_cast<double*>( A ), &lda, const_cast<int*>( ipiv ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/getrs.h b/src/cpu/blaze/math/lapack/clapack/getrs.h
new file mode 100644
index 00000000..a217ae74
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/getrs.h
@@ -0,0 +1,288 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/getrs.h
+// \brief Header file for the CLAPACK getrs wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_GETRS_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_GETRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sgetrs_( char* trans, int* n, int* nrhs, float* A, int* lda, int* ipiv, float* B, int* ldb, int* info );
+void dgetrs_( char* trans, int* n, int* nrhs, double* A, int* lda, int* ipiv, double* B, int* ldb, int* info );
+void cgetrs_( char* trans, int* n, int* nrhs, float* A, int* lda, int* ipiv, float* B, int* ldb, int* info );
+void zgetrs_( char* trans, int* n, int* nrhs, double* A, int* lda, int* ipiv, double* B, int* ldb, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LU-BASED SUBSTITUTION FUNCTIONS (GETRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LU-based substitution functions (getrs) */
+//@{
+inline void getrs( char trans, int n, int nrhs, const float* A, int lda, const int* ipiv,
+ float* B, int ldb, int* info );
+
+inline void getrs( char trans, int n, int nrhs, const double* A, int lda, const int* ipiv,
+ double* B, int ldb, int* info );
+
+inline void getrs( char trans, int n, int nrhs, const complex<float>* A, int lda,
+ const int* ipiv, complex<float>* B, int ldb, int* info );
+
+inline void getrs( char trans, int n, int nrhs, const complex<double>* A, int lda,
+ const int* ipiv, complex<double>* B, int ldb, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a general single precision linear
+// system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK sgetrs() function to perform the substitution step to compute
+// the solution to the general system of linear equations \f$ A*X=B \f$, \f$ A^{T}*X=B \f$, or
+// \f$ A^{H}*X=B \f$, where \a A is a n-by-n matrix that has already been factorized by the
+// sgetrf() function and \a X and \a B are column-major n-by-nrhs matrices. The \a trans argument
+// specifies the form of the linear system of equations:
+//
+// - 'N': \f$ A*X=B \f$ (no transpose)
+// - 'T': \f$ A^{T}*X=B \f$ (transpose)
+// - 'C': \f$ A^{H}*X=B \f$ (conjugate transpose)
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the sgetrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getrs( char trans, int n, int nrhs, const float* A, int lda,
+ const int* ipiv, float* B, int ldb, int* info )
+{
+ sgetrs_( &trans, &n, &nrhs, const_cast<float*>( A ), &lda,
+ const_cast<int*>( ipiv ), B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a general double precision linear
+// system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK dgetrs() function to perform the substitution step to compute
+// the solution to the general system of linear equations \f$ A*X=B \f$, \f$ A^{T}*X=B \f$, or
+// \f$ A^{H}*X=B \f$, where \a A is a n-by-n matrix that has already been factorized by the
+// dgetrf() function and \a X and \a B are column-major n-by-nrhs matrices. The \a trans argument
+// specifies the form of the linear system of equations:
+//
+// - 'N': \f$ A*X=B \f$ (no transpose)
+// - 'T': \f$ A^{T}*X=B \f$ (transpose)
+// - 'C': \f$ A^{H}*X=B \f$ (conjugate transpose)
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the dgetrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getrs( char trans, int n, int nrhs, const double* A, int lda,
+ const int* ipiv, double* B, int ldb, int* info )
+{
+ dgetrs_( &trans, &n, &nrhs, const_cast<double*>( A ), &lda,
+ const_cast<int*>( ipiv ), B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a general single precision complex
+// linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK cgetrs() function to perform the substitution step to compute
+// the solution to the general system of linear equations \f$ A*X=B \f$, \f$ A^{T}*X=B \f$, or
+// \f$ A^{H}*X=B \f$, where \a A is a n-by-n matrix that has already been factorized by the
+// cgetrf() function and \a X and \a B are column-major n-by-nrhs matrices. The \a trans argument
+// specifies the form of the linear system of equations:
+//
+// - 'N': \f$ A*X=B \f$ (no transpose)
+// - 'T': \f$ A^{T}*X=B \f$ (transpose)
+// - 'C': \f$ A^{H}*X=B \f$ (conjugate transpose)
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the cgetrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getrs( char trans, int n, int nrhs, const complex<float>* A, int lda,
+ const int* ipiv, complex<float>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cgetrs_( &trans, &n, &nrhs, const_cast<float*>( reinterpret_cast<const float*>( A ) ),
+ &lda, const_cast<int*>( ipiv ), reinterpret_cast<float*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a general double precision complex
+// linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK zgetrs() function to perform the substitution step to compute
+// the solution to the general system of linear equations \f$ A*X=B \f$, \f$ A^{T}*X=B \f$, or
+// \f$ A^{H}*X=B \f$, where \a A is a n-by-n matrix that has already been factorized by the
+// zgetrf() function and \a X and \a B are column-major n-by-nrhs matrices. The \a trans argument
+// specifies the form of the linear system of equations:
+//
+// - 'N': \f$ A*X=B \f$ (no transpose)
+// - 'T': \f$ A^{T}*X=B \f$ (transpose)
+// - 'C': \f$ A^{H}*X=B \f$ (conjugate transpose)
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the zgetrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void getrs( char trans, int n, int nrhs, const complex<double>* A, int lda,
+ const int* ipiv, complex<double>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zgetrs_( &trans, &n, &nrhs, const_cast<double*>( reinterpret_cast<const double*>( A ) ),
+ &lda, const_cast<int*>( ipiv ), reinterpret_cast<double*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/hesv.h b/src/cpu/blaze/math/lapack/clapack/hesv.h
new file mode 100644
index 00000000..2a3bf1ad
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/hesv.h
@@ -0,0 +1,206 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/hesv.h
+// \brief Header file for the CLAPACK hesv wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_HESV_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_HESV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void chesv_( char* uplo, int* n, int* nrhs, float* A, int* lda, int* ipiv, float* b, int* ldb, float* work, int* lwork, int* info );
+void zhesv_( char* uplo, int* n, int* nrhs, double* A, int* lda, int* ipiv, double* b, int* ldb, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK HERMITIAN INDEFINITE LINEAR SYSTEM FUNCTIONS (HESV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK Hermitian indefinite linear system functions (hesv) */
+//@{
+inline void hesv( char uplo, int n, int nrhs, complex<float>* A, int lda, int* ipiv,
+ complex<float>* B, int ldb, complex<float>* work, int lwork, int* info );
+
+inline void hesv( char uplo, int n, int nrhs, complex<double>* A, int lda, int* ipiv,
+ complex<double>* B, int ldb, complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a Hermitian indefinite single precision complex linear system
+// of equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK chesv() function to compute the solution to the Hermitian
+// indefinite system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and
+// \a B are n-by-nrhs matrices.
+//
+// The Bunch-Kaufman decomposition is used to factor \a A as
+
+ \f[ A = U D U^{H} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor D(i,i) is exactly
+// zero the solution could not be computed.
+//
+// For more information on the chesv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void hesv( char uplo, int n, int nrhs, complex<float>* A, int lda, int* ipiv,
+ complex<float>* B, int ldb, complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ chesv_( &uplo, &n, &nrhs, reinterpret_cast<float*>( A ), &lda, ipiv,
+ reinterpret_cast<float*>( B ), &ldb, reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a Hermitian indefinite double precision complex linear system
+// of equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK zhesv() function to compute the solution to the Hermitian
+// indefinite system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and
+// \a B are n-by-nrhs matrices.
+//
+// The Bunch-Kaufman decomposition is used to factor \a A as
+
+ \f[ A = U D U^{H} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor D(i,i) is exactly
+// zero the solution could not be computed.
+//
+// For more information on the zhesv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void hesv( char uplo, int n, int nrhs, complex<double>* A, int lda, int* ipiv,
+ complex<double>* B, int ldb, complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zhesv_( &uplo, &n, &nrhs, reinterpret_cast<double*>( A ), &lda, ipiv,
+ reinterpret_cast<double*>( B ), &ldb, reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/hetrf.h b/src/cpu/blaze/math/lapack/clapack/hetrf.h
new file mode 100644
index 00000000..ce00d648
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/hetrf.h
@@ -0,0 +1,204 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/hetrf.h
+// \brief Header file for the CLAPACK hetrf wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_HETRF_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_HETRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void chetrf_( char* uplo, int* n, float* A, int* lda, int* ipiv, float* work, int* lwork, int* info );
+void zhetrf_( char* uplo, int* n, double* A, int* lda, int* ipiv, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LDLH DECOMPOSITION FUNCTIONS (HETRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLH decomposition functions (hetrf) */
+//@{
+inline void hetrf( char uplo, int n, complex<float>* A, int lda, int* ipiv,
+ complex<float>* work, int lwork, int* info );
+
+inline void hetrf( char uplo, int n, complex<double>* A, int lda, int* ipiv,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the decomposition of the given dense Hermitian indefinite
+// single precision complex column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the Hermitian matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix decomposition of a Hermitian indefinite single precision
+// column-major matrix based on the LAPACK chetrf() function, which uses the Bunch-Kaufman diagonal
+// pivoting method. The decomposition has the form
+
+ \f[ A = U D U^{H} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but D(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= \a n*NB, where NB
+// is the optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a
+// workspace query is assumed. The function only calculates the optimal size of the \a work
+// array and returns this value as the first entry of the \a work array.
+//
+// For more information on the chetrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void hetrf( char uplo, int n, complex<float>* A, int lda, int* ipiv,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ chetrf_( &uplo, &n, reinterpret_cast<float*>( A ), &lda, ipiv,
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the decomposition of the given dense Hermitian indefinite
+// double precision complex column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the Hermitian matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix decomposition of a Hermitian indefinite double precision
+// column-major matrix based on the LAPACK zhetrf() function, which uses the Bunch-Kaufman diagonal
+// pivoting method. The decomposition has the form
+
+ \f[ A = U D U^{H} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but D(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= \a n*NB, where NB
+// is the optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a
+// workspace query is assumed. The function only calculates the optimal size of the \a work
+// array and returns this value as the first entry of the \a work array.
+//
+// For more information on the zhetrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void hetrf( char uplo, int n, complex<double>* A, int lda, int* ipiv,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zhetrf_( &uplo, &n, reinterpret_cast<double*>( A ), &lda, ipiv,
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/hetri.h b/src/cpu/blaze/math/lapack/clapack/hetri.h
new file mode 100644
index 00000000..679c57e7
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/hetri.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/hetri.h
+// \brief Header file for the CLAPACK hetri wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_HETRI_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_HETRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void chetri_( char* uplo, int* n, float* A, int* lda, int* ipiv, float* work, int* info );
+void zhetri_( char* uplo, int* n, double* A, int* lda, int* ipiv, double* work, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LDLH-BASED INVERSION FUNCTIONS (HETRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLH-based inversion functions (hetri) */
+//@{
+inline void hetri( char uplo, int n, complex<float>* A, int lda,
+ const int* ipiv, complex<float>* work, int* info );
+
+inline void hetri( char uplo, int n, complex<double>* A, int lda,
+ const int* ipiv, complex<double>* work, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense Hermitian indefinite single precision
+// complex column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param n The number of rows/columns of the Hermitian matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array of size \a n.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK chetri() function for
+// Hermitian indefinite single precision complex column-major matrices that have already been
+// factorized by the chetrf() function.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element D(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the chetri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void hetri( char uplo, int n, complex<float>* A, int lda,
+ const int* ipiv, complex<float>* work, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ chetri_( &uplo, &n, reinterpret_cast<float*>( A ), &lda,
+ const_cast<int*>( ipiv ), reinterpret_cast<float*>( work ), info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense Hermitian indefinite double precision
+// complex column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param n The number of rows/columns of the Hermitian matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array of size \a n.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK zhetri() function for
+// Hermitian indefinite double precision complex column-major matrices that have already been
+// factorized by the zhetrf() function.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element D(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the zhetri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void hetri( char uplo, int n, complex<double>* A, int lda,
+ const int* ipiv, complex<double>* work, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zhetri_( &uplo, &n, reinterpret_cast<double*>( A ), &lda,
+ const_cast<int*>( ipiv ), reinterpret_cast<double*>( work ), info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/hetrs.h b/src/cpu/blaze/math/lapack/clapack/hetrs.h
new file mode 100644
index 00000000..f7a7add0
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/hetrs.h
@@ -0,0 +1,176 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/hetrs.h
+// \brief Header file for the CLAPACK hetrs wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_HETRS_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_HETRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void chetrs_( char* uplo, int* n, int* nrhs, float* A, int* lda, int* ipiv, float* B, int* ldb, int* info );
+void zhetrs_( char* uplo, int* n, int* nrhs, double* A, int* lda, int* ipiv, double* B, int* ldb, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LDLH-BASED SUBSTITUTION FUNCTIONS (HETRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLH-based substitution functions (hetrs) */
+//@{
+inline void hetrs( char uplo, int n, int nrhs, const complex<float>* A, int lda, const int* ipiv,
+ complex<float>* B, int ldb, int* info );
+
+inline void hetrs( char uplo, int n, int nrhs, const complex<double>* A, int lda, const int* ipiv,
+ complex<double>* B, int ldb, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite single
+// precision complex linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the single precision complex column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK chetrs() function to perform the substitution step to compute
+// the solution to the symmetric indefinite system of linear equations \f$ A*X=B \f$, where \a A
+// is a n-by-n matrix that has already been factorized by the chetrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the chetrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void hetrs( char uplo, int n, int nrhs, const complex<float>* A, int lda,
+ const int* ipiv, complex<float>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ chetrs_( &uplo, &n, &nrhs, const_cast<float*>( reinterpret_cast<const float*>( A ) ),
+ &lda, const_cast<int*>( ipiv ), reinterpret_cast<float*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite double
+// precision complex linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the double precision complex column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK zhetrs() function to perform the substitution step to compute
+// the solution to the symmetric indefinite system of linear equations \f$ A*X=B \f$, where \a A
+// is a n-by-n matrix that has already been factorized by the zhetrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the zhetrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void hetrs( char uplo, int n, int nrhs, const complex<double>* A, int lda,
+ const int* ipiv, complex<double>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zhetrs_( &uplo, &n, &nrhs, const_cast<double*>( reinterpret_cast<const double*>( A ) ),
+ &lda, const_cast<int*>( ipiv ), reinterpret_cast<double*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/orglq.h b/src/cpu/blaze/math/lapack/clapack/orglq.h
new file mode 100644
index 00000000..c17f2de6
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/orglq.h
@@ -0,0 +1,162 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/orglq.h
+// \brief Header file for the CLAPACK orglq wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_ORGLQ_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_ORGLQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sorglq_( int* m, int* n, int* k, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void dorglq_( int* m, int* n, int* k, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A LQ DECOMPOSITION (ORGLQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a LQ decomposition (orglq) */
+//@{
+inline void orglq( int m, int n, int k, float* A, int lda, const float* tau,
+ float* work, int lwork, int* info );
+
+inline void orglq( int m, int n, int k, double* A, int lda, const double* tau,
+ double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a LQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..n)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..m)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a LQ decomposition based on
+// the LAPACK sorglq() function for single precision column-major matrices that have already been
+// factorized by the sgelqf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sorglq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void orglq( int m, int n, int k, float* A, int lda, const float* tau, float* work, int lwork, int* info )
+{
+ sorglq_( &m, &n, &k, A, &lda, const_cast<float*>( tau ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a LQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..n)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..m)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a LQ decomposition based on
+// the LAPACK dorglq() function for double precision column-major matrices that have already been
+// factorized by the dgelqf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dorglq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void orglq( int m, int n, int k, double* A, int lda, const double* tau, double* work, int lwork, int* info )
+{
+ dorglq_( &m, &n, &k, A, &lda, const_cast<double*>( tau ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/orgql.h b/src/cpu/blaze/math/lapack/clapack/orgql.h
new file mode 100644
index 00000000..7455a2bb
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/orgql.h
@@ -0,0 +1,162 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/orgql.h
+// \brief Header file for the CLAPACK orgql wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_ORGQL_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_ORGQL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sorgql_( int* m, int* n, int* k, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void dorgql_( int* m, int* n, int* k, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A QL DECOMPOSITION (ORGQL)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a QL decomposition (orgql) */
+//@{
+inline void orgql( int m, int n, int k, float* A, int lda, const float* tau,
+ float* work, int lwork, int* info );
+
+inline void orgql( int m, int n, int k, double* A, int lda, const double* tau,
+ double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QL decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..m)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..n)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a QL decomposition based on
+// the LAPACK sorgql() function for single precision column-major matrices that have already been
+// factorized by the sgeqlf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sorgql() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void orgql( int m, int n, int k, float* A, int lda, const float* tau, float* work, int lwork, int* info )
+{
+ sorgql_( &m, &n, &k, A, &lda, const_cast<float*>( tau ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QL decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..m)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..n)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a QL decomposition based on
+// the LAPACK dorgql() function for double precision column-major matrices that have already been
+// factorized by the dgeqlf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dorgql() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void orgql( int m, int n, int k, double* A, int lda, const double* tau, double* work, int lwork, int* info )
+{
+ dorgql_( &m, &n, &k, A, &lda, const_cast<double*>( tau ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/orgqr.h b/src/cpu/blaze/math/lapack/clapack/orgqr.h
new file mode 100644
index 00000000..5354d18f
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/orgqr.h
@@ -0,0 +1,162 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/orgqr.h
+// \brief Header file for the CLAPACK orgqr wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_ORGQR_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_ORGQR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sorgqr_( int* m, int* n, int* k, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void dorgqr_( int* m, int* n, int* k, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A QR DECOMPOSITION (ORGQR)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a QR decomposition (orgqr) */
+//@{
+inline void orgqr( int m, int n, int k, float* A, int lda, const float* tau,
+ float* work, int lwork, int* info );
+
+inline void orgqr( int m, int n, int k, double* A, int lda, const double* tau,
+ double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QR decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..m)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..n)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a QR decomposition based on
+// the LAPACK sorgqr() function for single precision column-major matrices that have already been
+// factorized by the sgeqrf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sorgqr() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void orgqr( int m, int n, int k, float* A, int lda, const float* tau, float* work, int lwork, int* info )
+{
+ sorgqr_( &m, &n, &k, A, &lda, const_cast<float*>( tau ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QR decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..m)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..n)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a QR decomposition based on
+// the LAPACK dorgqr() function for double precision column-major matrices that have already been
+// factorized by the dgeqrf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dorgqr() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void orgqr( int m, int n, int k, double* A, int lda, const double* tau, double* work, int lwork, int* info )
+{
+ dorgqr_( &m, &n, &k, A, &lda, const_cast<double*>( tau ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/orgrq.h b/src/cpu/blaze/math/lapack/clapack/orgrq.h
new file mode 100644
index 00000000..6bbb0171
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/orgrq.h
@@ -0,0 +1,162 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/orgrq.h
+// \brief Header file for the CLAPACK orgrq wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_ORGRQ_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_ORGRQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sorgrq_( int* m, int* n, int* k, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void dorgrq_( int* m, int* n, int* k, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A RQ DECOMPOSITION (ORGRQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a RQ decomposition (orgrq) */
+//@{
+inline void orgrq( int m, int n, int k, float* A, int lda, const float* tau,
+ float* work, int lwork, int* info );
+
+inline void orgrq( int m, int n, int k, double* A, int lda, const double* tau,
+ double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a RQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..n)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..m)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a RQ decomposition based on
+// the LAPACK sorgrq() function for single precision column-major matrices that have already been
+// factorized by the sgerqf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sorgrq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void orgrq( int m, int n, int k, float* A, int lda, const float* tau, float* work, int lwork, int* info )
+{
+ sorgrq_( &m, &n, &k, A, &lda, const_cast<float*>( tau ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a RQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..n)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..m)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a RQ decomposition based on
+// the LAPACK dorgrq() function for double precision column-major matrices that have already been
+// factorized by the dgerqf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dorgrq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void orgrq( int m, int n, int k, double* A, int lda, const double* tau, double* work, int lwork, int* info )
+{
+ dorgrq_( &m, &n, &k, A, &lda, const_cast<double*>( tau ), work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/ormlq.h b/src/cpu/blaze/math/lapack/clapack/ormlq.h
new file mode 100644
index 00000000..f3c8aa1a
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/ormlq.h
@@ -0,0 +1,190 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/ormlq.h
+// \brief Header file for the CLAPACK ormlq wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_ORMLQ_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_ORMLQ_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sormlq_( char* side, char* trans, int* m, int* n, int* k, float* A, int* lda, float* tau, float* C, int* ldc, float* work, int* lwork, int* info );
+void dormlq_( char* side, char* trans, int* m, int* n, int* k, double* A, int* lda, double* tau, double* C, int* ldc, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A LQ DECOMPOSITION WITH A MATRIX (ORMLQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a LQ decomposition with a matrix (ormlq) */
+//@{
+inline void ormlq( char side, char trans, int m, int n, int k, const float* A, int lda,
+ const float* tau, float* C, int ldc, float* work, int lwork, int* info );
+
+inline void ormlq( char side, char trans, int m, int n, int k, const double* A, int lda,
+ const double* tau, double* C, int ldc, double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the single precision Q from a LQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the LQ decomposed single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the single precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the LQ decomposition of the sgelqf()
+// function with the given general single precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sormlq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ormlq( char side, char trans, int m, int n, int k, const float* A, int lda,
+ const float* tau, float* C, int ldc, float* work, int lwork, int* info )
+{
+ sormlq_( &side, &trans, &m, &n, &k, const_cast<float*>( A ), &lda,
+ const_cast<float*>( tau ), C, &ldc, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a LQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the LQ decomposed double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the double precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the LQ decomposition of the sgelqf()
+// function with the given general double precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dormlq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ormlq( char side, char trans, int m, int n, int k, const double* A, int lda,
+ const double* tau, double* C, int ldc, double* work, int lwork, int* info )
+{
+ dormlq_( &side, &trans, &m, &n, &k, const_cast<double*>( A ), &lda,
+ const_cast<double*>( tau ), C, &ldc, work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/ormql.h b/src/cpu/blaze/math/lapack/clapack/ormql.h
new file mode 100644
index 00000000..168d617c
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/ormql.h
@@ -0,0 +1,190 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/ormql.h
+// \brief Header file for the CLAPACK ormql wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_ORMQL_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_ORMQL_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sormql_( char* side, char* trans, int* m, int* n, int* k, float* A, int* lda, float* tau, float* C, int* ldc, float* work, int* lwork, int* info );
+void dormql_( char* side, char* trans, int* m, int* n, int* k, double* A, int* lda, double* tau, double* C, int* ldc, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A QL DECOMPOSITION WITH A MATRIX (ORMQL)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a QL decomposition with a matrix (ormql) */
+//@{
+inline void ormql( char side, char trans, int m, int n, int k, const float* A, int lda,
+ const float* tau, float* C, int ldc, float* work, int lwork, int* info );
+
+inline void ormql( char side, char trans, int m, int n, int k, const double* A, int lda,
+ const double* tau, double* C, int ldc, double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the single precision Q from a QL decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the QL decomposed single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the single precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the QL decomposition of the sgeqlf()
+// function with the given general single precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sormql() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ormql( char side, char trans, int m, int n, int k, const float* A, int lda,
+ const float* tau, float* C, int ldc, float* work, int lwork, int* info )
+{
+ sormql_( &side, &trans, &m, &n, &k, const_cast<float*>( A ), &lda,
+ const_cast<float*>( tau ), C, &ldc, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a QL decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the QL decomposed double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the double precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the QL decomposition of the sgeqlf()
+// function with the given general double precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dormql() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ormql( char side, char trans, int m, int n, int k, const double* A, int lda,
+ const double* tau, double* C, int ldc, double* work, int lwork, int* info )
+{
+ dormql_( &side, &trans, &m, &n, &k, const_cast<double*>( A ), &lda,
+ const_cast<double*>( tau ), C, &ldc, work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/ormqr.h b/src/cpu/blaze/math/lapack/clapack/ormqr.h
new file mode 100644
index 00000000..dd234428
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/ormqr.h
@@ -0,0 +1,190 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/ormqr.h
+// \brief Header file for the CLAPACK ormqr wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_ORMQR_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_ORMQR_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sormqr_( char* side, char* trans, int* m, int* n, int* k, float* A, int* lda, float* tau, float* C, int* ldc, float* work, int* lwork, int* info );
+void dormqr_( char* side, char* trans, int* m, int* n, int* k, double* A, int* lda, double* tau, double* C, int* ldc, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A QR DECOMPOSITION WITH A MATRIX (ORMQR)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a QR decomposition with a matrix (ormqr) */
+//@{
+inline void ormqr( char side, char trans, int m, int n, int k, const float* A, int lda,
+ const float* tau, float* C, int ldc, float* work, int lwork, int* info );
+
+inline void ormqr( char side, char trans, int m, int n, int k, const double* A, int lda,
+ const double* tau, double* C, int ldc, double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the single precision Q from a QR decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the QR decomposed single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the single precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the QR decomposition of the sgeqrf()
+// function with the given general single precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sormqr() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ormqr( char side, char trans, int m, int n, int k, const float* A, int lda,
+ const float* tau, float* C, int ldc, float* work, int lwork, int* info )
+{
+ sormqr_( &side, &trans, &m, &n, &k, const_cast<float*>( A ), &lda,
+ const_cast<float*>( tau ), C, &ldc, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a QR decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the QR decomposed double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the double precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the QR decomposition of the sgeqrf()
+// function with the given general double precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dormqr() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ormqr( char side, char trans, int m, int n, int k, const double* A, int lda,
+ const double* tau, double* C, int ldc, double* work, int lwork, int* info )
+{
+ dormqr_( &side, &trans, &m, &n, &k, const_cast<double*>( A ), &lda,
+ const_cast<double*>( tau ), C, &ldc, work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/ormrq.h b/src/cpu/blaze/math/lapack/clapack/ormrq.h
new file mode 100644
index 00000000..c4faf9a7
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/ormrq.h
@@ -0,0 +1,190 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/ormrq.h
+// \brief Header file for the CLAPACK ormrq wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_ORMRQ_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_ORMRQ_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sormrq_( char* side, char* trans, int* m, int* n, int* k, float* A, int* lda, float* tau, float* C, int* ldc, float* work, int* lwork, int* info );
+void dormrq_( char* side, char* trans, int* m, int* n, int* k, double* A, int* lda, double* tau, double* C, int* ldc, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A RQ DECOMPOSITION WITH A MATRIX (ORMRQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a RQ decomposition with a matrix (ormrq) */
+//@{
+inline void ormrq( char side, char trans, int m, int n, int k, const float* A, int lda,
+ const float* tau, float* C, int ldc, float* work, int lwork, int* info );
+
+inline void ormrq( char side, char trans, int m, int n, int k, const double* A, int lda,
+ const double* tau, double* C, int ldc, double* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the single precision Q from a RQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the RQ decomposed single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the single precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the RQ decomposition of the sgerqf()
+// function with the given general single precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the sormrq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ormrq( char side, char trans, int m, int n, int k, const float* A, int lda,
+ const float* tau, float* C, int ldc, float* work, int lwork, int* info )
+{
+ sormrq_( &side, &trans, &m, &n, &k, const_cast<float*>( A ), &lda,
+ const_cast<float*>( tau ), C, &ldc, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a RQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the RQ decomposed double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the double precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the RQ decomposition of the sgerqf()
+// function with the given general double precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the dormrq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ormrq( char side, char trans, int m, int n, int k, const double* A, int lda,
+ const double* tau, double* C, int ldc, double* work, int lwork, int* info )
+{
+ dormrq_( &side, &trans, &m, &n, &k, const_cast<double*>( A ), &lda,
+ const_cast<double*>( tau ), C, &ldc, work, &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/posv.h b/src/cpu/blaze/math/lapack/clapack/posv.h
new file mode 100644
index 00000000..70db214c
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/posv.h
@@ -0,0 +1,302 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/posv.h
+// \brief Header file for the CLAPACK posv wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_POSV_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_POSV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void sposv_( char* uplo, int* n, int* nrhs, float* A, int* lda, float* b, int* ldb, int* info );
+void dposv_( char* uplo, int* n, int* nrhs, double* A, int* lda, double* b, int* ldb, int* info );
+void cposv_( char* uplo, int* n, int* nrhs, float* A, int* lda, float* b, int* ldb, int* info );
+void zposv_( char* uplo, int* n, int* nrhs, double* A, int* lda, double* b, int* ldb, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK POSITIVE DEFINITE LINEAR SYSTEM FUNCTIONS (POSV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK positive definite linear system functions (posv) */
+//@{
+inline void posv( char uplo, int n, int nrhs, float* A, int lda, float* B, int ldb, int* info );
+
+inline void posv( char uplo, int n, int nrhs, double* A, int lda, double* B, int ldb, int* info );
+
+inline void posv( char uplo, int n, int nrhs, complex<float>* A, int lda, complex<float>* B, int ldb, int* info );
+
+inline void posv( char uplo, int n, int nrhs, complex<double>* A, int lda, complex<double>* B, int ldb, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a positive definite single precision linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK sposv() function to compute the solution to the positive definite
+// system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n positive definite matrix and
+// \a X and \a B are n-by-nrhs matrices.
+//
+// The Cholesky decomposition is used to factor \a A as
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the leading minor of order i is not positive definite, so the decomposition
+// could not be completed and the solution has not been computed.
+//
+// For more information on the sposv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void posv( char uplo, int n, int nrhs, float* A, int lda, float* B, int ldb, int* info )
+{
+ sposv_( &uplo, &n, &nrhs, A, &lda, B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a positive definite double precision linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK dposv() function to compute the solution to the positive definite
+// system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n positive definite matrix and
+// \a X and \a B are n-by-nrhs matrices.
+//
+// The Cholesky decomposition is used to factor \a A as
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the leading minor of order i is not positive definite, so the decomposition
+// could not be completed and the solution has not been computed.
+//
+// For more information on the dposv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void posv( char uplo, int n, int nrhs, double* A, int lda, double* B, int ldb, int* info )
+{
+ dposv_( &uplo, &n, &nrhs, A, &lda, B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a positive definite single precision complex linear system of
+// equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK cposv() function to compute the solution to the positive definite
+// system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n positive definite matrix and
+// \a X and \a B are n-by-nrhs matrices.
+//
+// The Cholesky decomposition is used to factor \a A as
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the leading minor of order i is not positive definite, so the decomposition
+// could not be completed and the solution has not been computed.
+//
+// For more information on the cposv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void posv( char uplo, int n, int nrhs, complex<float>* A, int lda, complex<float>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cposv_( &uplo, &n, &nrhs, reinterpret_cast<float*>( A ), &lda,
+ reinterpret_cast<float*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a positive definite double precision complex linear system of
+// equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK zposv() function to compute the solution to the positive definite
+// system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n positive definite matrix and
+// \a X and \a B are n-by-nrhs matrices.
+//
+// The Cholesky decomposition is used to factor \a A as
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the leading minor of order i is not positive definite, so the decomposition
+// could not be completed and the solution has not been computed.
+//
+// For more information on the zposv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void posv( char uplo, int n, int nrhs, complex<double>* A, int lda, complex<double>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zposv_( &uplo, &n, &nrhs, reinterpret_cast<double*>( A ), &lda,
+ reinterpret_cast<double*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/potrf.h b/src/cpu/blaze/math/lapack/clapack/potrf.h
new file mode 100644
index 00000000..cddede95
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/potrf.h
@@ -0,0 +1,272 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/potrf.h
+// \brief Header file for the CLAPACK potrf wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_POTRF_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_POTRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void spotrf_( char* uplo, int* n, float* A, int* lda, int* info );
+void dpotrf_( char* uplo, int* n, double* A, int* lda, int* info );
+void cpotrf_( char* uplo, int* n, float* A, int* lda, int* info );
+void zpotrf_( char* uplo, int* n, double* A, int* lda, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LLH (CHOLESKY) DECOMPOSITION FUNCTIONS (POTRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LLH (Cholesky) decomposition functions (potrf) */
+//@{
+inline void potrf( char uplo, int n, float* A, int lda, int* info );
+
+inline void potrf( char uplo, int n, double* A, int lda, int* info );
+
+inline void potrf( char uplo, int n, complex<float>* A, int lda, int* info );
+
+inline void potrf( char uplo, int n, complex<double>* A, int lda, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the Cholesky decomposition of the given dense positive definite
+// single precision column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix Cholesky decomposition of a symmetric positive definite
+// single precision column-major matrix based on the LAPACK spotrf() function. The decomposition
+// has the form
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the leading minor of order i is not positive definite.
+//
+// For more information on the spotrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potrf( char uplo, int n, float* A, int lda, int* info )
+{
+ spotrf_( &uplo, &n, A, &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the Cholesky decomposition of the given dense positive definite
+// double precision column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix Cholesky decomposition of a symmetric positive definite
+// double precision column-major matrix based on the LAPACK dpotrf() function. The decomposition
+// has the form
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the leading minor of order i is not positive definite.
+//
+// For more information on the dpotrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potrf( char uplo, int n, double* A, int lda, int* info )
+{
+ dpotrf_( &uplo, &n, A, &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the Cholesky decomposition of the given dense positive definite
+// single precision complex column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix Cholesky decomposition of a symmetric positive
+// definite single precision complex column-major matrix based on the LAPACK cpotrf() function.
+// The decomposition has the form
+
+ \f[ A = U^{H} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the leading minor of order i is not positive definite.
+//
+// For more information on the cpotrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potrf( char uplo, int n, complex<float>* A, int lda, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cpotrf_( &uplo, &n, reinterpret_cast<float*>( A ), &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the Cholesky decomposition of the given dense positive definite
+// double precision complex column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix Cholesky decomposition of a symmetric positive
+// definite double precision complex column-major matrix based on the LAPACK zpotrf() function.
+// The decomposition has the form
+
+ \f[ A = U^{H} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the leading minor of order i is not positive definite.
+//
+// For more information on the zpotrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potrf( char uplo, int n, complex<double>* A, int lda, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zpotrf_( &uplo, &n, reinterpret_cast<double*>( A ), &lda, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/potri.h b/src/cpu/blaze/math/lapack/clapack/potri.h
new file mode 100644
index 00000000..887d8a17
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/potri.h
@@ -0,0 +1,244 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/potri.h
+// \brief Header file for the CLAPACK potri wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ORx
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_POTRI_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_POTRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void spotri_( char* uplo, int* n, float* A, int* lda, int* info );
+void dpotri_( char* uplo, int* n, double* A, int* lda, int* info );
+void cpotri_( char* uplo, int* n, float* A, int* lda, int* info );
+void zpotri_( char* uplo, int* n, double* A, int* lda, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LLH-BASED INVERSION FUNCTIONS (POTRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LLH-based inversion functions (potri) */
+//@{
+inline void potri( char uplo, int n, float* A, int lda, int* info );
+
+inline void potri( char uplo, int n, double* A, int lda, int* info );
+
+inline void potri( char uplo, int n, complex<float>* A, int lda, int* info );
+
+inline void potri( char uplo, int n, complex<double>* A, int lda, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense positive definite single precision
+// column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK spotri() function for
+// positive-definite single precision column-major matrices that have already been factorized
+// by the spotrf() function. The resulting symmetric inverse of \a A is stored either in the
+// lower part of \a A (\a uplo = \c 'L') or in the upper part (\a uplo = \c 'U').
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element (i,i) of U or L is zero and the inverse could not be computed.
+//
+// For more information on the spotri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potri( char uplo, int n, float* A, int lda, int* info )
+{
+ spotri_( &uplo, &n, A, &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense positive definite double precision
+// column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK dpotri() function for
+// positive-definite double precision column-major matrices that have already been factorized
+// by the dpotrf() function. The resulting symmetric inverse of \a A is stored either in the
+// lower part of \a A (\a uplo = \c 'L') or in the upper part (\a uplo = \c 'U').
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element (i,i) of U or L is zero and the inverse could not be computed.
+//
+// For more information on the spotri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potri( char uplo, int n, double* A, int lda, int* info )
+{
+ dpotri_( &uplo, &n, A, &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense positive definite single precision
+// complex column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK cpotri() function for
+// positive-definite single precision complex column-major matrices that have already been
+// factorized by the cpotrf() function. The resulting symmetric inverse of \a A is stored either
+// in the lower part of \a A (\a uplo = \c 'L') or in the upper part (\a uplo = \c 'U').
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element (i,i) of U or L is zero and the inverse could not be computed.
+//
+// For more information on the cpotri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potri( char uplo, int n, complex<float>* A, int lda, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cpotri_( &uplo, &n, reinterpret_cast<float*>( A ), &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense positive definite double precision
+// complex column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK zpotri() function for
+// positive-definite double precision complex column-major matrices that have already been
+// factorized by the zpotrf() function. The resulting symmetric inverse of \a A is stored either
+// in the lower part of \a A (\a uplo = \c 'L') or in the upper part (\a uplo = \c 'U').
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element (i,i) of U or L is zero and the inverse could not be computed.
+//
+// For more information on the zpotri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potri( char uplo, int n, complex<double>* A, int lda, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zpotri_( &uplo, &n, reinterpret_cast<double*>( A ), &lda, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/potrs.h b/src/cpu/blaze/math/lapack/clapack/potrs.h
new file mode 100644
index 00000000..90341e0b
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/potrs.h
@@ -0,0 +1,256 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/potrs.h
+// \brief Header file for the CLAPACK potrs wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_POTRS_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_POTRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void spotrs_( char* uplo, int* n, int* nrhs, float* A, int* lda, float* B, int* ldb, int* info );
+void dpotrs_( char* uplo, int* n, int* nrhs, double* A, int* lda, double* B, int* ldb, int* info );
+void cpotrs_( char* uplo, int* n, int* nrhs, float* A, int* lda, float* B, int* ldb, int* info );
+void zpotrs_( char* uplo, int* n, int* nrhs, double* A, int* lda, double* B, int* ldb, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LLH-BASED SUBSTITUTION FUNCTIONS (POTRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LLH-based substitution functions (potrs) */
+//@{
+inline void potrs( char uplo, int n, int nrhs, const float* A, int lda, float* B, int ldb, int* info );
+
+inline void potrs( char uplo, int n, int nrhs, const double* A, int lda, double* B, int ldb, int* info );
+
+inline void potrs( char uplo, int n, int nrhs, const complex<float>* A, int lda, complex<float>* B, int ldb, int* info );
+
+inline void potrs( char uplo, int n, int nrhs, const complex<double>* A, int lda, complex<double>* B, int ldb, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a positive definite single precision
+// linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the single precision column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK spotrs() function to perform the substitution step to compute
+// the solution to the positive definite system of linear equations \f$ A*X=B \f$, where \a A is
+// a n-by-n matrix that has already been factorized by the spotrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the spotrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potrs( char uplo, int n, int nrhs, const float* A, int lda, float* B, int ldb, int* info )
+{
+ spotrs_( &uplo, &n, &nrhs, const_cast<float*>( A ), &lda, B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a positive definite double precision
+// linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the double precision column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK dpotrs() function to perform the substitution step to compute
+// the solution to the positive definite system of linear equations \f$ A*X=B \f$, where \a A is
+// a n-by-n matrix that has already been factorized by the dpotrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the dpotrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potrs( char uplo, int n, int nrhs, const double* A, int lda, double* B, int ldb, int* info )
+{
+ dpotrs_( &uplo, &n, &nrhs, const_cast<double*>( A ), &lda, B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a positive definite single precision
+// complex linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the single precision complex column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK cpotrs() function to perform the substitution step to compute
+// the solution to the positive definite system of linear equations \f$ A*X=B \f$, where \a A is
+// a n-by-n matrix that has already been factorized by the cpotrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the cpotrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potrs( char uplo, int n, int nrhs, const complex<float>* A,
+ int lda, complex<float>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cpotrs_( &uplo, &n, &nrhs, const_cast<float*>( reinterpret_cast<const float*>( A ) ),
+ &lda, reinterpret_cast<float*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a positive definite double precision
+// complex linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the double precision complex column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK zpotrs() function to perform the substitution step to compute
+// the solution to the positive definite system of linear equations \f$ A*X=B \f$, where \a A is
+// a n-by-n matrix that has already been factorized by the zpotrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the zpotrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void potrs( char uplo, int n, int nrhs, const complex<double>* A,
+ int lda, complex<double>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zpotrs_( &uplo, &n, &nrhs, const_cast<double*>( reinterpret_cast<const double*>( A ) ),
+ &lda, reinterpret_cast<double*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/sysv.h b/src/cpu/blaze/math/lapack/clapack/sysv.h
new file mode 100644
index 00000000..6dcd33aa
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/sysv.h
@@ -0,0 +1,326 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/sysv.h
+// \brief Header file for the CLAPACK sysv wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_SYSV_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_SYSV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void ssysv_( char* uplo, int* n, int* nrhs, float* A, int* lda, int* ipiv, float* b, int* ldb, float* work, int* lwork, int* info );
+void dsysv_( char* uplo, int* n, int* nrhs, double* A, int* lda, int* ipiv, double* b, int* ldb, double* work, int* lwork, int* info );
+void csysv_( char* uplo, int* n, int* nrhs, float* A, int* lda, int* ipiv, float* b, int* ldb, float* work, int* lwork, int* info );
+void zsysv_( char* uplo, int* n, int* nrhs, double* A, int* lda, int* ipiv, double* b, int* ldb, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK SYMMETRIC INDEFINITE LINEAR SYSTEM FUNCTIONS (SYSV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK symmetric indefinite linear system functions (sysv) */
+//@{
+inline void sysv( char uplo, int n, int nrhs, float* A, int lda, int* ipiv,
+ float* B, int ldb, float* work, int lwork, int* info );
+
+inline void sysv( char uplo, int n, int nrhs, double* A, int lda, int* ipiv,
+ double* B, int ldb, double* work, int lwork, int* info );
+
+inline void sysv( char uplo, int n, int nrhs, complex<float>* A, int lda, int* ipiv,
+ complex<float>* B, int ldb, complex<float>* work, int lwork, int* info );
+
+inline void sysv( char uplo, int n, int nrhs, complex<double>* A, int lda, int* ipiv,
+ complex<double>* B, int ldb, complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a symmetric indefinite single precision linear system of
+// equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK ssysv() function to compute the solution to the symmetric
+// indefinite system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and
+// \a B are n-by-nrhs matrices.
+//
+// The Bunch-Kaufman decomposition is used to factor \a A as
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor D(i,i) is exactly
+// zero the solution could not be computed.
+//
+// For more information on the ssysv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sysv( char uplo, int n, int nrhs, float* A, int lda, int* ipiv,
+ float* B, int ldb, float* work, int lwork, int* info )
+{
+ ssysv_( &uplo, &n, &nrhs, A, &lda, ipiv, B, &ldb, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a symmetric indefinite double precision linear system of
+// equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK dsysv() function to compute the solution to the symmetric
+// indefinite system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and
+// \a B are n-by-nrhs matrices.
+//
+// The Bunch-Kaufman decomposition is used to factor \a A as
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor D(i,i) is exactly
+// zero the solution could not be computed.
+//
+// For more information on the dsysv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sysv( char uplo, int n, int nrhs, double* A, int lda, int* ipiv,
+ double* B, int ldb, double* work, int lwork, int* info )
+{
+ dsysv_( &uplo, &n, &nrhs, A, &lda, ipiv, B, &ldb, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a symmetric indefinite single precision complex linear system
+// of equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK csysv() function to compute the solution to the symmetric
+// indefinite system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and
+// \a B are n-by-nrhs matrices.
+//
+// The Bunch-Kaufman decomposition is used to factor \a A as
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor D(i,i) is exactly
+// zero the solution could not be computed.
+//
+// For more information on the csysv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sysv( char uplo, int n, int nrhs, complex<float>* A, int lda, int* ipiv,
+ complex<float>* B, int ldb, complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ csysv_( &uplo, &n, &nrhs, reinterpret_cast<float*>( A ), &lda, ipiv,
+ reinterpret_cast<float*>( B ), &ldb, reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a symmetric indefinite double precision complex linear system
+// of equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of matrix \a A \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK zsysv() function to compute the solution to the symmetric
+// indefinite system of linear equations \f$ A*X=B \f$, where \a A is a n-by-n matrix and \a X and
+// \a B are n-by-nrhs matrices.
+//
+// The Bunch-Kaufman decomposition is used to factor \a A as
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but since factor D(i,i) is exactly
+// zero the solution could not be computed.
+//
+// For more information on the zsysv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sysv( char uplo, int n, int nrhs, complex<double>* A, int lda, int* ipiv,
+ complex<double>* B, int ldb, complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zsysv_( &uplo, &n, &nrhs, reinterpret_cast<double*>( A ), &lda, ipiv,
+ reinterpret_cast<double*>( B ), &ldb, reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/sytrf.h b/src/cpu/blaze/math/lapack/clapack/sytrf.h
new file mode 100644
index 00000000..9be57f04
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/sytrf.h
@@ -0,0 +1,322 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/sytrf.h
+// \brief Header file for the CLAPACK sytrf wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_SYTRF_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_SYTRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void ssytrf_( char* uplo, int* n, float* A, int* lda, int* ipiv, float* work, int* lwork, int* info );
+void dsytrf_( char* uplo, int* n, double* A, int* lda, int* ipiv, double* work, int* lwork, int* info );
+void csytrf_( char* uplo, int* n, float* A, int* lda, int* ipiv, float* work, int* lwork, int* info );
+void zsytrf_( char* uplo, int* n, double* A, int* lda, int* ipiv, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LDLT DECOMPOSITION FUNCTIONS (SYTRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLT decomposition functions (sytrf) */
+//@{
+inline void sytrf( char uplo, int n, float* A, int lda, int* ipiv,
+ float* work, int lwork, int* info );
+
+inline void sytrf( char uplo, int n, double* A, int lda, int* ipiv,
+ double* work, int lwork, int* info );
+
+inline void sytrf( char uplo, int n, complex<float>* A, int lda, int* ipiv,
+ complex<float>* work, int lwork, int* info );
+
+inline void sytrf( char uplo, int n, complex<double>* A, int lda, int* ipiv,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the decomposition of the given dense symmetric indefinite single
+// precision column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the symmetric matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix decomposition of a symmetric indefinite single precision
+// column-major matrix based on the LAPACK ssytrf() function, which uses the Bunch-Kaufman diagonal
+// pivoting method. The decomposition has the form
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but D(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= \a n*NB, where NB
+// is the optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a
+// workspace query is assumed. The function only calculates the optimal size of the \a work
+// array and returns this value as the first entry of the \a work array.
+//
+// For more information on the ssytrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytrf( char uplo, int n, float* A, int lda, int* ipiv,
+ float* work, int lwork, int* info )
+{
+ ssytrf_( &uplo, &n, A, &lda, ipiv, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the decomposition of the given dense symmetric indefinite double
+// precision column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the symmetric matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix decomposition of a symmetric indefinite double precision
+// column-major matrix based on the LAPACK dsytrf() function, which uses the Bunch-Kaufman diagonal
+// pivoting method. The decomposition has the form
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but D(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= \a n*NB, where NB
+// is the optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a
+// workspace query is assumed. The function only calculates the optimal size of the \a work
+// array and returns this value as the first entry of the \a work array.
+//
+// For more information on the dsytrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytrf( char uplo, int n, double* A, int lda, int* ipiv,
+ double* work, int lwork, int* info )
+{
+ dsytrf_( &uplo, &n, A, &lda, ipiv, work, &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the decomposition of the given dense symmetric indefinite single
+// precision complex column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the symmetric matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix decomposition of a symmetric indefinite single precision
+// column-major matrix based on the LAPACK csytrf() function, which uses the Bunch-Kaufman diagonal
+// pivoting method. The decomposition has the form
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but D(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= \a n*NB, where NB
+// is the optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a
+// workspace query is assumed. The function only calculates the optimal size of the \a work
+// array and returns this value as the first entry of the \a work array.
+//
+// For more information on the csytrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytrf( char uplo, int n, complex<float>* A, int lda, int* ipiv,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ csytrf_( &uplo, &n, reinterpret_cast<float*>( A ), &lda, ipiv,
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the decomposition of the given dense symmetric indefinite double
+// precision complex column-major matrix.
+// \ingroup lapack_decomposition
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the symmetric matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix decomposition of a symmetric indefinite double precision
+// column-major matrix based on the LAPACK zsytrf() function, which uses the Bunch-Kaufman diagonal
+// pivoting method. The decomposition has the form
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+// - > 0: If info = i, the decomposition has been completed, but D(i,i) is exactly zero.
+//
+// If the function exits successfully (i.e. \a info = 0) then the first element of the \a work
+// array returns the optimal \a lwork. For optimal performance \a lwork >= \a n*NB, where NB
+// is the optimal blocksize returned by the LAPACK function ilaenv(). If \a lwork = -1 then a
+// workspace query is assumed. The function only calculates the optimal size of the \a work
+// array and returns this value as the first entry of the \a work array.
+//
+// For more information on the zsytrf() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytrf( char uplo, int n, complex<double>* A, int lda, int* ipiv,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zsytrf_( &uplo, &n, reinterpret_cast<double*>( A ), &lda, ipiv,
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/sytri.h b/src/cpu/blaze/math/lapack/clapack/sytri.h
new file mode 100644
index 00000000..80c80806
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/sytri.h
@@ -0,0 +1,254 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/sytri.h
+// \brief Header file for the CLAPACK sytri wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_SYTRI_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_SYTRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void ssytri_( char* uplo, int* n, float* A, int* lda, int* ipiv, float* work, int* info );
+void dsytri_( char* uplo, int* n, double* A, int* lda, int* ipiv, double* work, int* info );
+void csytri_( char* uplo, int* n, float* A, int* lda, int* ipiv, float* work, int* info );
+void zsytri_( char* uplo, int* n, double* A, int* lda, int* ipiv, double* work, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LDLT-BASED INVERSION FUNCTIONS (SYTRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLT-based inversion functions (sytri) */
+//@{
+inline void sytri( char uplo, int n, float* A, int lda, const int* ipiv, float* work, int* info );
+
+inline void sytri( char uplo, int n, double* A, int lda, const int* ipiv, double* work, int* info );
+
+inline void sytri( char uplo, int n, complex<float>* A, int lda,
+ const int* ipiv, complex<float>* work, int* info );
+
+inline void sytri( char uplo, int n, complex<double>* A, int lda,
+ const int* ipiv, complex<double>* work, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense symmetric indefinite single precision
+// column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param n The number of rows/columns of the symmetric matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array of size \a n.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK ssytri() function for
+// symmetric indefinite single precision column-major matrices that have already been factorized
+// by the ssytrf() function.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element D(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the ssytri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytri( char uplo, int n, float* A, int lda, const int* ipiv, float* work, int* info )
+{
+ ssytri_( &uplo, &n, A, &lda, const_cast<int*>( ipiv ), work, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense symmetric indefinite double precision
+// column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param n The number of rows/columns of the symmetric matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array of size \a n.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK dsytri() function for
+// symmetric indefinite double precision column-major matrices that have already been factorized
+// by the dsytrf() function.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element D(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the dsytri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytri( char uplo, int n, double* A, int lda, const int* ipiv, double* work, int* info )
+{
+ dsytri_( &uplo, &n, A, &lda, const_cast<int*>( ipiv ), work, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense symmetric indefinite single precision
+// complex column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param n The number of rows/columns of the symmetric matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array of size \a n.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK csytri() function for
+// symmetric indefinite single precision complex column-major matrices that have already been
+// factorized by the csytrf() function.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element D(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the csytri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytri( char uplo, int n, complex<float>* A, int lda,
+ const int* ipiv, complex<float>* work, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ csytri_( &uplo, &n, reinterpret_cast<float*>( A ), &lda,
+ const_cast<int*>( ipiv ), reinterpret_cast<float*>( work ), info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense symmetric indefinite double precision
+// complex column-major square matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param n The number of rows/columns of the symmetric matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param work Auxiliary array of size \a n.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK zsytri() function for
+// symmetric indefinite double precision complex column-major matrices that have already been
+// factorized by the zsytrf() function.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element D(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the zsytri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytri( char uplo, int n, complex<double>* A, int lda,
+ const int* ipiv, complex<double>* work, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zsytri_( &uplo, &n, reinterpret_cast<double*>( A ), &lda,
+ const_cast<int*>( ipiv ), reinterpret_cast<double*>( work ), info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/sytrs.h b/src/cpu/blaze/math/lapack/clapack/sytrs.h
new file mode 100644
index 00000000..1bddd927
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/sytrs.h
@@ -0,0 +1,268 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/sytrs.h
+// \brief Header file for the CLAPACK sytrs wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_SYTRS_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_SYTRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void ssytrs_( char* uplo, int* n, int* nrhs, float* A, int* lda, int* ipiv, float* B, int* ldb, int* info );
+void dsytrs_( char* uplo, int* n, int* nrhs, double* A, int* lda, int* ipiv, double* B, int* ldb, int* info );
+void csytrs_( char* uplo, int* n, int* nrhs, float* A, int* lda, int* ipiv, float* B, int* ldb, int* info );
+void zsytrs_( char* uplo, int* n, int* nrhs, double* A, int* lda, int* ipiv, double* B, int* ldb, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK LDLT-BASED SUBSTITUTION FUNCTIONS (SYTRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLT-based substitution functions (sytrs) */
+//@{
+inline void sytrs( char uplo, int n, int nrhs, const float* A, int lda, const int* ipiv,
+ float* B, int ldb, int* info );
+
+inline void sytrs( char uplo, int n, int nrhs, const double* A, int lda, const int* ipiv,
+ double* B, int ldb, int* info );
+
+inline void sytrs( char uplo, int n, int nrhs, const complex<float>* A, int lda, const int* ipiv,
+ complex<float>* B, int ldb, int* info );
+
+inline void sytrs( char uplo, int n, int nrhs, const complex<double>* A, int lda, const int* ipiv,
+ complex<double>* B, int ldb, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite single
+// precision linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the single precision column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK ssytrs() function to perform the substitution step to compute
+// the solution to the symmetric indefinite system of linear equations \f$ A*X=B \f$, where \a A
+// is a n-by-n matrix that has already been factorized by the ssytrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the ssytrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytrs( char uplo, int n, int nrhs, const float* A, int lda, const int* ipiv,
+ float* B, int ldb, int* info )
+{
+ ssytrs_( &uplo, &n, &nrhs, const_cast<float*>( A ), &lda,
+ const_cast<int*>( ipiv ), B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite double
+// precision linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the double precision column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK dsytrs() function to perform the substitution step to compute
+// the solution to the symmetric indefinite system of linear equations \f$ A*X=B \f$, where \a A
+// is a n-by-n matrix that has already been factorized by the dsytrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the dsytrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytrs( char uplo, int n, int nrhs, const double* A, int lda, const int* ipiv,
+ double* B, int ldb, int* info )
+{
+ dsytrs_( &uplo, &n, &nrhs, const_cast<double*>( A ), &lda,
+ const_cast<int*>( ipiv ), B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite single
+// precision complex linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the single precision complex column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK csytrs() function to perform the substitution step to compute
+// the solution to the symmetric indefinite system of linear equations \f$ A*X=B \f$, where \a A
+// is a n-by-n matrix that has already been factorized by the csytrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the csytrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytrs( char uplo, int n, int nrhs, const complex<float>* A, int lda,
+ const int* ipiv, complex<float>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ csytrs_( &uplo, &n, &nrhs, const_cast<float*>( reinterpret_cast<const float*>( A ) ),
+ &lda, const_cast<int*>( ipiv ), reinterpret_cast<float*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite double
+// precision complex linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of matrix \a A \f$[0..\infty)\f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \param B Pointer to the first element of the double precision complex column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK zsytrs() function to perform the substitution step to compute
+// the solution to the symmetric indefinite system of linear equations \f$ A*X=B \f$, where \a A
+// is a n-by-n matrix that has already been factorized by the zsytrf() function and \a X and \a B
+// are column-major n-by-nrhs matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the zsytrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void sytrs( char uplo, int n, int nrhs, const complex<double>* A, int lda,
+ const int* ipiv, complex<double>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zsytrs_( &uplo, &n, &nrhs, const_cast<double*>( reinterpret_cast<const double*>( A ) ),
+ &lda, const_cast<int*>( ipiv ), reinterpret_cast<double*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/trsv.h b/src/cpu/blaze/math/lapack/clapack/trsv.h
new file mode 100644
index 00000000..4f98a316
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/trsv.h
@@ -0,0 +1,270 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/trsv.h
+// \brief Header file for the CLAPACK trsv wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_TRSV_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_TRSV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void strsv_( char* uplo, char* trans, char* diag, int* n, float* A, int* lda, float* x, int* incX );
+void dtrsv_( char* uplo, char* trans, char* diag, int* n, double* A, int* lda, double* x, int* incX );
+void ctrsv_( char* uplo, char* trans, char* diag, int* n, float* A, int* lda, float* x, int* incX );
+void ztrsv_( char* uplo, char* trans, char* diag, int* n, double* A, int* lda, double* x, int* incX );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK TRIANGULAR LINEAR SYSTEM FUNCTIONS (TRSV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK triangular linear system functions (trsv) */
+//@{
+inline void trsv( char uplo, char trans, char diag, int n, const float* A,
+ int lda, float* x, int incX );
+
+inline void trsv( char uplo, char trans, char diag, int n, const double* A,
+ int lda, double* x, int incX );
+
+inline void trsv( char uplo, char trans, char diag, int n, const complex<float>* A,
+ int lda, complex<float>* x, int incX );
+
+inline void trsv( char uplo, char trans, char diag, int n, const complex<double>* A,
+ int lda, complex<double>* x, int incX );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a triangular single precision linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the column-major triangular matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \return void
+//
+// This function uses the LAPACK strsv() function to compute the solution to the triangular system
+// of linear equations \f$ A*x=b \f$, where \a A is a n-by-n triangular matrix and \a x and \a b
+// are n-dimensional vectors. The \a trans argument specifies the form of the linear system of
+// equations:
+//
+// - 'N': \f$ A*x=b \f$ (no transpose)
+// - 'T': \f$ A^{T}*x=b \f$ (transpose)
+// - 'C': \f$ A^{H}*x=b \f$ (conjugate transpose)
+//
+// For more information on the strsv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note The function does not perform any test for singularity or near-singularity. Such tests
+// must be performed prior to calling this function!
+*/
+inline void trsv( char uplo, char trans, char diag, int n, const float* A,
+ int lda, float* x, int incX )
+{
+ strsv_( &uplo, &trans, &diag, &n, const_cast<float*>( A ), &lda, x, &incX );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a triangular double precision linear system of equations
+// (\f$ A*x=b \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the column-major triangular matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \return void
+//
+// This function uses the LAPACK dtrsv() function to compute the solution to the triangular system
+// of linear equations \f$ A*x=b \f$, where \a A is a n-by-n triangular matrix and \a x and \a b
+// are n-dimensional vectors. The \a trans argument specifies the form of the linear system of
+// equations:
+//
+// - 'N': \f$ A*x=b \f$ (no transpose)
+// - 'T': \f$ A^{T}*x=b \f$ (transpose)
+// - 'C': \f$ A^{H}*x=b \f$ (conjugate transpose)
+//
+// For more information on the dtrsv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note The function does not perform any test for singularity or near-singularity. Such tests
+// must be performed prior to calling this function!
+*/
+inline void trsv( char uplo, char trans, char diag, int n, const double* A,
+ int lda, double* x, int incX )
+{
+ dtrsv_( &uplo, &trans, &diag, &n, const_cast<double*>( A ), &lda, x, &incX );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a triangular single precision complex linear system of
+// equations (\f$ A*x=b \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the column-major triangular matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \return void
+//
+// This function uses the LAPACK ctrsv() function to compute the solution to the triangular system
+// of linear equations \f$ A*x=b \f$, where \a A is a n-by-n triangular matrix and \a x and \a b
+// are n-dimensional vectors. The \a trans argument specifies the form of the linear system of
+// equations:
+//
+// - 'N': \f$ A*x=b \f$ (no transpose)
+// - 'T': \f$ A^{T}*x=b \f$ (transpose)
+// - 'C': \f$ A^{H}*x=b \f$ (conjugate transpose)
+//
+// For more information on the ctrsv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note The function does not perform any test for singularity or near-singularity. Such tests
+// must be performed prior to calling this function!
+*/
+inline void trsv( char uplo, char trans, char diag, int n, const complex<float>* A,
+ int lda, complex<float>* x, int incX )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ ctrsv_( &uplo, &trans, &diag, &n, const_cast<float*>( reinterpret_cast<const float*>( A ) ),
+ &lda, reinterpret_cast<float*>( x ), &incX );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a triangular double precision complex linear system of
+// equations (\f$ A*x=b \f$).
+// \ingroup lapack_solver
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the column-major triangular matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param x Pointer to the first element of vector \a x.
+// \param incX The stride within vector \a x.
+// \return void
+//
+// This function uses the LAPACK ztrsv() function to compute the solution to the triangular system
+// of linear equations \f$ A*x=b \f$, where \a A is a n-by-n triangular matrix and \a x and \a b
+// are n-dimensional vectors. The \a trans argument specifies the form of the linear system of
+// equations:
+//
+// - 'N': \f$ A*x=b \f$ (no transpose)
+// - 'T': \f$ A^{T}*x=b \f$ (transpose)
+// - 'C': \f$ A^{H}*x=b \f$ (conjugate transpose)
+//
+// For more information on the ztrsv() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note The function does not perform any test for singularity or near-singularity. Such tests
+// must be performed prior to calling this function!
+*/
+inline void trsv( char uplo, char trans, char diag, int n, const complex<double>* A,
+ int lda, complex<double>* x, int incX )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ ztrsv_( &uplo, &trans, &diag, &n, const_cast<double*>( reinterpret_cast<const double*>( A ) ),
+ &lda, reinterpret_cast<double*>( x ), &incX );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/trtri.h b/src/cpu/blaze/math/lapack/clapack/trtri.h
new file mode 100644
index 00000000..e04097c2
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/trtri.h
@@ -0,0 +1,244 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/trtri.h
+// \brief Header file for the CLAPACK trtri wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_TRTRI_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_TRTRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void strtri_( char* uplo, char* diag, int* n, float* A, int* lda, int* info );
+void dtrtri_( char* uplo, char* diag, int* n, double* A, int* lda, int* info );
+void ctrtri_( char* uplo, char* diag, int* n, float* A, int* lda, int* info );
+void ztrtri_( char* uplo, char* diag, int* n, double* A, int* lda, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK TRIANGULAR MATRIX INVERSION FUNCTIONS (TRTRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK triangular matrix inversion functions (trtri) */
+//@{
+inline void trtri( char uplo, char diag, int n, float* A, int lda, int* info );
+
+inline void trtri( char uplo, char diag, int n, double* A, int lda, int* info );
+
+inline void trtri( char uplo, char diag, int n, complex<float>* A, int lda, int* info );
+
+inline void trtri( char uplo, char diag, int n, complex<double>* A, int lda, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense triangular single precision
+// column-major matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the triangular matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK strtri() function for
+// lower triangular (\a uplo = \c 'L') or upper triangular (\a uplo = \a 'U') single precision
+// column-major matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element A(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the strtri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void trtri( char uplo, char diag, int n, float* A, int lda, int* info )
+{
+ strtri_( &uplo, &diag, &n, A, &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense triangular double precision
+// column-major matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the triangular matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK dtrtri() function for
+// lower triangular (\a uplo = \c 'L') or upper triangular (\a uplo = \a 'U') double precision
+// column-major matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element A(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the dtrtri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void trtri( char uplo, char diag, int n, double* A, int lda, int* info )
+{
+ dtrtri_( &uplo, &diag, &n, A, &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense triangular single precision complex
+// column-major matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the triangular matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK ctrtri() function for
+// lower triangular (\a uplo = \c 'L') or upper triangular (\a uplo = \a 'U') single precision
+// complex column-major matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element A(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the ctrtri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void trtri( char uplo, char diag, int n, complex<float>* A, int lda, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ ctrtri_( &uplo, &diag, &n, reinterpret_cast<float*>( A ), &lda, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense triangular double precision complex
+// column-major matrix.
+// \ingroup lapack_inversion
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the triangular matrix \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function performs the dense matrix inversion based on the LAPACK ztrtri() function for
+// lower triangular (\a uplo = \c 'L') or upper triangular (\a uplo = \a 'U') double precision
+// complex column-major matrices.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The inversion finished successfully.
+// - < 0: If \a info = -i, the i-th argument had an illegal value.
+// - > 0: If \a info = i, element A(i,i) is exactly zero and the inverse could not be computed.
+//
+// For more information on the ztrtri() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void trtri( char uplo, char diag, int n, complex<double>* A, int lda, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ ztrtri_( &uplo, &diag, &n, reinterpret_cast<double*>( A ), &lda, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/trtrs.h b/src/cpu/blaze/math/lapack/clapack/trtrs.h
new file mode 100644
index 00000000..e4e674a2
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/trtrs.h
@@ -0,0 +1,286 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/trtrs.h
+// \brief Header file for the CLAPACK trtrs wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_TRTRS_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_TRTRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void strtrs_( char* uplo, char* trans, char* diag, int* n, int* nrhs, float* A, int* lda, float* B, int* ldb, int* info );
+void dtrtrs_( char* uplo, char* trans, char* diag, int* n, int* nrhs, double* A, int* lda, double* B, int* ldb, int* info );
+void ctrtrs_( char* uplo, char* trans, char* diag, int* n, int* nrhs, float* A, int* lda, float* B, int* ldb, int* info );
+void ztrtrs_( char* uplo, char* trans, char* diag, int* n, int* nrhs, double* A, int* lda, double* B, int* ldb, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK TRIANGULAR SUBSTITUTION FUNCTIONS (TRTRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK triangular substitution functions (trtrs) */
+//@{
+inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const float* A,
+ int lda, float* B, int ldb, int* info );
+
+inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const double* A,
+ int lda, double* B, int ldb, int* info );
+
+inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const complex<float>* A,
+ int lda, complex<float>* B, int ldb, int* info );
+
+inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const complex<double>* A,
+ int lda, complex<double>* B, int ldb, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a triangular single precision linear
+// system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK strtrs() function to perform the substitution step to compute
+// the solution to the general system of linear equations \f$ A*X=B \f$, \f$ A^{T}*X=B \f$, or
+// \f$ A^{H}*X=B \f$, where \a A is a n-by-n matrix and \a X and \a B are column-major n-by-nrhs
+// matrices. The \a trans argument specifies the form of the linear system of equations:
+//
+// - 'N': \f$ A*X=B \f$ (no transpose)
+// - 'T': \f$ A^{T}*X=B \f$ (transpose)
+// - 'C': \f$ A^{H}*X=B \f$ (conjugate transpose)
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the strtrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const float* A, int lda,
+ float* B, int ldb, int* info )
+{
+ strtrs_( &uplo, &trans, &diag, &n, &nrhs, const_cast<float*>( A ), &lda, B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a triangular double precision linear
+// system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK dtrtrs() function to perform the substitution step to compute
+// the solution to the general system of linear equations \f$ A*X=B \f$, \f$ A^{T}*X=B \f$, or
+// \f$ A^{H}*X=B \f$, where \a A is a n-by-n matrix and \a X and \a B are column-major n-by-nrhs
+// matrices. The \a trans argument specifies the form of the linear system of equations:
+//
+// - 'N': \f$ A*X=B \f$ (no transpose)
+// - 'T': \f$ A^{T}*X=B \f$ (transpose)
+// - 'C': \f$ A^{H}*X=B \f$ (conjugate transpose)
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the dtrtrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const double* A, int lda,
+ double* B, int ldb, int* info )
+{
+ dtrtrs_( &uplo, &trans, &diag, &n, &nrhs, const_cast<double*>( A ), &lda, B, &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a triangular single precision complex
+// linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the single precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK ctrtrs() function to perform the substitution step to compute
+// the solution to the general system of linear equations \f$ A*X=B \f$, \f$ A^{T}*X=B \f$, or
+// \f$ A^{H}*X=B \f$, where \a A is a n-by-n matrix and \a X and \a B are column-major n-by-nrhs
+// matrices. The \a trans argument specifies the form of the linear system of equations:
+//
+// - 'N': \f$ A*X=B \f$ (no transpose)
+// - 'T': \f$ A^{T}*X=B \f$ (transpose)
+// - 'C': \f$ A^{H}*X=B \f$ (conjugate transpose)
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the ctrtrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const complex<float>* A,
+ int lda, complex<float>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ ctrtrs_( &uplo, &trans, &diag, &n, &nrhs, const_cast<float*>( reinterpret_cast<const float*>( A ) ),
+ &lda, reinterpret_cast<float*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a triangular double precision complex
+// linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \param n The number of rows/columns of the column-major matrix \f$[0..\infty)\f$.
+// \param nrhs The number of right-hand side vectors \f$[0..\infty)\f$.
+// \param A Pointer to the first element of the double precision complex column-major square matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param B Pointer to the first element of the column-major matrix.
+// \param ldb The total number of elements between two columns of matrix \a B \f$[0..\infty)\f$.
+// \param info Return code of the function call.
+// \return void
+//
+// This function uses the LAPACK ztrtrs() function to perform the substitution step to compute
+// the solution to the general system of linear equations \f$ A*X=B \f$, \f$ A^{T}*X=B \f$, or
+// \f$ A^{H}*X=B \f$, where \a A is a n-by-n matrix and \a X and \a B are column-major n-by-nrhs
+// matrices. The \a trans argument specifies the form of the linear system of equations:
+//
+// - 'N': \f$ A*X=B \f$ (no transpose)
+// - 'T': \f$ A^{T}*X=B \f$ (transpose)
+// - 'C': \f$ A^{H}*X=B \f$ (conjugate transpose)
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The function finished successfully.
+// - < 0: If info = -i, the i-th argument had an illegal value.
+//
+// For more information on the ztrtrs() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const complex<double>* A,
+ int lda, complex<double>* B, int ldb, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ ztrtrs_( &uplo, &trans, &diag, &n, &nrhs, const_cast<double*>( reinterpret_cast<const double*>( A ) ),
+ &lda, reinterpret_cast<double*>( B ), &ldb, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/unglq.h b/src/cpu/blaze/math/lapack/clapack/unglq.h
new file mode 100644
index 00000000..1f6be583
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/unglq.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/unglq.h
+// \brief Header file for the CLAPACK unglq wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_UNGLQ_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_UNGLQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void cunglq_( int* m, int* n, int* k, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void zunglq_( int* m, int* n, int* k, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A LQ DECOMPOSITION (UNGLQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a LQ decomposition (unglq) */
+//@{
+inline void unglq( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau,
+ complex<float>* work, int lwork, int* info );
+
+inline void unglq( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a LQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..n)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..m)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a LQ decomposition based on
+// the LAPACK cunglq() function for single precision complex column-major matrices that have already
+// been factorized by the cgelqf() function. The \a info argument provides feedback on the success
+// of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cunglq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unglq( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cunglq_( &m, &n, &k, reinterpret_cast<float*>( A ), &lda,
+ const_cast<float*>( reinterpret_cast<const float*>( tau ) ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a LQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..n)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..m)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a LQ decomposition based on
+// the LAPACK zunglq() function for double precision complex column-major matrices that have already
+// been factorized by the zgelqf() function. The \a info argument provides feedback on the success
+// of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zunglq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unglq( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zunglq_( &m, &n, &k, reinterpret_cast<double*>( A ), &lda,
+ const_cast<double*>( reinterpret_cast<const double*>( tau ) ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/ungql.h b/src/cpu/blaze/math/lapack/clapack/ungql.h
new file mode 100644
index 00000000..f7090e2c
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/ungql.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/ungql.h
+// \brief Header file for the CLAPACK ungql wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_UNGQL_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_UNGQL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void cungql_( int* m, int* n, int* k, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void zungql_( int* m, int* n, int* k, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A QL DECOMPOSITION (UNGQL)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a QL decomposition (ungql) */
+//@{
+inline void ungql( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau,
+ complex<float>* work, int lwork, int* info );
+
+inline void ungql( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QL decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..m)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..n)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a QL decomposition based on
+// the LAPACK cungql() function for single precision column-major matrices that have already been
+// factorized by the sgeqlf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cungql() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ungql( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cungql_( &m, &n, &k, reinterpret_cast<float*>( A ), &lda,
+ const_cast<float*>( reinterpret_cast<const float*>( tau ) ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QL decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..m)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..n)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a QL decomposition based on
+// the LAPACK zungql() function for double precision column-major matrices that have already been
+// factorized by the dgeqlf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zungql() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ungql( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zungql_( &m, &n, &k, reinterpret_cast<double*>( A ), &lda,
+ const_cast<double*>( reinterpret_cast<const double*>( tau ) ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/ungqr.h b/src/cpu/blaze/math/lapack/clapack/ungqr.h
new file mode 100644
index 00000000..36599128
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/ungqr.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/ungqr.h
+// \brief Header file for the CLAPACK ungqr wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_UNGQR_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_UNGQR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void cungqr_( int* m, int* n, int* k, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void zungqr_( int* m, int* n, int* k, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A QR DECOMPOSITION (UNGQR)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a QR decomposition (ungqr) */
+//@{
+inline void ungqr( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau,
+ complex<float>* work, int lwork, int* info );
+
+inline void ungqr( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QR decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..m)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..n)\f$.
+// \param A Pointer to the first element of the single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a QR decomposition based on
+// the LAPACK cungqr() function for single precision complex column-major matrices that have already
+// been factorized by the cgeqrf() function. The \a info argument provides feedback on the success
+// of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cungqr() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ungqr( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cungqr_( &m, &n, &k, reinterpret_cast<float*>( A ), &lda,
+ const_cast<float*>( reinterpret_cast<const float*>( tau ) ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QR decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..\infty)\f$.
+// \param n The number of columns of the given matrix \f$[0..m)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..n)\f$.
+// \param A Pointer to the first element of the double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a QR decomposition based on
+// the LAPACK zungqr() function for double precision complex column-major matrices that have already
+// been factorized by the zgeqrf() function. The \a info argument provides feedback on the success
+// of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zungqr() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ungqr( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zungqr_( &m, &n, &k, reinterpret_cast<double*>( A ), &lda,
+ const_cast<double*>( reinterpret_cast<const double*>( tau ) ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/ungrq.h b/src/cpu/blaze/math/lapack/clapack/ungrq.h
new file mode 100644
index 00000000..34d602d1
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/ungrq.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/ungrq.h
+// \brief Header file for the CLAPACK ungrq wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_UNGRQ_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_UNGRQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void cungrq_( int* m, int* n, int* k, float* A, int* lda, float* tau, float* work, int* lwork, int* info );
+void zungrq_( int* m, int* n, int* k, double* A, int* lda, double* tau, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A RQ DECOMPOSITION (UNGRQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a RQ decomposition (ungrq) */
+//@{
+inline void ungrq( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau,
+ complex<float>* work, int lwork, int* info );
+
+inline void ungrq( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau,
+ complex<double>* work, int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a RQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..n)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..m)\f$.
+// \param A Pointer to the first element of the single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a RQ decomposition based on
+// the LAPACK cungrq() function for single precision column-major matrices that have already been
+// factorized by the sgerqf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cungrq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ungrq( int m, int n, int k, complex<float>* A, int lda, const complex<float>* tau,
+ complex<float>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cungrq_( &m, &n, &k, reinterpret_cast<float*>( A ), &lda,
+ const_cast<float*>( reinterpret_cast<const float*>( tau ) ),
+ reinterpret_cast<float*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a RQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param m The number of rows of the given matrix \f$[0..n)\f$.
+// \param n The number of columns of the given matrix \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \f$[0..m)\f$.
+// \param A Pointer to the first element of the double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work; size >= max( 1, \a n ).
+// \param info Return code of the function call.
+// \return void
+//
+// This function generates all or part of the orthogonal matrix Q from a RQ decomposition based on
+// the LAPACK zungrq() function for double precision column-major matrices that have already been
+// factorized by the dgerqf() function. The \a info argument provides feedback on the success of
+// the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zungrq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void ungrq( int m, int n, int k, complex<double>* A, int lda, const complex<double>* tau,
+ complex<double>* work, int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zungrq_( &m, &n, &k, reinterpret_cast<double*>( A ), &lda,
+ const_cast<double*>( reinterpret_cast<const double*>( tau ) ),
+ reinterpret_cast<double*>( work ), &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/unmlq.h b/src/cpu/blaze/math/lapack/clapack/unmlq.h
new file mode 100644
index 00000000..b16848f6
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/unmlq.h
@@ -0,0 +1,212 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/unmlq.h
+// \brief Header file for the CLAPACK unmlq wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_UNMLQ_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_UNMLQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void cunmlq_( char* side, char* trans, int* m, int* n, int* k, float* A, int* lda, float* tau, float* C, int* ldc, float* work, int* lwork, int* info );
+void zunmlq_( char* side, char* trans, int* m, int* n, int* k, double* A, int* lda, double* tau, double* C, int* ldc, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A LQ DECOMPOSITION WITH A MATRIX (UNMLQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a LQ decomposition with a matrix (unmlq) */
+//@{
+inline void unmlq( char side, char trans, int m, int n, int k, const complex<float>* A, int lda,
+ const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work,
+ int lwork, int* info );
+
+inline void unmlq( char side, char trans, int m, int n, int k, const complex<double>* A, int lda,
+ const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work,
+ int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the single precision complex Q from a LQ
+// decomposition with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the LQ decomposed single precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the single precision complex column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the LQ decomposition of the sgelqf()
+// function with the given general single precision complex \a m-by-\a n matrix \a C. Depending
+// on the settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|---------------|---------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | ctrans(Q) * C | C * ctrans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cunmlq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unmlq( char side, char trans, int m, int n, int k, const complex<float>* A, int lda,
+ const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work,
+ int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cunmlq_( &side, &trans, &m, &n, &k,
+ const_cast<float*>( reinterpret_cast<const float*>( A ) ), &lda,
+ const_cast<float*>( reinterpret_cast<const float*>( tau ) ),
+ reinterpret_cast<float*>( C ), &ldc, reinterpret_cast<float*>( work ),
+ &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision complex Q from a LQ
+// decomposition with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the LQ decomposed double precision complex column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the double precision complex column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the LQ decomposition of the sgelqf()
+// function with the given general double precision complex \a m-by-\a n matrix \a C. Depending
+// on the settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|---------------|---------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | ctrans(Q) * C | C * ctrans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zunmlq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unmlq( char side, char trans, int m, int n, int k, const complex<double>* A, int lda,
+ const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work,
+ int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zunmlq_( &side, &trans, &m, &n, &k,
+ const_cast<double*>( reinterpret_cast<const double*>( A ) ), &lda,
+ const_cast<double*>( reinterpret_cast<const double*>( tau ) ),
+ reinterpret_cast<double*>( C ), &ldc, reinterpret_cast<double*>( work ),
+ &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/unmql.h b/src/cpu/blaze/math/lapack/clapack/unmql.h
new file mode 100644
index 00000000..fa2ef64c
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/unmql.h
@@ -0,0 +1,212 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/unmql.h
+// \brief Header file for the CLAPACK unmql wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_UNMQL_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_UNMQL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void cunmql_( char* side, char* trans, int* m, int* n, int* k, float* A, int* lda, float* tau, float* C, int* ldc, float* work, int* lwork, int* info );
+void zunmql_( char* side, char* trans, int* m, int* n, int* k, double* A, int* lda, double* tau, double* C, int* ldc, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A QL DECOMPOSITION WITH A MATRIX (UNMQL)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a QL decomposition with a matrix (unmql) */
+//@{
+inline void unmql( char side, char trans, int m, int n, int k, const complex<float>* A, int lda,
+ const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work,
+ int lwork, int* info );
+
+inline void unmql( char side, char trans, int m, int n, int k, const complex<double>* A, int lda,
+ const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work,
+ int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the single precision Q from a QL decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the QL decomposed single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the single precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the QL decomposition of the sgeqlf()
+// function with the given general single precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|---------------|---------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | ctrans(Q) * C | C * ctrans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cunmql() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unmql( char side, char trans, int m, int n, int k, const complex<float>* A, int lda,
+ const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work,
+ int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cunmql_( &side, &trans, &m, &n, &k,
+ const_cast<float*>( reinterpret_cast<const float*>( A ) ), &lda,
+ const_cast<float*>( reinterpret_cast<const float*>( tau ) ),
+ reinterpret_cast<float*>( C ), &ldc, reinterpret_cast<float*>( work ),
+ &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a QL decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the QL decomposed double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the double precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the QL decomposition of the sgeqlf()
+// function with the given general double precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|---------------|---------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | ctrans(Q) * C | C * ctrans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zunmql() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unmql( char side, char trans, int m, int n, int k, const complex<double>* A, int lda,
+ const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work,
+ int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zunmql_( &side, &trans, &m, &n, &k,
+ const_cast<double*>( reinterpret_cast<const double*>( A ) ), &lda,
+ const_cast<double*>( reinterpret_cast<const double*>( tau ) ),
+ reinterpret_cast<double*>( C ), &ldc, reinterpret_cast<double*>( work ),
+ &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/unmqr.h b/src/cpu/blaze/math/lapack/clapack/unmqr.h
new file mode 100644
index 00000000..13cde722
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/unmqr.h
@@ -0,0 +1,212 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/unmqr.h
+// \brief Header file for the CLAPACK unmqr wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_UNMQR_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_UNMQR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void cunmqr_( char* side, char* trans, int* m, int* n, int* k, float* A, int* lda, float* tau, float* C, int* ldc, float* work, int* lwork, int* info );
+void zunmqr_( char* side, char* trans, int* m, int* n, int* k, double* A, int* lda, double* tau, double* C, int* ldc, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A QR DECOMPOSITION WITH A MATRIX (UNMQR)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a QR decomposition with a matrix (unmqr) */
+//@{
+inline void unmqr( char side, char trans, int m, int n, int k, const complex<float>* A, int lda,
+ const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work,
+ int lwork, int* info );
+
+inline void unmqr( char side, char trans, int m, int n, int k, const complex<double>* A, int lda,
+ const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work,
+ int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the single precision Q from a QR decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the QR decomposed single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the single precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the QR decomposition of the sgeqrf()
+// function with the given general single precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|---------------|---------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | ctrans(Q) * C | C * ctrans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cunmqr() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unmqr( char side, char trans, int m, int n, int k, const complex<float>* A, int lda,
+ const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work,
+ int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cunmqr_( &side, &trans, &m, &n, &k,
+ const_cast<float*>( reinterpret_cast<const float*>( A ) ), &lda,
+ const_cast<float*>( reinterpret_cast<const float*>( tau ) ),
+ reinterpret_cast<float*>( C ), &ldc, reinterpret_cast<float*>( work ),
+ &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a QR decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the QR decomposed double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the double precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the QR decomposition of the sgeqrf()
+// function with the given general double precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|---------------|---------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | ctrans(Q) * C | C * ctrans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zunmqr() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unmqr( char side, char trans, int m, int n, int k, const complex<double>* A, int lda,
+ const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work,
+ int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zunmqr_( &side, &trans, &m, &n, &k,
+ const_cast<double*>( reinterpret_cast<const double*>( A ) ), &lda,
+ const_cast<double*>( reinterpret_cast<const double*>( tau ) ),
+ reinterpret_cast<double*>( C ), &ldc, reinterpret_cast<double*>( work ),
+ &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/clapack/unmrq.h b/src/cpu/blaze/math/lapack/clapack/unmrq.h
new file mode 100644
index 00000000..373ff300
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/clapack/unmrq.h
@@ -0,0 +1,212 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/clapack/unmrq.h
+// \brief Header file for the CLAPACK unmrq wrapper functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_CLAPACK_UNMRQ_H_
+#define _BLAZE_MATH_LAPACK_CLAPACK_UNMRQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+extern "C" {
+
+void cunmrq_( char* side, char* trans, int* m, int* n, int* k, float* A, int* lda, float* tau, float* C, int* ldc, float* work, int* lwork, int* info );
+void zunmrq_( char* side, char* trans, int* m, int* n, int* k, double* A, int* lda, double* tau, double* C, int* ldc, double* work, int* lwork, int* info );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A RQ DECOMPOSITION WITH A MATRIX (UNMRQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a RQ decomposition with a matrix (unmrq) */
+//@{
+inline void unmrq( char side, char trans, int m, int n, int k, const complex<float>* A, int lda,
+ const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work,
+ int lwork, int* info );
+
+inline void unmrq( char side, char trans, int m, int n, int k, const complex<double>* A, int lda,
+ const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work,
+ int lwork, int* info );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the single precision Q from a RQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the RQ decomposed single precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the single precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the RQ decomposition of the sgerqf()
+// function with the given general single precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|---------------|---------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | ctrans(Q) * C | C * ctrans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the cunmrq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unmrq( char side, char trans, int m, int n, int k, const complex<float>* A, int lda,
+ const complex<float>* tau, complex<float>* C, int ldc, complex<float>* work,
+ int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+ cunmrq_( &side, &trans, &m, &n, &k,
+ const_cast<float*>( reinterpret_cast<const float*>( A ) ), &lda,
+ const_cast<float*>( reinterpret_cast<const float*>( tau ) ),
+ reinterpret_cast<float*>( C ), &ldc, reinterpret_cast<float*>( work ),
+ &lwork, info );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a RQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param m The number of rows of the matrix \a C \f$[0..\infty)\f$.
+// \param n The number of columns of the matrix \a C \f$[0..\infty)\f$.
+// \param k The number of elementary reflectors, whose product defines the matrix \a Q.
+// \param A Pointer to the first element of the RQ decomposed double precision column-major matrix.
+// \param lda The total number of elements between two columns of the matrix \a A \f$[0..\infty)\f$.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \param C Pointer to the first element of the double precision column-major matrix multiplicator.
+// \param ldc The total number of elements between two columns of the matrix \a C \f$[0..\infty)\f$.
+// \param work Auxiliary array; size >= max( 1, \a lwork ).
+// \param lwork The dimension of the array \a work.
+// \param info Return code of the function call.
+// \return void
+//
+// This function multiplies the \a Q matrix resulting from the RQ decomposition of the sgerqf()
+// function with the given general double precision \a m-by-\a n matrix \a C. Depending on the
+// settings of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|---------------|---------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | ctrans(Q) * C | C * ctrans(Q)
+ \endcode
+
+// In case \a side is specified as \c 'L', the \a Q matrix is expected to be of size \a m-by-\a m,
+// in case \a side is set to \c 'R', \a Q is expected to be of size \a n-by-\a n.
+//
+// The \a info argument provides feedback on the success of the function call:
+//
+// - = 0: The decomposition finished successfully.
+// - < 0: The i-th argument had an illegal value.
+//
+// For more information on the zunmrq() function, see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+inline void unmrq( char side, char trans, int m, int n, int k, const complex<double>* A, int lda,
+ const complex<double>* tau, complex<double>* C, int ldc, complex<double>* work,
+ int lwork, int* info )
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+ zunmrq_( &side, &trans, &m, &n, &k,
+ const_cast<double*>( reinterpret_cast<const double*>( A ) ), &lda,
+ const_cast<double*>( reinterpret_cast<const double*>( tau ) ),
+ reinterpret_cast<double*>( C ), &ldc, reinterpret_cast<double*>( work ),
+ &lwork, info );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/gelqf.h b/src/cpu/blaze/math/lapack/gelqf.h
new file mode 100644
index 00000000..ca273a67
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/gelqf.h
@@ -0,0 +1,152 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/gelqf.h
+// \brief Header file for the LAPACK LQ decomposition functions (gelqf)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GELQF_H_
+#define _BLAZE_MATH_LAPACK_GELQF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/gelqf.h>
+#include <blaze/math/lapack/clapack/geqrf.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LQ DECOMPOSITION FUNCTIONS (GELQF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LQ decomposition functions (gelqf) */
+//@{
+template< typename MT, bool SO >
+inline void gelqf( DenseMatrix<MT,SO>& A, ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the LQ decomposition of the given dense matrix.
+// \ingroup lapack_decomposition
+//
+// \param A The matrix to be decomposed.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function performs the dense matrix LQ decomposition of a general \a m-by-\a n matrix
+// based on the LAPACK gelqf() functions. Note that this function can only be used for general,
+// non-adapted matrices with \c float, \c double, \c complex<float>, or \c complex<double> element
+// type. The attempt to call the function with any adapted matrix or matrices of any other element
+// type results in a compile time error!\n
+//
+// In case of a column-major matrix, the resulting decomposition has the form
+
+ \f[ A = L \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) . . . H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:n)</tt> is stored on exit in <tt>A(i,i+1:n)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and below the diagonal of the matrix contain the
+// \a m-by-min(\a m,\a n) lower trapezoidal matrix \c L (\c L is lower triangular if \a m <= \a n);
+// the elements above the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// For more information on the gelqf() functions (i.e. sgelqf(), dgelqf(), cgelqf(), and zgelqf())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void gelqf( DenseMatrix<MT,SO>& A, ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 ) {
+ return;
+ }
+
+ int lwork( m*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ gelqf( m, n, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ geqrf( m, n, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for LQ decomposition" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/geqlf.h b/src/cpu/blaze/math/lapack/geqlf.h
new file mode 100644
index 00000000..e73fc9df
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/geqlf.h
@@ -0,0 +1,153 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/geqlf.h
+// \brief Header file for the LAPACK QL decomposition functions (geqlf)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GEQLF_H_
+#define _BLAZE_MATH_LAPACK_GEQLF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/geqlf.h>
+#include <blaze/math/lapack/clapack/gerqf.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK QL DECOMPOSITION FUNCTIONS (GEQLF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK QL decomposition functions (geqlf) */
+//@{
+template< typename MT, bool SO >
+inline void geqlf( DenseMatrix<MT,SO>& A, ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QL decomposition of the given dense matrix.
+// \ingroup lapack_decomposition
+//
+// \param A The matrix to be decomposed.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function performs the dense matrix QL decomposition of a general \a m-by-\a n matrix
+// based on the LAPACK geqlf() functions. Note that this function can only be used for general,
+// non-adapted matrices with \c float, \c double, \c complex<float>, or \c complex<double> element
+// type. The attempt to call the function with any adapted matrix or matrices of any other element
+// type results in a compile time error!\n
+//
+// In case of a column-major matrix, the resulting decomposition has the form
+
+ \f[ A = Q \cdot L, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(k) ... H(2) H(1) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(m-k+i+1:m) = 0</tt> and
+// <tt>v(m-k+i) = 1</tt>. <tt>v(1:m-k+i-1)</tt> is stored on exit in <tt>A(1:m-k+i-1,n-k+i)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m >= \a n, the lower triangle of the subarray
+// A(m-n+1:m,1:n) contains the \a n-by-\a n lower triangular matrix \c L and in case \a m <= \a n,
+// the elements on and below the (\a n-\a m)-th subdiagonal contain the \a m-by-\a n lower
+// trapezoidal matrix \c L; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// For more information on the geqlf() functions (i.e. sgeqlf(), dgeqlf(), cgeqlf(), and zgeqlf())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void geqlf( DenseMatrix<MT,SO>& A, ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 ) {
+ return;
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ geqlf( m, n, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ gerqf( m, n, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for QL decomposition" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/geqp3.h b/src/cpu/blaze/math/lapack/geqp3.h
new file mode 100644
index 00000000..3498a1bc
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/geqp3.h
@@ -0,0 +1,45 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/geqp3.h
+// \brief Header file for the LAPACK QR decomposition functions (geqp3)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GEQP3_H_
+#define _BLAZE_MATH_LAPACK_GEQP3_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/lapack/clapack/geqp3.h>
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/geqrf.h b/src/cpu/blaze/math/lapack/geqrf.h
new file mode 100644
index 00000000..94dc9f1e
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/geqrf.h
@@ -0,0 +1,152 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/geqrf.h
+// \brief Header file for the LAPACK QR decomposition functions (geqrf)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GEQRF_H_
+#define _BLAZE_MATH_LAPACK_GEQRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/gelqf.h>
+#include <blaze/math/lapack/clapack/geqrf.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK QR DECOMPOSITION FUNCTIONS (GEQRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK QR decomposition functions (geqrf) */
+//@{
+template< typename MT, bool SO >
+inline void geqrf( DenseMatrix<MT,SO>& A, ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the QR decomposition of the given dense matrix.
+// \ingroup lapack_decomposition
+//
+// \param A The matrix to be decomposed.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function performs the dense matrix QR decomposition of a general \a m-by-\a n matrix
+// based on the LAPACK geqrf() functions. Note that this function can only be used for general,
+// non-adapted matrices with \c float, \c double, \c complex<float>, or \c complex<double> element
+// type. The attempt to call the function with any adapted matrix or matrices of any other element
+// type results in a compile time error!\n
+//
+// In case of a column-major matrix, the resulting decomposition has the form
+
+ \f[ A = Q \cdot R, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(0:i-1) = 0</tt> and
+// <tt>v(i) = 1</tt>. <tt>v(i+1:m)</tt> is stored on exit in <tt>A(i+1:m,i)</tt>, and \c tau
+// in \c tau(i). Thus on exit the elements on and above the diagonal of the matrix contain the
+// min(\a m,\a n)-by-\a n upper trapezoidal matrix \c R (\c R is upper triangular if \a m >= \a n);
+// the elements below the diagonal, with the array \c tau, represent the orthogonal matrix \c Q
+// as a product of min(\a m,\a n) elementary reflectors.
+//
+// For more information on the geqrf() functions (i.e. sgeqrf(), dgeqrf(), cgeqrf(), and zgeqrf())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void geqrf( DenseMatrix<MT,SO>& A, ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 ) {
+ return;
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ geqrf( m, n, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ gelqf( m, n, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for QR decomposition" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/gerqf.h b/src/cpu/blaze/math/lapack/gerqf.h
new file mode 100644
index 00000000..25e1e92b
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/gerqf.h
@@ -0,0 +1,153 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/gerqf.h
+// \brief Header file for the LAPACK RQ decomposition functions (gerqf)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GERQF_H_
+#define _BLAZE_MATH_LAPACK_GERQF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/geqlf.h>
+#include <blaze/math/lapack/clapack/gerqf.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK RQ DECOMPOSITION FUNCTIONS (GERQF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK RQ decomposition functions (gerqf) */
+//@{
+template< typename MT, bool SO >
+inline void gerqf( DenseMatrix<MT,SO>& A, ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the RQ decomposition of the given dense matrix.
+// \ingroup lapack_decomposition
+//
+// \param A The matrix to be decomposed.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function performs the dense matrix RQ decomposition of a general \a m-by-\a n matrix
+// based on the LAPACK gerqf() functions. Note that this function can only be used for general,
+// non-adapted matrices with \c float, \c double, \c complex<float>, or \c complex<double> element
+// type. The attempt to call the function with any adapted matrix or matrices of any other element
+// type results in a compile time error!\n
+//
+// In case of a column-major matrix, the resulting decomposition has the form
+
+ \f[ A = R \cdot Q, \f]
+
+// where the \c Q is represented as a product of elementary reflectors
+
+ \f[ Q = H(1) H(2) . . . H(k) \texttt{, with k = min(m,n).} \f]
+
+// Each H(i) has the form
+
+ \f[ H(i) = I - tau \cdot v \cdot v^T, \f]
+
+// where \c tau is a real scalar, and \c v is a real vector with <tt>v(n-k+i+1:n) = 0</tt> and
+// <tt>v(n-k+i) = 1</tt>. <tt>v(1:n-k+i-1)</tt> is stored on exit in <tt>A(m-k+i,1:n-k+i-1)</tt>,
+// and \c tau in \c tau(i). Thus in case \a m <= \a n, the upper triangle of the subarray
+// A(1:m,n-m+1:n) contains the \a m-by-\a m upper triangular matrix \c R and in case \a m >= \a n,
+// the elements on and above the (\a m-\a n)-th subdiagonal contain the \a m-by-\a n upper
+// trapezoidal matrix \c R; the remaining elements in combination with the array \c tau represent
+// the orthogonal matrix \c Q as a product of min(\a m,\a n) elementary reflectors.
+//
+// For more information on the gerqf() functions (i.e. sgerqf(), dgerqf(), cgerqf(), and zgerqf())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void gerqf( DenseMatrix<MT,SO>& A, ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 ) {
+ return;
+ }
+
+ int lwork( m*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ gerqf( m, n, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ geqlf( m, n, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for RQ decomposition" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/gesv.h b/src/cpu/blaze/math/lapack/gesv.h
new file mode 100644
index 00000000..c9bbafbe
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/gesv.h
@@ -0,0 +1,273 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/gesv.h
+// \brief Header file for the LAPACK general linear system solver functions (gesv)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GESV_H_
+#define _BLAZE_MATH_LAPACK_GESV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/gesv.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK GENERAL LINEAR SYSTEM FUNCTIONS (GESV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK general linear system functions (gesv) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void gesv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, int* ipiv );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void gesv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a general linear system of equations (\f$ A*x=b \f$).
+// \ingroup lapack_solver
+//
+// \param A The column-major system matrix.
+// \param b The right-hand side vector.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function uses the LAPACK gesv() functions to compute the solution to the system of general
+// linear equations:
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the general system matrix \a A n-by-n matrix and \a x and \a b are n-dimensional
+// vectors. Note that the function only works for general, non-adapted matrices with \c float,
+// \c double, \c complex<float>, or \c complex<double> element type. The attempt to call the
+// function with adaptors or matrices of any other element type results in a compile time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations and \a A has been decomposed by means of an LU decomposition with partial pivoting
+// and row interchanges. The decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix, and \c U is an upper
+// triangular matrix. \c L is stored in the lower part of \a A and \c U is stored in the upper
+// part. The unit diagonal elements of \c L are not stored. The factored form of \a A is then
+// used to solve the system of equations.
+//
+// The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given system matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the gesv() functions (i.e. sgesv(), dgesv(), cgesv(), and zgesv()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void gesv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT>, ElementType_<VT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ gesv( n, nrhs, (~A).data(), lda, ipiv, (~b).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid function argument" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a general linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param A The column-major system matrix.
+// \param B The matrix of right-hand sides.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function uses the LAPACK gesv() functions to compute the solution to the general system of
+// linera equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the general system matrix \a A is a n-by-n matrix and \a X and \a B are either
+// row-major m-by-n matrices or column-major n-by-m matrices. Note that the function only works for
+// general, non-adapted matrices with \c float, \c double, \c complex<float>, or \c complex<double>
+// element type. The attempt to call the function with adaptors or matrices of any other element
+// type results in a compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solutions of the linear system
+// of equations and \a A has been decomposed by means of an LU decomposition with partial pivoting
+// and row interchanges. The decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c P is a permutation matrix, \c L is a lower unitriangular matrix, and \c U is an upper
+// triangular matrix. \c L is stored in the lower part of \a A and \c U is stored in the upper
+// part. The unit diagonal elements of \c L are not stored. The factored form of \a A is then
+// used to solve the system of equations.
+//
+// The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the sizes of the two given matrices do not match;
+// - ... the given system matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the gesv() functions (i.e. sgesv(), dgesv(), cgesv(), and zgesv()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void gesv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ gesv( n, nrhs, (~A).data(), lda, ipiv, (~B).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid function argument" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/getrf.h b/src/cpu/blaze/math/lapack/getrf.h
new file mode 100644
index 00000000..6d7b72b9
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/getrf.h
@@ -0,0 +1,147 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/getrf.h
+// \brief Header file for the LAPACK LU decomposition functions (getrf)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GETRF_H_
+#define _BLAZE_MATH_LAPACK_GETRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/getrf.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LU DECOMPOSITION FUNCTIONS (GETRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LU decomposition functions (getrf) */
+//@{
+template< typename MT, bool SO >
+inline void getrf( DenseMatrix<MT,SO>& A, int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief LAPACK kernel for the LU decomposition of the given dense general matrix.
+// \ingroup lapack_decomposition
+//
+// \param A The matrix to be decomposed.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \return void
+//
+// This function performs the dense matrix LU decomposition of a general m-by-n matrix based
+// on the LAPACK \c getrf() functions, which use partial pivoting with row/column interchanges.
+// Note that the function only works for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// adaptors or matrices of any other element type results in a compile time error!\n
+//
+// In case of a column-major matrix, the resulting decomposition has the form
+
+ \f[ A = P \cdot L \cdot U, \f]
+
+// where \c L is a lower unitriangular matrix (lower trapezoidal if \a m > \a n), \c U is an upper
+// triangular matrix (upper trapezoidal if \a m < \a n), and \c P is an m-by-m permutation matrix,
+// which represents the pivoting indices for the applied row interchanges.
+//
+// In case of a row-major matrix, the resulting decomposition has the form
+
+ \f[ A = L \cdot U \cdot P, \f]
+
+// where \c P is an n-by-n permutation matrix, which represents the pivoting indices for the applied
+// column interchanges, \c L is a lower triangular matrix (lower trapezoidal if \a m > \a n), and
+// \c U is an upper unitriangular matrix (upper trapezoidal if \a m < \a n).
+//
+// The resulting decomposition is stored within the matrix \a A: \c L is stored in the lower part
+// of \a A and \c U is stored in the upper part. The unit diagonal elements of \c L or \c U are
+// not stored.
+//
+// For more information on the getrf() functions (i.e. sgetrf(), dgetrf(), cgetrf(), and zgetrf())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note The LU decomposition will never fail, even for singular matrices. However, in case of a
+// singular matrix the resulting decomposition cannot be used for a matrix inversion or solving
+// a linear system of equations.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void getrf( DenseMatrix<MT,SO>& A, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 ) {
+ return;
+ }
+
+ getrf( m, n, (~A).data(), lda, ipiv, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for LU decomposition" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/getri.h b/src/cpu/blaze/math/lapack/getri.h
new file mode 100644
index 00000000..7f996c36
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/getri.h
@@ -0,0 +1,147 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/getri.h
+// \brief Header file for the LAPACK LU-based matrix inversion functionality (getri)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GETRI_H_
+#define _BLAZE_MATH_LAPACK_GETRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/getri.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LU-BASED INVERSION FUNCTIONS (GETRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LU-based inversion functions (getri) */
+//@{
+template< typename MT, bool SO >
+inline void getri( DenseMatrix<MT,SO>& A, const int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense general matrix.
+// \ingroup lapack_inversion
+//
+// \param A The matrix to be inverted.
+// \param ipiv Auxiliary array for the pivot indices; size >= min( \a m, \a n ).
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function performs the dense matrix inversion based on the LAPACK getri() functions for
+// matrices that have already been factorized by the getrf() functions. Note that the function
+// only works for general, non-adapted matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with adaptors or matrices
+// of any other element type results in a compile time error!
+//
+// The function fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the getri() functions (i.e. sgetri(), dgetri(), cgetri(), and zgetri())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void getri( DenseMatrix<MT,SO>& A, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).columns() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ getri( n, (~A).data(), lda, ipiv, work.get(), lwork, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for matrix inversion" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/getrs.h b/src/cpu/blaze/math/lapack/getrs.h
new file mode 100644
index 00000000..07a9c3c3
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/getrs.h
@@ -0,0 +1,336 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/getrs.h
+// \brief Header file for the LAPACK general backward substitution functionality (getrs)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_GETRS_H_
+#define _BLAZE_MATH_LAPACK_GETRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/getrs.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LU-BASED SUBSTITUTION FUNCTIONS (GETRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LU-based substitution functions (getrs) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void getrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char trans, const int* ipiv );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void getrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ char trans, const int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a general linear system of equations
+// (\f$ A*x=b \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param b The right-hand side vector.
+// \param trans \c 'N' for \f$ A*x=b \f$, \c 'T' for \f$ A^T*x=b \f$, and \c C for \f$ A^H*x=b \f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function uses the LAPACK getrs() functions to perform the substitution step to compute
+// the solution to the general system of linear equations:
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the general system matrix \a A is a n-by-n matrix that has already been
+// factorized by the getrf() functions and \a x and \a b are n-dimensional vectors. Note that the
+// function only works for general, non-adapted matrices with \c float, \c double, \c complex<float>,
+// or \c complex<double> element type. The attempt to call the function with adaptors or matrices
+// of any other element type results in a compile time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a trans argument is neither 'N' nor 'T' nor 'C'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ getrf( D, ipiv.data() );
+ getrs( D, x, 'N', ipiv.data() );
+
+ assert( A * x == b );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ getrf( D, ipiv.data() );
+ getrs( D, x, 'N', ipiv.data() );
+
+ assert( trans( A ) * x == b );
+ \endcode
+
+// For more information on the getrs() functions (i.e. sgetrs(), dgetrs(), cgetrs(), and zgetrs()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void getrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char trans, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ getrs( trans, n, nrhs, (~A).data(), lda, ipiv, (~b).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a general linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param trans \c 'N' for \f$ A*X=B \f$, \c 'T' for \f$ A^T*X=B \f$, and \c C for \f$ A^H*X=B \f$.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This function uses the LAPACK getrs() functions to perform the substitution step to compute
+// the solution to the general system of linear equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the general system matrix \a A is a n-by-n matrix that has already been
+// factorized by the getrf() functions and \a X and \a B are either row-major m-by-n matrices
+// or column-major n-by-m matrices. Note that the function only works for general, non-adapted
+// matrices with \c float, \c double, \c complex<float>, or \c complex<double> element type. The
+// attempt to call the function with adaptors or matrices of any other element type results in a
+// compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solutions of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a trans argument is neither 'N' nor 'T' nor 'C';
+// - ... the sizes of the two given matrices do not match.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,columnMajor> B( 2UL, 4UL ); // The right-hand side matrix B
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,columnMajor> X( B ); // Temporary matrix for the solution
+
+ getrf( D, ipiv.data() );
+ getrs( D, X, 'N', ipiv.data() );
+
+ assert( A * X == B );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,rowMajor> B( 2UL, 4UL ); // The right-hand side matrix B
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,rowMajor> X( B ); // Temporary matrix for the solution
+
+ getrf( D, ipiv.data() );
+ getrs( D, X, 'N', ipiv.data() );
+
+ assert( trans( A ) * trans( X ) == trans( B ) );
+ \endcode
+
+// For more information on the getrs() functions (i.e. sgetrs(), dgetrs(), cgetrs(), and zgetrs()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void getrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ char trans, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ getrs( trans, n, nrhs, (~A).data(), lda, ipiv, (~B).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/hesv.h b/src/cpu/blaze/math/lapack/hesv.h
new file mode 100644
index 00000000..1015d2d5
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/hesv.h
@@ -0,0 +1,314 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/hesv.h
+// \brief Header file for the LAPACK Hermitian indefinite linear system solver functions (hesv)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_HESV_H_
+#define _BLAZE_MATH_LAPACK_HESV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/hesv.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK HERMITIAN INDEFINITE LINEAR SYSTEM FUNCTIONS (HESV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK Hermitian indefinite linear system functions (hesv) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void hesv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, int* ipiv );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void hesv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a Hermitian indefinite linear system of equations (\f$ A*x=b \f$).
+// \ingroup lapack_solver
+//
+// \param A The column-major system matrix.
+// \param b The right-hand side vector.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function uses the LAPACK hesv() functions to compute the solution to the Hermitian
+// indefinite system of linear equations;
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the Hermitian indefinite system matrix \a A is a n-by-n matrix and \a x and
+// \a b are n-dimensional vectors. Note that the function only works for general, non-adapted
+// matrices with \c float, \c double, \c complex<float>, or \c complex<double> element type.
+// The attempt to call the function with adaptors or matrices of any other element type results
+// in a compile time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations and \a A has been decomposed by means of the Bunch-Kaufman decomposition. The
+// decomposition has the form
+
+ \f[ A = U D U^{H} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given system matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the hesv() functions (i.e. chesv() and zhesv()) see the LAPACK online
+// documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void hesv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT>, ElementType_<VT> );
+
+ typedef ElementType_<MT> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ hesv( uplo, n, nrhs, (~A).data(), lda, ipiv, (~b).data(), ldb, work.get(), lwork, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid function argument" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a Hermitian indefinite linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function uses the LAPACK hesv() functions to compute the solution to the Hermitian
+// indefinite system of linear equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the Hermitian indefinite system matrix \a A is a n-by-n matrix and \a X and
+/ \a B are either row-major m-by-n matrices or column-major n-by-m matrices. Note that the function
+// only works for general, non-adapted matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with adaptors or matrices of
+// any other element type results in a compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solution of the linear system
+// of equations and \a A has been decomposed by means of a Bunch-Kaufman decomposition. The
+// decomposition has the form
+
+ \f[ A = U D U^{H} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the sizes of the two given matrices do not match;
+// - ... the given system matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the hesv() functions (i.e. chesv() and zhesv()) see the LAPACK online
+// documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void hesv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ char uplo, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ hesv( uplo, n, nrhs, (~A).data(), lda, ipiv, (~B).data(), ldb, work.get(), lwork, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid function argument" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/hetrf.h b/src/cpu/blaze/math/lapack/hetrf.h
new file mode 100644
index 00000000..79b15a6e
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/hetrf.h
@@ -0,0 +1,161 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/hetrf.h
+// \brief Header file for the LAPACK Hermitian matrix decomposition functionality (hetrf)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_HETRF_H_
+#define _BLAZE_MATH_LAPACK_HETRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/hetrf.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LDLH DECOMPOSITION FUNCTIONS (HETRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLH decomposition functions (hetrf) */
+//@{
+template< typename MT, bool SO >
+inline void hetrf( DenseMatrix<MT,SO>& A, char uplo, int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the decomposition of the given dense Hermitian indefinite matrix.
+// \ingroup lapack_decomposition
+//
+// \param A The matrix to be decomposed.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+//
+// This function performs the dense matrix decomposition of a Hermitian indefinite matrix based
+// on the LAPACK hetrf() functions, which use the Bunch-Kaufman diagonal pivoting method. Note
+// that the function only works for general, non-adapted matrices with \c complex<float> or
+// \c complex<double> element type. The attempt to call the function with any adapted matrix
+// or matrices of any other element type results in a compile time error!\n
+//
+// The decomposition has the form
+
+ \f[ A = U D U^{H} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The function fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// For more information on the hetrf() functions (i.e. chetrf() and zhetrf()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void hetrf( DenseMatrix<MT,SO>& A, char uplo, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ hetrf( uplo, n, (~A).data(), lda, ipiv, work.get(), lwork, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for matrix decomposition" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/hetri.h b/src/cpu/blaze/math/lapack/hetri.h
new file mode 100644
index 00000000..70fc3462
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/hetri.h
@@ -0,0 +1,159 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/hetri.h
+// \brief Header file for the LAPACK Hermitian matrix inversion functionality (hetri)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_HETRI_H_
+#define _BLAZE_MATH_LAPACK_HETRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/hetri.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LDLH-BASED INVERSION FUNCTIONS (HETRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLH-based inversion functions (hetri) */
+//@{
+template< typename MT, bool SO >
+inline void hetri( DenseMatrix<MT,SO>& A, char uplo, const int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense Hermitian indefinite matrix.
+// \ingroup lapack_inversion
+//
+// \param A The triangular matrix to be inverted.
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function performs the dense matrix inversion based on the LAPACK hetri() functions for
+// Hermitian indefinite matrices that have already been factorized by the hetrf() functions.
+// Note that the function only works for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// adaptors or matrices of any other element type results in a compile time error!
+//
+// The function fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the hetri() functions (i.e. chetri() and zhetri()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void hetri( DenseMatrix<MT,SO>& A, char uplo, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).columns() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ const std::unique_ptr<ET[]> work( new ET[n] );
+
+ hetri( uplo, n, (~A).data(), lda, ipiv, work.get(), &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for matrix inversion" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/hetrs.h b/src/cpu/blaze/math/lapack/hetrs.h
new file mode 100644
index 00000000..76b95470
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/hetrs.h
@@ -0,0 +1,343 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/hetrs.h
+// \brief Header file for the LAPACK symmetric indefinite backward substitution functionality (hetrs)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_HETRS_H_
+#define _BLAZE_MATH_LAPACK_HETRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/hetrs.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LDLH-BASED SUBSTITUTION FUNCTIONS (HETRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLH-based substitution functions (hetrs) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void hetrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, const int* ipiv );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void hetrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ char uplo, const int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite linear
+// system of equations (\f$ A*x=b \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param b The right-hand side vector.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+//
+// This function uses the LAPACK hetrs() functions to perform the substitution step to compute
+// the solution to the system of symmetric indefinite linear equations:
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the symmetric indefinite system matrix \a A is a n-by-n matrix that has already
+// been factorized by the hetrf() functions and \a x and \a b are n-dimensional vectors. Note that
+// the function only works for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// adaptors or matrices of any other element type results in a compile time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ hetrf( D, 'L', ipiv.data() );
+ hetrs( D, x, 'L', ipiv.data() );
+
+ assert( A * x == b );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ hetrf( D, 'L', ipiv.data() );
+ hetrs( D, x, 'L', ipiv.data() );
+
+ assert( trans( A ) * x == b );
+ \endcode
+
+// For more information on the hetrs() functions (i.e. chetrs() and zhetrs()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void hetrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT>, ElementType_<VT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ hetrs( uplo, n, nrhs, (~A).data(), lda, ipiv, (~b).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite linear
+// system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This function uses the LAPACK hetrs() functions to perform the substitution step to compute
+// the solution to a system of symmetric indefinite linear equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the symmetric indefinite system matrix \a A is a n-by-n matrix that has already
+// been factorized by the hetrf() functions and \a X and \a B are either row-major m-by-n matrices
+// or column-major n-by-m matrices. Note that the function only works for general, non-adapted
+// matrices with \c float, \c double, \c complex<float>, or \c complex<double> element type. The
+// attempt to call the function with adaptors or matrices of any other element type results in a
+// compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the sizes of the two given matrices do not match;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,columnMajor> B( 2UL, 4UL ); // The right-hand side matrix B
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,columnMajor> X( B ); // Temporary matrix for the solution
+
+ hetrf( D, 'L' );
+ hetrs( D, X, 'L' );
+
+ assert( A * X == B );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::rowMajor;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,rowMajor> B( 4UL, 2UL ); // The right-hand side matrix B
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,rowMajor> X( B ); // Temporary matrix for the solution
+
+ hetrf( D, 'L' );
+ hetrs( D, X, 'L' );
+
+ assert( trans( A ) * trans( X ) == trans( B ) );
+ \endcode
+
+// For more information on the hetrs() functions (i.e. chetrs() and zhetrs()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void hetrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ hetrs( uplo, n, nrhs, (~A).data(), lda, ipiv, (~B).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/orglq.h b/src/cpu/blaze/math/lapack/orglq.h
new file mode 100644
index 00000000..fb9311e1
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/orglq.h
@@ -0,0 +1,154 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/orglq.h
+// \brief Header file for the LAPACK functions to reconstruct Q from a LQ decomposition (orglq)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_ORGLQ_H_
+#define _BLAZE_MATH_LAPACK_ORGLQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/orglq.h>
+#include <blaze/math/lapack/clapack/orgqr.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Builtin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A LQ DECOMPOSITION (ORGLQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a LQ decomposition (orglq) */
+//@{
+template< typename MT, bool SO >
+inline void orglq( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a LQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param A The decomposed matrix.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function reconstructs the orthogonal matrix \a Q of a LQ decomposition based on the LAPACK
+// orglq() functions from matrices that have already been LQ factorized by the gelqf() functions.
+// Note that this function can only be used for general, non-adapted matrices with \c float or
+// \c double element type. The attempt to call the function with any adapted matrix or matrices
+// of any other element type results in a compile time error!\n
+//
+// The min(\a m,\a n)-by-\a n \a Q matrix is stored within the given matrix \a A:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ gelqf( A, tau.data() ); // Performing the LQ decomposition
+ orglq( A, tau.data() ); // Reconstructing the Q matrix
+
+ const int m( A.rows() );
+ const int n( A.columns() );
+
+ DynamicMatrix<double,columnMajor> Q( submatrix( A, 0UL, 0UL, min(m,n), n ) );
+ \endcode
+
+// For more information on the orglq() functions (i.e. sorglq() and dorglq()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT, bool SO >
+inline void orglq( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int k ( min( m, n ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( k == 0 ) {
+ return;
+ }
+
+ int lwork( k*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ orglq( k, n, k, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ orgqr( m, k, k, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q reconstruction" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/orgql.h b/src/cpu/blaze/math/lapack/orgql.h
new file mode 100644
index 00000000..9dfeea44
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/orgql.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/orgql.h
+// \brief Header file for the LAPACK functions to reconstruct Q from a QL decomposition (orgql)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_ORGQL_H_
+#define _BLAZE_MATH_LAPACK_ORGQL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/orgql.h>
+#include <blaze/math/lapack/clapack/orgrq.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Builtin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A QL DECOMPOSITION (ORGQL)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a QL decomposition (orgql) */
+//@{
+template< typename MT, bool SO >
+inline void orgql( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QL decomposition.
+// \ingroup lapack_decomposition
+//
+// \param A The decomposed matrix.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function reconstructs the orthogonal matrix \a Q of a QL decomposition based on the LAPACK
+// orgql() functions from matrices that have already been QL factorized by the geqlf() functions.
+// Note that this function can only be used for general, non-adapted matrices with \c float or
+// \c double element type. The attempt to call the function with any adapted matrix or matrices
+// of any other element type results in a compile time error!\n
+//
+// The \a m-by-min(\a m,\a n) \a Q matrix is stored within the given matrix \a A:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ geqlf( A, tau.data() ); // Performing the QL decomposition
+ orgql( A, tau.data() ); // Reconstructing the Q matrix
+
+ const int m( A.rows() );
+ const int n( A.columns() );
+
+ const size_t column( m < n ? n - m : 0UL )
+ DynamicMatrix<double,columnMajor> Q( submatrix( A, 0UL, column, m, min(m,n) ) );
+ \endcode
+
+// For more information on the orgql() functions (i.e. sorgql() and dorgql()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT, bool SO >
+inline void orgql( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int k ( min( m, n ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( k == 0 ) {
+ return;
+ }
+
+ int lwork( k*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ const size_t offset( ( m < n )?( n - m ):( 0UL ) );
+ orgql( m, k, k, (~A).data(offset), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ const size_t offset( ( m > n )?( m - n ):( 0UL ) );
+ orgrq( k, n, k, (~A).data()+offset, lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q reconstruction" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/orgqr.h b/src/cpu/blaze/math/lapack/orgqr.h
new file mode 100644
index 00000000..0ea9977d
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/orgqr.h
@@ -0,0 +1,154 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/orgqr.h
+// \brief Header file for the LAPACK functions to reconstruct Q from a QR decomposition (orgqr)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_ORGQR_H_
+#define _BLAZE_MATH_LAPACK_ORGQR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/orglq.h>
+#include <blaze/math/lapack/clapack/orgqr.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Builtin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A QR DECOMPOSITION (ORGQR)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a QR decomposition (orgqr) */
+//@{
+template< typename MT, bool SO >
+inline void orgqr( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QR decomposition.
+// \ingroup lapack_decomposition
+//
+// \param A The decomposed matrix.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function reconstructs the orthogonal matrix \a Q of a QR decomposition based on the LAPACK
+// orgqr() functions from matrices that have already been QR factorized by the geqrf() functions.
+// Note that this function can only be used for general, non-adapted matrices with \c float or
+// \c double element type. The attempt to call the function with any adapted matrix or matrices
+// of any other element type results in a compile time error!\n
+//
+// The \a m-by-min(\a m,\a n) \a Q matrix is stored within the given matrix \a A:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ geqrf( A, tau.data() ); // Performing the QR decomposition
+ orgqr( A, tau.data() ); // Reconstructing the Q matrix
+
+ const int m( A.rows() );
+ const int n( A.columns() );
+
+ DynamicMatrix<double,columnMajor> Q( submatrix( A, 0UL, 0UL, m, min(m,n) ) );
+ \endcode
+
+// For more information on the orgqr() functions (i.e. sorgqr() and dorgqr()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT, bool SO >
+inline void orgqr( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int k ( min( m, n ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( k == 0 ) {
+ return;
+ }
+
+ int lwork( k*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ orgqr( m, k, k, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ orglq( k, n, k, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q reconstruction" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/orgrq.h b/src/cpu/blaze/math/lapack/orgrq.h
new file mode 100644
index 00000000..b7c6e2a9
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/orgrq.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/orgrq.h
+// \brief Header file for the LAPACK functions to reconstruct Q from a RQ decomposition (orgrq)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_ORGRQ_H_
+#define _BLAZE_MATH_LAPACK_ORGRQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/orgql.h>
+#include <blaze/math/lapack/clapack/orgrq.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Builtin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A RQ DECOMPOSITION (ORGRQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a RQ decomposition (orgrq) */
+//@{
+template< typename MT, bool SO >
+inline void orgrq( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a RQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param A The decomposed matrix.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function reconstructs the orthogonal matrix \a Q of a RQ decomposition based on the LAPACK
+// orgrq() functions from matrices that have already been RQ factorized by the gerqf() functions.
+// Note that this function can only be used for general, non-adapted matrices with \c float or
+// \c double element type. The attempt to call the function with any adapted matrix or matrices
+// of any other element type results in a compile time error!\n
+//
+// The min(\a m,\a n)-by-\a n \a Q matrix is stored within the given matrix \a A:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ gerqf( A, tau.data() ); // Performing the RQ decomposition
+ orgrq( A, tau.data() ); // Reconstructing the Q matrix
+
+ const int m( A.rows() );
+ const int n( A.columns() );
+
+ const size_t row( m > n ? m - n : 0UL )
+ DynamicMatrix<double,columnMajor> Q( submatrix( A, row, 0UL, min(m,n), n ) );
+ \endcode
+
+// For more information on the orgrq() functions (i.e. sorgrq() and dorgrq()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT, bool SO >
+inline void orgrq( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int k ( min( m, n ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( k == 0 ) {
+ return;
+ }
+
+ int lwork( k*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ const size_t offset( ( m > n )?( m - n ):( 0UL ) );
+ orgrq( k, n, k, (~A).data()+offset, lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ const size_t offset( ( m < n )?( n - m ):( 0UL ) );
+ orgql( m, k, k, (~A).data(offset), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q reconstruction" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/ormlq.h b/src/cpu/blaze/math/lapack/ormlq.h
new file mode 100644
index 00000000..7c5aaa0e
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/ormlq.h
@@ -0,0 +1,201 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/ormlq.h
+// \brief Header file for the LAPACK functions to multiply Q from a LQ decomposition with a matrix (ormlq)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_ORMLQ_H_
+#define _BLAZE_MATH_LAPACK_ORMLQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/ormlq.h>
+#include <blaze/math/lapack/clapack/ormqr.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/mpl/Xor.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A LQ DECOMPOSITION WITH A MATRIX (ORMLQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a LQ decomposition with a matrix (ormlq) */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void ormlq( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a LQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param C The matrix multiplier.
+// \param A The decomposed matrix.
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+// \exception std::invalid_argument Invalid size of Q matrix.
+// \exception std::invalid_argument Invalid side argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function multiplies a square \a Q matrix resulting from the LQ decomposition of the
+// gelqf() functions with the given general \a m-by-\a n matrix \a C. Depending on the settings
+// of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// Note that the size of matrix \c C is preserved, which means that the function does not work for
+// non-square Q matrices. Therefore in case the number of rows of \a A is larger than the number
+// of columns, a \a std::invalid_argument exception is thrown. Also Note that this function can
+// only be used for general, non-adapted matrices with \c float or \c double element type. The
+// attempt to call the function with any adapted matrix or matrices of any other element type
+// results in a compile time error!
+//
+// The following code example demonstrates the use of the ormlq() function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicMatrix<double,columnMajor> C;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ gelqf( A, tau.data() ); // Performing the LQ decomposition
+ ormlq( C, A, 'R', 'N', tau.data() ); // Computing C = C * Q
+ \endcode
+
+// For more information on the ormlq() functions (i.e. sormlq() and dormlq()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void ormlq( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( (~A).rows() > (~A).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size of Q matrix" );
+ }
+
+ if( side != 'L' && side != 'R' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid side argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int m ( numeric_cast<int>( SO1 ? (~C).rows() : (~C).columns() ) );
+ int n ( numeric_cast<int>( SO1 ? (~C).columns() : (~C).rows() ) );
+ int k ( numeric_cast<int>( min( (~A).rows(), (~A).columns() ) ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldc ( numeric_cast<int>( (~C).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 || k == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( side == 'L' )?( side = 'R' ):( side = 'L' );
+ }
+
+ if( Xor< IsRowMajorMatrix<MT1>, IsRowMajorMatrix<MT2> >::value ) {
+ ( trans == 'N' )?( trans = 'T' ):( trans = 'N' );
+ }
+
+ int lwork( k*ldc );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO2 ) {
+ ormlq( side, trans, m, n, k, (~A).data(), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+ else {
+ ormqr( side, trans, m, n, k, (~A).data(), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q multiplication" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/ormql.h b/src/cpu/blaze/math/lapack/ormql.h
new file mode 100644
index 00000000..7f7088b7
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/ormql.h
@@ -0,0 +1,202 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/ormql.h
+// \brief Header file for the LAPACK functions to multiply Q from a QL decomposition with a matrix (ormql)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_ORMQL_H_
+#define _BLAZE_MATH_LAPACK_ORMQL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/ormql.h>
+#include <blaze/math/lapack/clapack/ormrq.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/mpl/Xor.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A QL DECOMPOSITION WITH A MATRIX (ORMQL)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a QL decomposition with a matrix (ormql) */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void ormql( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a QL decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param C The matrix multiplier.
+// \param A The decomposed matrix.
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+// \exception std::invalid_argument Invalid size of Q matrix.
+// \exception std::invalid_argument Invalid side argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function multiplies a square \a Q matrix resulting from the QL decomposition of the
+// geqlf() functions with the given general \a m-by-\a n matrix \a C. Depending on the settings
+// of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// Note that the size of matrix \c C is preserved, which means that the function does not work for
+// non-square Q matrices. Therefore in case the number of rows of \a A is smaller than the number
+// of columns, a \a std::invalid_argument exception is thrown. Also note that this function can
+// only be used for general, non-adapted matrices with \c float or \c double element type. The
+// attempt to call the function with any adapted matrix or matrices of any other element type
+// results in a compile time error!
+//
+// The following code example demonstrates the use of the ormql() function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicMatrix<double,columnMajor> C;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ geqlf( A, tau.data() ); // Performing the QL decomposition
+ ormql( C, A, 'R', 'N', tau.data() ); // Computing C = C * Q
+ \endcode
+
+// For more information on the ormql() functions (i.e. sormql() and dormql()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void ormql( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( (~A).rows() < (~A).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size of Q matrix" );
+ }
+
+ if( side != 'L' && side != 'R' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid side argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int m ( numeric_cast<int>( SO1 ? (~C).rows() : (~C).columns() ) );
+ int n ( numeric_cast<int>( SO1 ? (~C).columns() : (~C).rows() ) );
+ int k ( numeric_cast<int>( min( (~A).rows(), (~A).columns() ) ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldc ( numeric_cast<int>( (~C).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 || k == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( side == 'L' )?( side = 'R' ):( side = 'L' );
+ }
+
+ if( Xor< IsRowMajorMatrix<MT1>, IsRowMajorMatrix<MT2> >::value ) {
+ ( trans == 'N' )?( trans = 'T' ):( trans = 'N' );
+ }
+
+ int lwork( k*ldc );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+ const size_t offset( (~A).rows() - (~A).columns() );
+
+ if( SO2 ) {
+ ormql( side, trans, m, n, k, (~A).data()+offset, lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+ else {
+ ormrq( side, trans, m, n, k, (~A).data(offset), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q multiplication" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/ormqr.h b/src/cpu/blaze/math/lapack/ormqr.h
new file mode 100644
index 00000000..c9868d68
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/ormqr.h
@@ -0,0 +1,201 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/ormqr.h
+// \brief Header file for the LAPACK functions to multiply Q from a QR decomposition with a matrix (ormqr)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_ORMQR_H_
+#define _BLAZE_MATH_LAPACK_ORMQR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/ormlq.h>
+#include <blaze/math/lapack/clapack/ormqr.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/mpl/Xor.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A QR DECOMPOSITION WITH A MATRIX (ORMQR)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a QR decomposition with a matrix (ormqr) */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void ormqr( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a QR decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param C The matrix multiplier.
+// \param A The decomposed matrix.
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+// \exception std::invalid_argument Invalid size of Q matrix.
+// \exception std::invalid_argument Invalid side argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function multiplies a square \a Q matrix resulting from the QR decomposition of the
+// geqrf() functions with the given general \a m-by-\a n matrix \a C. Depending on the settings
+// of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// Note that the size of matrix \c C is preserved, which means that the function does not work for
+// non-square Q matrices. Therefore in case the number of rows of \a A is larger than the number
+// of columns, a \a std::invalid_argument exception is thrown. Also Note that this function can
+// only be used for general, non-adapted matrices with \c float or \c double element type. The
+// attempt to call the function with any adapted matrix or matrices of any other element type
+// results in a compile time error!
+//
+// The following code example demonstrates the use of the ormqr() function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicMatrix<double,columnMajor> C;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ geqrf( A, tau.data() ); // Performing the QR decomposition
+ ormqr( C, A, 'R', 'N', tau.data() ); // Computing C = C * Q
+ \endcode
+
+// For more information on the ormqr() functions (i.e. sormqr() and dormqr()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void ormqr( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( (~A).rows() > (~A).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size of Q matrix" );
+ }
+
+ if( side != 'L' && side != 'R' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid side argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int m ( numeric_cast<int>( SO1 ? (~C).rows() : (~C).columns() ) );
+ int n ( numeric_cast<int>( SO1 ? (~C).columns() : (~C).rows() ) );
+ int k ( numeric_cast<int>( min( (~A).rows(), (~A).columns() ) ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldc ( numeric_cast<int>( (~C).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 || k == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( side == 'L' )?( side = 'R' ):( side = 'L' );
+ }
+
+ if( Xor< IsRowMajorMatrix<MT1>, IsRowMajorMatrix<MT2> >::value ) {
+ ( trans == 'N' )?( trans = 'T' ):( trans = 'N' );
+ }
+
+ int lwork( k*ldc );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO2 ) {
+ ormqr( side, trans, m, n, k, (~A).data(), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+ else {
+ ormlq( side, trans, m, n, k, (~A).data(), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q multiplication" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/ormrq.h b/src/cpu/blaze/math/lapack/ormrq.h
new file mode 100644
index 00000000..faa48805
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/ormrq.h
@@ -0,0 +1,202 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/ormrq.h
+// \brief Header file for the LAPACK functions to multiply Q from a RQ decomposition with a matrix (ormrq)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_ORMRQ_H_
+#define _BLAZE_MATH_LAPACK_ORMRQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/ormql.h>
+#include <blaze/math/lapack/clapack/ormrq.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/mpl/Xor.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A RQ DECOMPOSITION WITH A MATRIX (ORMRQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a RQ decomposition with a matrix (ormrq) */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void ormrq( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a RQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param C The matrix multiplier.
+// \param A The decomposed matrix.
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+// \exception std::invalid_argument Invalid size of Q matrix.
+// \exception std::invalid_argument Invalid side argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function multiplies a square \a Q matrix resulting from the RQ decomposition of the
+// gerqf() functions with the given general \a m-by-\a n matrix \a C. Depending on the settings
+// of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// Note that the size of matrix \c C is preserved, which means that the function does not work for
+// non-square Q matrices. Therefore in case the number of rows of \a A is smaller than the number
+// of columns, a \a std::invalid_argument exception is thrown. Also note that this function can
+// only be used for general, non-adapted matrices with \c float or \c double element type. The
+// attempt to call the function with any adapted matrix or matrices of any other element type
+// results in a compile time error!
+//
+// The following code example demonstrates the use of the ormrq() function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicMatrix<double,columnMajor> C;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ gerqf( A, tau.data() ); // Performing the RQ decomposition
+ ormrq( C, A, 'R', 'N', tau.data() ); // Computing C = C * Q
+ \endcode
+
+// For more information on the ormrq() functions (i.e. sormrq() and dormrq()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void ormrq( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( (~A).rows() < (~A).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size of Q matrix" );
+ }
+
+ if( side != 'L' && side != 'R' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid side argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int m ( numeric_cast<int>( SO1 ? (~C).rows() : (~C).columns() ) );
+ int n ( numeric_cast<int>( SO1 ? (~C).columns() : (~C).rows() ) );
+ int k ( numeric_cast<int>( min( (~A).rows(), (~A).columns() ) ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldc ( numeric_cast<int>( (~C).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 || k == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( side == 'L' )?( side = 'R' ):( side = 'L' );
+ }
+
+ if( Xor< IsRowMajorMatrix<MT1>, IsRowMajorMatrix<MT2> >::value ) {
+ ( trans == 'N' )?( trans = 'T' ):( trans = 'N' );
+ }
+
+ int lwork( k*ldc );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+ const size_t offset( (~A).rows() - (~A).columns() );
+
+ if( SO2 ) {
+ ormrq( side, trans, m, n, k, (~A).data()+offset, lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+ else {
+ ormql( side, trans, m, n, k, (~A).data(offset), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q multiplication" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/posv.h b/src/cpu/blaze/math/lapack/posv.h
new file mode 100644
index 00000000..0d045d32
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/posv.h
@@ -0,0 +1,299 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/posv.h
+// \brief Header file for the LAPACK positive definite linear system solver functions (posv)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_POSV_H_
+#define _BLAZE_MATH_LAPACK_POSV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/posv.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK POSITIVE DEFINITE LINEAR SYSTEM FUNCTIONS (POSV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK positive definite linear system functions (posv) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void posv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void posv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a positive definite linear system of equations (\f$ A*x=b \f$).
+// \ingroup lapack_solver
+//
+// \param A The column-major system matrix.
+// \param b The right-hand side vector.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function uses the LAPACK posv() functions to compute the solution to the positive definite
+// system of linear equations:
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the positive definite system matrix \a A is a n-by-n matrix and \a x and \a b
+// are n-dimensional vectors. Note that the function only works for general, non-adapted matrices
+// with \c float, \c double, \c complex<float>, or \c complex<double> element type. The attempt
+// to call the function with adaptors or matrices of any other element type results in a compile
+// time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations and \a A has been decomposed by means of a Cholesky decomposition. The decomposition
+// has the form
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given system matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the posv() functions (i.e. sposv(), dposv(), cposv(), and zposv()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void posv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT>, ElementType_<VT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ posv( uplo, n, nrhs, (~A).data(), lda, (~b).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid function argument" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a positive definite linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function uses the LAPACK posv() functions to compute the solution to the positive definite
+// system of linear equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the positive definite system matrix \a A is a n-by-n matrix and \a X and \a B
+// are either row-major m-by-n matrices or column-major n-by-m matrices. Note that the function
+// only works for general, non-adapted matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with adaptors or matrices
+// of any other element type results in a compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solution of the linear system
+// of equations and \a A has been decomposed by means of a Cholesky decomposition. The decomposition
+// has the form
+
+ \f[ A = U^{T} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the sizes of the two given matrices do not match;
+// - ... the given system matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the posv() functions (i.e. sposv(), dposv(), cposv(), and zposv()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void posv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ posv( uplo, n, nrhs, (~A).data(), lda, (~B).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid function argument" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/potrf.h b/src/cpu/blaze/math/lapack/potrf.h
new file mode 100644
index 00000000..7ccc2122
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/potrf.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/potrf.h
+// \brief Header file for the LAPACK Cholesky decomposition functions (potrf)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_POTRF_H_
+#define _BLAZE_MATH_LAPACK_POTRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/potrf.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LLH (CHOLESKY) DECOMPOSITION FUNCTIONS (POTRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LLH (Cholesky) decomposition functions (potrf) */
+//@{
+template< typename MT, bool SO >
+inline void potrf( DenseMatrix<MT,SO>& A, char uplo );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the Cholesky decomposition of the given dense positive definite matrix.
+// \ingroup lapack_decomposition
+//
+// \param A The matrix to be decomposed.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::runtime_error Decomposition of singular matrix failed.
+//
+// This function performs the dense matrix Cholesky decomposition of a symmetric positive definite
+// matrix based on the LAPACK potrf() functions. Note that the function only works for general,
+// non-adapted matrices with \c float, \c double, \c complex<float>, or \c complex<double> element
+// type. The attempt to call the function with any adapted matrix or matrices of any other element
+// type results in a compile time error!\n
+//
+// The decomposition has the form
+
+ \f[ A = U^{H} U \texttt{ (if uplo = 'U'), or }
+ A = L L^{H} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U is an upper triangular matrix and \c L is a lower triangular matrix. The Cholesky
+// decomposition fails if ...
+//
+// - ... the given system matrix \a A is not a symmetric positive definite matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the potrf() functions (i.e. spotrf(), dpotrf(), cpotrf(), and zpotrf())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void potrf( DenseMatrix<MT,SO>& A, char uplo )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ potrf( uplo, n, (~A).data(), lda, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for Cholesky decomposition" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Decomposition of non-positive-definite matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/potri.h b/src/cpu/blaze/math/lapack/potri.h
new file mode 100644
index 00000000..2cc67037
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/potri.h
@@ -0,0 +1,154 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/potri.h
+// \brief Header file for the LAPACK matrix Cholesky-based inversion functions (potri)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ORx
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_POTRI_H_
+#define _BLAZE_MATH_LAPACK_POTRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/potri.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LLH-BASED INVERSION FUNCTIONS (POTRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LLH-based inversion functions (potri) */
+//@{
+template< typename MT, bool SO >
+inline void potri( DenseMatrix<MT,SO>& A, char uplo );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense positive definite matrix.
+// \ingroup lapack_inversion
+//
+// \param A The positive-definite matrix to be inverted.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function performs the dense matrix inversion based on the LAPACK potri() functions for
+// positive-definite matrices that have already been factorized by the potrf() functions. The
+// resulting symmetric inverse of the given matrix \a A is stored either in the lower part of
+// \a A (\a uplo = \c 'L') or in the upper part (\a uplo = \c 'U'). Note that the function only
+// works for general, non-adapted matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with adaptors or matrices
+// of any other element type results in a compile time error!
+//
+// The function fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the potri() functions (i.e. spotri(), dpotri(), cpotri(), and zpotri())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void potri( DenseMatrix<MT,SO>& A, char uplo )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).columns() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ potri( uplo, n, (~A).data(), lda, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for matrix inversion" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/potrs.h b/src/cpu/blaze/math/lapack/potrs.h
new file mode 100644
index 00000000..3cf91bb0
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/potrs.h
@@ -0,0 +1,336 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/potrs.h
+// \brief Header file for the LAPACK positive definite backward substitution functions (potrs)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_POTRS_H_
+#define _BLAZE_MATH_LAPACK_POTRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/potrs.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LLH-BASED SUBSTITUTION FUNCTIONS (POTRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LLH-based substitution functions (potrs) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void potrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void potrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a positive definite linear system
+// of equations (\f$ A*x=b \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param b The right-hand side vector.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+//
+// This function uses the LAPACK potrs() functions to perform the substitution step to compute
+// the solution to the system of positive definite linear equations:
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the positive definite system matrix \a A is a n-by-n matrix that has already
+// been factorized by the potrf() functions and \a x and \a b are n-dimensional vectors. Note
+// that the function only works for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// adaptors or matrices of any other element type results in a compile time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ potrf( D, 'L' );
+ potrs( D, x, 'L' );
+
+ assert( A * x == b );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ potrf( D, 'L' );
+ potrs( D, x, 'L' );
+
+ assert( trans( A ) * x == b );
+ \endcode
+
+// For more information on the potrs() functions (i.e. spotrs(), dpotrs(), cpotrs(), and zpotrs()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void potrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT>, ElementType_<VT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ potrs( uplo, n, nrhs, (~A).data(), lda, (~b).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a positive definite linear system
+// of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This function uses the LAPACK potrs() functions to perform the substitution step to compute
+// the solution to a system of positive definite linear equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the positive definite system matrix \a A is a n-by-n matrix that has already
+// been factorized by the potrf() functions and \a X and \a B are either row-major m-by-n matrices
+// or column-major n-by-m matrices. Note that the function only works for general, non-adapted
+// matrices with \c float, \c double, \c complex<float>, or \c complex<double> element type. The
+// attempt to call the function with adaptors or matrices of any other element type results in a
+// compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the sizes of the two given matrices do not match;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,columnMajor> B( 2UL, 4UL ); // The right-hand side matrix B
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,columnMajor> X( B ); // Temporary matrix for the solution
+
+ potrf( D, 'L' );
+ potrs( D, X, 'L' );
+
+ assert( A * X == B );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::rowMajor;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,rowMajor> B( 4UL, 2UL ); // The right-hand side matrix B
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,rowMajor> X( B ); // Temporary matrix for the solution
+
+ potrf( D, 'L' );
+ potrs( D, X, 'L' );
+
+ assert( trans( A ) * trans( X ) == trans( B ) );
+ \endcode
+
+// For more information on the potrs() functions (i.e. spotrs(), dpotrs(), cpotrs(), and zpotrs()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void potrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ potrs( uplo, n, nrhs, (~A).data(), lda, (~B).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/sysv.h b/src/cpu/blaze/math/lapack/sysv.h
new file mode 100644
index 00000000..7b7e69f5
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/sysv.h
@@ -0,0 +1,314 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/sysv.h
+// \brief Header file for the LAPACK symmetric indefinite linear system solver functions (sysv)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_SYSV_H_
+#define _BLAZE_MATH_LAPACK_SYSV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/sysv.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK SYMMETRIC INDEFINITE LINEAR SYSTEM FUNCTIONS (SYSV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK symmetric indefinite linear system functions (sysv) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void sysv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, int* ipiv );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void sysv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a symmetric indefinite linear system of equations (\f$ A*x=b \f$).
+// \ingroup lapack_solver
+//
+// \param A The column-major system matrix.
+// \param b The right-hand side vector.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function uses the LAPACK sysv() functions to compute the solution to the symmetric
+// indefinite system of linear equations;
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the symmetric indefinite system matrix \a A is a n-by-n matrix and \a x and
+// \a b are n-dimensional vectors. Note that the function only works for general, non-adapted
+// matrices with \c float, \c double, \c complex<float>, or \c complex<double> element type.
+// The attempt to call the function with adaptors or matrices of any other element type results
+// in a compile time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations and \a A has been decomposed by means of the Bunch-Kaufman decomposition. The
+// decomposition has the form
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given system matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the sysv() functions (i.e. ssysv(), dsysv(), csysv(), and zsysv()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void sysv( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT>, ElementType_<VT> );
+
+ typedef ElementType_<MT> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ sysv( uplo, n, nrhs, (~A).data(), lda, ipiv, (~b).data(), ldb, work.get(), lwork, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid function argument" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a symmetric indefinite linear system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_solver
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function uses the LAPACK sysv() functions to compute the solution to the symmetric
+// indefinite system of linear equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the symmetric indefinite system matrix \a A is a n-by-n matrix and \a X and
+/ \a B are either row-major m-by-n matrices or column-major n-by-m matrices. Note that the function
+// only works for general, non-adapted matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with adaptors or matrices of
+// any other element type results in a compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solution of the linear system
+// of equations and \a A has been decomposed by means of a Bunch-Kaufman decomposition. The
+// decomposition has the form
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched. The factored
+// form of \a A is then used to solve the system of equations.
+//
+// The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the sizes of the two given matrices do not match;
+// - ... the given system matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the sysv() functions (i.e. ssysv(), dsysv(), csysv(), and zsysv()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void sysv( DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ sysv( uplo, n, nrhs, (~A).data(), lda, ipiv, (~B).data(), ldb, work.get(), lwork, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid function argument" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/sytrf.h b/src/cpu/blaze/math/lapack/sytrf.h
new file mode 100644
index 00000000..ee522b16
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/sytrf.h
@@ -0,0 +1,161 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/sytrf.h
+// \brief Header file for the LAPACK symmetric matrix decomposition functions (sytrf)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_SYTRF_H_
+#define _BLAZE_MATH_LAPACK_SYTRF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/sytrf.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LDLT DECOMPOSITION FUNCTIONS (SYTRF)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLT decomposition functions (sytrf) */
+//@{
+template< typename MT, bool SO >
+inline void sytrf( DenseMatrix<MT,SO>& A, char uplo, int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the decomposition of the given dense symmetric indefinite matrix.
+// \ingroup lapack_decomposition
+//
+// \param A The matrix to be decomposed.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+//
+// This function performs the dense matrix decomposition of a symmetric indefinite matrix based
+// on the LAPACK sytrf() functions, which use the Bunch-Kaufman diagonal pivoting method. Note
+// that the function only works for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// any adapted matrix or matrices of any other element type results in a compile time error!\n
+//
+// The decomposition has the form
+
+ \f[ A = U D U^{T} \texttt{ (if uplo = 'U'), or }
+ A = L D L^{T} \texttt{ (if uplo = 'L'), } \f]
+
+// where \c U (or \c L) is a product of permutation and unit upper (lower) triangular matrices,
+// and \c D is symmetric and block diagonal with 1-by-1 and 2-by-2 diagonal blocks. The resulting
+// decomposition is stored within \a A: In case \a uplo is set to \c 'L' the result is stored in
+// the lower part of the matrix and the upper part remains untouched, in case \a uplo is set to
+// \c 'U' the result is stored in the upper part and the lower part remains untouched.
+//
+// The function fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// For more information on the sytrf() functions (i.e. ssytrf(), dsytrf(), csytrf(), and zsytrf())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void sytrf( DenseMatrix<MT,SO>& A, char uplo, int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ int lwork( n*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ sytrf( uplo, n, (~A).data(), lda, ipiv, work.get(), lwork, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for matrix decomposition" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/sytri.h b/src/cpu/blaze/math/lapack/sytri.h
new file mode 100644
index 00000000..0abbc02f
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/sytri.h
@@ -0,0 +1,158 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/sytri.h
+// \brief Header file for the LAPACK symmetric matrix inversion functions (sytri)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_SYTRI_H_
+#define _BLAZE_MATH_LAPACK_SYTRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/sytri.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LDLT-BASED INVERSION FUNCTIONS (SYTRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLT-based inversion functions (sytri) */
+//@{
+template< typename MT, bool SO >
+inline void sytri( DenseMatrix<MT,SO>& A, char uplo, const int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense symmetric indefinite matrix.
+// \ingroup lapack_inversion
+//
+// \param A The triangular matrix to be inverted.
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function performs the dense matrix inversion based on the LAPACK sytri() functions for
+// symmetric indefinite matrices that have already been factorized by the sytrf() functions.
+// Note that the function only works for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// adaptors or matrices of any other element type results in a compile time error!
+//
+// The function fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the sytri() functions (i.e. ssytri(), dsytri(), csytri(), and zsytri())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void sytri( DenseMatrix<MT,SO>& A, char uplo, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).columns() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ const std::unique_ptr<ET[]> work( new ET[n] );
+
+ sytri( uplo, n, (~A).data(), lda, ipiv, work.get(), &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for matrix inversion" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/sytrs.h b/src/cpu/blaze/math/lapack/sytrs.h
new file mode 100644
index 00000000..9f825cf4
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/sytrs.h
@@ -0,0 +1,343 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/sytrs.h
+// \brief Header file for the LAPACK symmetric indefinite backward substitution functions (sytrs)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_SYTRS_H_
+#define _BLAZE_MATH_LAPACK_SYTRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/sytrs.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK LDLT-BASED SUBSTITUTION FUNCTIONS (SYTRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK LDLT-based substitution functions (sytrs) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void sytrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, const int* ipiv );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void sytrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ char uplo, const int* ipiv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite linear
+// system of equations (\f$ A*x=b \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param b The right-hand side vector.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+//
+// This function uses the LAPACK sytrs() functions to perform the substitution step to compute
+// the solution to the system of symmetric indefinite linear equations:
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the symmetric indefinite system matrix \a A is a n-by-n matrix that has already
+// been factorized by the sytrf() functions and \a x and \a b are n-dimensional vectors. Note that
+// the function only works for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// adaptors or matrices of any other element type results in a compile time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ sytrf( D, 'L', ipiv.data() );
+ sytrs( D, x, 'L', ipiv.data() );
+
+ assert( A * x == b );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ sytrf( D, 'L', ipiv.data() );
+ sytrs( D, x, 'L', ipiv.data() );
+
+ assert( trans( A ) * x == b );
+ \endcode
+
+// For more information on the sytrs() functions (i.e. ssytrs(), dsytrs(), csytrs(), and zsytrs()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void sytrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( VT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT>, ElementType_<VT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ sytrs( uplo, n, nrhs, (~A).data(), lda, ipiv, (~b).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a symmetric indefinite linear
+// system of equations (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param uplo \c 'L' to use the lower part of the matrix, \c 'U' to use the upper part.
+// \param ipiv Auxiliary array of size \a n for the pivot indices.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This function uses the LAPACK sytrs() functions to perform the substitution step to compute
+// the solution to a system of symmetric indefinite linear equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the symmetric indefinite system matrix \a A is a n-by-n matrix that has already
+// been factorized by the sytrf() functions and \a X and \a B are either row-major m-by-n matrices
+// or column-major n-by-m matrices. Note that the function only works for general, non-adapted
+// matrices with \c float, \c double, \c complex<float>, or \c complex<double> element type. The
+// attempt to call the function with adaptors or matrices of any other element type results in a
+// compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the sizes of the two given matrices do not match;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,columnMajor> B( 2UL, 4UL ); // The right-hand side matrix B
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,columnMajor> X( B ); // Temporary matrix for the solution
+
+ sytrf( D, 'L' );
+ sytrs( D, X, 'L' );
+
+ assert( A * X == B );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::rowMajor;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,rowMajor> B( 4UL, 2UL ); // The right-hand side matrix B
+ DynamicVector<int,columnVector> ipiv( 2UL ); // Pivoting indices
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,rowMajor> X( B ); // Temporary matrix for the solution
+
+ sytrf( D, 'L' );
+ sytrs( D, X, 'L' );
+
+ assert( trans( A ) * trans( X ) == trans( B ) );
+ \endcode
+
+// For more information on the sytrs() functions (i.e. ssytrs(), dsytrs(), csytrs(), and zsytrs()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void sytrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B, char uplo, const int* ipiv )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ sytrs( uplo, n, nrhs, (~A).data(), lda, ipiv, (~B).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/trsv.h b/src/cpu/blaze/math/lapack/trsv.h
new file mode 100644
index 00000000..260b8e6f
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/trsv.h
@@ -0,0 +1,210 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/trsv.h
+// \brief Header file for the LAPACK triangular linear system solver functions (trsv)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_TRSV_H_
+#define _BLAZE_MATH_LAPACK_TRSV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/trsv.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK TRIANGULAR LINEAR SYSTEM FUNCTIONS (TRSV)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK triangular linear system functions (trsv) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void trsv( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b,
+ char uplo, char trans, char diag );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for solving a triangular linear system of equations (\f$ A*x=b \f$).
+// (\f$ A*x=b \f$).
+// \ingroup lapack_solver
+//
+// \param A The system matrix.
+// \param b The right-hand side vector.
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*x=b \f$, \c 'T' for \f$ A^T*x=b \f$, and \c C for \f$ A^H*x=b \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+// \exception std::invalid_argument Invalid diag argument provided.
+//
+// This function uses the LAPACK trsv() functions to compute the solution to the triangular system
+// of linear equations:
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the positive definite system matrix \a A is a n-by-n matrix and \a x and \a b
+// are n-dimensional vectors. Note that the function only works for general, non-adapted matrices
+// with \c float, \c double, \c complex<float>, or \c complex<double> element type. The attempt
+// to call the function with adaptors or matrices of any other element type results in a compile
+// time error!
+//
+// If the function exits successfully, the vector \a x contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given \a trans argument is neither \c 'N' nor \c 'T' nor \c 'C';
+// - ... the given \a diag argument is neither \c 'U' nor \c 'N'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ trsv( D, x, 'L', 'N', 'N' );
+
+ assert( A * x == b );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ trsv( D, x, 'L', 'N', 'N' );
+
+ assert( trans( A ) * x == b );
+ \endcode
+
+// For more information on the trsv() functions (i.e. strsv(), dtrsv(), ctrsv(), and ztrsv()), see
+// the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note The function does not perform any test for singularity or near-singularity. Such tests
+// must be performed prior to calling this function!
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void trsv( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, char trans, char diag )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ if( diag != 'U' && diag != 'N' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid diag argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int incX( 1 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ trsv( uplo, trans, diag, n, (~A).data(), lda, (~b).data(), incX );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/trtri.h b/src/cpu/blaze/math/lapack/trtri.h
new file mode 100644
index 00000000..37d2bbb3
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/trtri.h
@@ -0,0 +1,159 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/trtri.h
+// \brief Header file for the LAPACK triangular matrix inversion functions (trtri)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_TRTRI_H_
+#define _BLAZE_MATH_LAPACK_TRTRI_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/trtri.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK TRIANGULAR MATRIX INVERSION FUNCTIONS (TRTRI)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK triangular matrix inversion functions (trtri) */
+//@{
+template< typename MT, bool SO >
+inline void trtri( DenseMatrix<MT,SO>& A, char uplo, char diag );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the inversion of the given dense triangular matrix.
+// \ingroup lapack_inversion
+//
+// \param A The triangular matrix to be inverted.
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Invalid diag argument provided.
+// \exception std::runtime_error Inversion of singular matrix failed.
+//
+// This function performs the dense matrix inversion based on the LAPACK trtri() functions for
+// a lower triangular (\a uplo = \c 'L') or upper triangular (\a uplo = \a 'U') matrix. Note
+// that the function only works for general, non-adapted matrices with \c float, \c double,
+// \c complex<float>, or \c complex<double> element type. The attempt to call the function with
+// adaptors or matrices of any other element type results in a compile time error!
+//
+// The function fails if ...
+//
+// - ... the given matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given \a diag argument is neither \c 'U' nor \c 'N';
+// - ... the given matrix is singular and not invertible.
+//
+// In all failure cases an exception is thrown.
+//
+// For more information on the trtri() functions (i.e. strtri(), dtrtri(), ctrtri(), and ztrtri())
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a A may already have been modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order of the dense matrix
+inline void trtri( DenseMatrix<MT,SO>& A, char uplo, char diag )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ if( diag != 'U' && diag != 'N' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid diag argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).columns() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ trtri( uplo, diag, n, (~A).data(), lda, &info );
+
+ BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for matrix inversion" );
+
+ if( info > 0 ) {
+ BLAZE_THROW_LAPACK_ERROR( "Inversion of singular matrix failed" );
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/trtrs.h b/src/cpu/blaze/math/lapack/trtrs.h
new file mode 100644
index 00000000..3f8a74b4
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/trtrs.h
@@ -0,0 +1,362 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/trtrs.h
+// \brief Header file for the LAPACK triangular backward substitution functions (trtrs)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_TRTRS_H_
+#define _BLAZE_MATH_LAPACK_TRTRS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/lapack/clapack/trtrs.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/SameType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK TRIANGULAR SUBSTITUTION FUNCTIONS (TRTRS)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK triangular substitution functions (trtrs) */
+//@{
+template< typename MT, bool SO, typename VT, bool TF >
+inline void trtrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b,
+ char uplo, char trans, char diag );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void trtrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ char uplo, char trans, char diag );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a triangular linear system of equations
+// (\f$ A*x=b \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param b The right-hand side vector.
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*x=b \f$, \c 'T' for \f$ A^T*x=b \f$, and \c C for \f$ A^H*x=b \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+// \exception std::invalid_argument Invalid diag argument provided.
+//
+// This function uses the LAPACK trtrs() functions to perform the substitution step to compute
+// the solution to the triangular system of linear equations:
+//
+// - \f$ A *x=b \f$ if \a A is column-major
+// - \f$ A^T*x=b \f$ if \a A is row-major
+//
+// In this context the triangular system matrix \a A is a n-by-n matrix and \a x and \a b are
+// n-dimensional vectors. Note that the function only works for general, non-adapted matrices with
+// \c float, \c double, \c complex<float>, or \c complex<double> element type. The attempt to call
+// the function with adaptors or matrices of any other element type results in a compile time error!
+//
+// If the function exits successfully, the vector \a b contains the solution of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given \a trans argument is neither \c 'N' nor \c 'T' nor \c 'C';
+// - ... the given \a diag argument is neither \c 'U' nor \c 'N'.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ trtrs( D, x, 'L', 'N', 'N' );
+
+ assert( A * x == b );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicVector<double,columnVector> b( 2UL ); // The right-hand side vector b
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicVector<double,columnVector> x( b ); // Temporary vector for the solution
+
+ trtrs( D, x, 'L', 'N', 'N' );
+
+ assert( trans( A ) * x == b );
+ \endcode
+
+// For more information on the trtrs() functions (i.e. strtrs(), dtrtrs(), ctrtrs(), and ztrtrs()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT // Type of the system matrix
+ , bool SO // Storage order of the system matrix
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline void trtrs( const DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& b, char uplo, char trans, char diag )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ if( diag != 'U' && diag != 'N' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid diag argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int nrhs( 1 );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~b).size() ) );
+ int info( 0 );
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ trtrs( uplo, trans, diag, n, nrhs, (~A).data(), lda, (~b).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the substitution step of solving a triangular linear system of equations
+// (\f$ A*X=B \f$).
+// \ingroup lapack_substitution
+//
+// \param A The system matrix.
+// \param B The matrix of right-hand sides.
+// \param uplo \c 'L' in case of a lower matrix, \c 'U' in case of an upper matrix.
+// \param trans \c 'N' for \f$ A*x=b \f$, \c 'T' for \f$ A^T*x=b \f$, and \c C for \f$ A^H*x=b \f$.
+// \param diag \c 'U' in case of a unitriangular matrix, \c 'N' otherwise.
+// \return void
+// \exception std::invalid_argument Invalid non-square matrix provided.
+// \exception std::invalid_argument Invalid uplo argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+// \exception std::invalid_argument Invalid diag argument provided.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// This function uses the LAPACK getrs() functions to perform the substitution step to compute
+// the solution to the triangular system of linear equations:
+//
+// - \f$ A *X =B \f$ if both \a A and \a B are column-major
+// - \f$ A^T*X =B \f$ if \a A is row-major and \a B is column-major
+// - \f$ A *X^T=B^T \f$ if \a A is column-major and \a B is row-major
+// - \f$ A^T*X^T=B^T \f$ if both \a A and \a B are row-major
+//
+// In this context the triangular system matrix \a A is a n-by-n matrix and \a X and \a B are
+// either row-major m-by-n matrices or column-major n-by-m matrices. Note that the function only
+// works for general, non-adapted matrices with \c float, \c double, \c complex<float>, or
+// \c complex<double> element type. The attempt to call the function with adaptors or matrices
+// of any other element type results in a compile time error!
+//
+// If the function exits successfully, the matrix \a B contains the solutions of the linear system
+// of equations. The function fails if ...
+//
+// - ... the given system matrix is not a square matrix;
+// - ... the given \a uplo argument is neither \c 'L' nor \c 'U';
+// - ... the given \a trans argument is neither \c 'N' nor \c 'T' nor \c 'C';
+// - ... the given \a diag argument is neither \c 'U' nor \c 'N';
+// - ... the sizes of the two given matrices do not match.
+//
+// In all failure cases a \a std::invalid_argument exception is thrown.
+//
+// Examples:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::columnMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,columnMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,columnMajor> B( 2UL, 4UL ); // The right-hand side matrix B
+ // ... Initialization
+
+ DynamicMatrix<double,columnMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,columnMajor> X( B ); // Temporary matrix for the solution
+
+ trtrs( D, X, 'L', 'N', 'N' );
+
+ assert( A * X == B );
+ \endcode
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::DynamicVector;
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ DynamicMatrix<double,rowMajor> A( 2UL, 2UL ); // The system matrix A
+ DynamicMatrix<double,rowMajor> B( 2UL, 4UL ); // The right-hand side matrix B
+ // ... Initialization
+
+ DynamicMatrix<double,rowMajor> D( A ); // Temporary matrix to be decomposed
+ DynamicMatrix<double,rowMajor> X( B ); // Temporary matrix for the solution
+
+ trtrs( D, X, 'L', 'N', 'N' );
+
+ assert( trans( A ) * trans( X ) == trans( B ) );
+ \endcode
+
+// For more information on the trtrs() functions (i.e. strtrs(), dtrtrs(), ctrtrs(), and ztrtrs()),
+// see the LAPACK online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1 // Type of the system matrix
+ , bool SO1 // Storage order of the system matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline void trtrs( const DenseMatrix<MT1,SO1>& A, DenseMatrix<MT2,SO2>& B,
+ char uplo, char trans, char diag )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_<MT1>, ElementType_<MT2> );
+
+ if( !isSquare( ~A ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
+ }
+
+ if( uplo != 'L' && uplo != 'U' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid uplo argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'T' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ if( diag != 'U' && diag != 'N' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid diag argument provided" );
+ }
+
+ int n ( numeric_cast<int>( (~A).rows() ) );
+ int mrhs( numeric_cast<int>( SO2 ? (~B).rows() : (~B).columns() ) );
+ int nrhs( numeric_cast<int>( SO2 ? (~B).columns() : (~B).rows() ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldb ( numeric_cast<int>( (~B).spacing() ) );
+ int info( 0 );
+
+ if( n != mrhs ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( n == 0 ) {
+ return;
+ }
+
+ if( IsRowMajorMatrix<MT1>::value ) {
+ ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' );
+ }
+
+ trtrs( uplo, trans, diag, n, nrhs, (~A).data(), lda, (~B).data(), ldb, &info );
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid function argument" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/unglq.h b/src/cpu/blaze/math/lapack/unglq.h
new file mode 100644
index 00000000..69e14b36
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/unglq.h
@@ -0,0 +1,156 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/unglq.h
+// \brief Header file for the LAPACK functions to reconstruct Q from a LQ decomposition (unglq)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_UNGLQ_H_
+#define _BLAZE_MATH_LAPACK_UNGLQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/unglq.h>
+#include <blaze/math/lapack/clapack/ungqr.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A LQ DECOMPOSITION (UNGLQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a LQ decomposition (unglq) */
+//@{
+template< typename MT, bool SO >
+inline void unglq( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a LQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param A The decomposed matrix.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function reconstructs the orthogonal matrix \a Q of a LQ decomposition based on the LAPACK
+// unglq() functions from matrices that have already been LQ factorized by the gelqf() functions.
+// Note that this function can only be used for general, non-adapted matrices with \c complex<float>
+// or \c complex<double> element type. The attempt to call the function with any adapted matrix or
+// matrices of any other element type results in a compile time error!\n
+//
+// The min(\a m,\a n)-by-\a n \a Q matrix is stored within the given matrix \a A:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ typedef complex<double> cplx;
+
+ DynamicMatrix<cplx,columnMajor> A;
+ DynamicVector<cplx> tau;
+ // ... Resizing and initialization
+
+ gelqf( A, tau.data() ); // Performing the LQ decomposition
+ unglq( A, tau.data() ); // Reconstructing the Q matrix
+
+ const int m( A.rows() );
+ const int n( A.columns() );
+
+ DynamicMatrix<cplx,columnMajor> Q( submatrix( A, 0, 0, min(m,n), n ) );
+ \endcode
+
+// For more information on the unglq() functions (i.e. cunglq() and zunglq()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT, bool SO >
+inline void unglq( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int k ( min( m, n ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( k == 0 ) {
+ return;
+ }
+
+ int lwork( k*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ unglq( k, n, k, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ ungqr( m, k, k, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q reconstruction" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/ungql.h b/src/cpu/blaze/math/lapack/ungql.h
new file mode 100644
index 00000000..d3b0f9f2
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/ungql.h
@@ -0,0 +1,159 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/ungql.h
+// \brief Header file for the LAPACK functions to reconstruct Q from a QL decomposition (ungql)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_UNGQL_H_
+#define _BLAZE_MATH_LAPACK_UNGQL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/ungql.h>
+#include <blaze/math/lapack/clapack/ungrq.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A QL DECOMPOSITION (UNGQL)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a QL decomposition (ungql) */
+//@{
+template< typename MT, bool SO >
+inline void ungql( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QL decomposition.
+// \ingroup lapack_decomposition
+//
+// \param A The decomposed matrix.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function reconstructs the orthogonal matrix \a Q of a QL decomposition based on the LAPACK
+// ungql() functions from matrices that have already been QL factorized by the geqlf() functions.
+// Note that this function can only be used for general, non-adapted matrices with \c float or
+// \c double element type. The attempt to call the function with any adapted matrix or matrices
+// of any other element type results in a compile time error!\n
+//
+// The min(\a m,\a n)-by-\a n \a Q matrix is stored within the given matrix \a A:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ typedef complex<double> cplx;
+
+ DynamicMatrix<cplx,columnMajor> A;
+ DynamicVector<cplx> tau;
+ // ... Resizing and initialization
+
+ geqlf( A, tau.data() ); // Performing the QL decomposition
+ ungql( A, tau.data() ); // Reconstructing the Q matrix
+
+ const int m( A.rows() );
+ const int n( A.columns() );
+
+ const size_t column( m < n ? n - m : 0UL )
+ DynamicMatrix<cplx,columnMajor> Q( submatrix( A, 0UL, column, m, min(m,n) ) );
+ \endcode
+
+// For more information on the ungql() functions (i.e. cungql() and zungql()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT, bool SO >
+inline void ungql( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int k ( min( m, n ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( k == 0 ) {
+ return;
+ }
+
+ int lwork( k*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ const size_t offset( ( m < n )?( n - m ):( 0UL ) );
+ ungql( m, k, k, (~A).data(offset), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ const size_t offset( ( m > n )?( m - n ):( 0UL ) );
+ ungrq( k, n, k, (~A).data()+offset, lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q reconstruction" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/ungqr.h b/src/cpu/blaze/math/lapack/ungqr.h
new file mode 100644
index 00000000..269fee8e
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/ungqr.h
@@ -0,0 +1,156 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/ungqr.h
+// \brief Header file for the LAPACK functions to reconstruct Q from a QR decomposition (ungqr)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_UNGQR_H_
+#define _BLAZE_MATH_LAPACK_UNGQR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/unglq.h>
+#include <blaze/math/lapack/clapack/ungqr.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A QR DECOMPOSITION (UNGQR)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a QR decomposition (ungqr) */
+//@{
+template< typename MT, bool SO >
+inline void ungqr( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a QR decomposition.
+// \ingroup lapack_decomposition
+//
+// \param A The decomposed matrix.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function reconstructs the orthogonal matrix \a Q of a QR decomposition based on the LAPACK
+// ungqr() functions from matrices that have already been QR factorized by the geqrf() functions.
+// Note that this function can only be used for general, non-adapted matrices with \c complex<float>
+// or \c complex<double> element type. The attempt to call the function with any adapted matrix or
+// matrices of any other element type results in a compile time error!\n
+//
+// The \a m-by-min(\a m,\a n) \a Q matrix is stored within the given matrix \a A:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ typedef complex<double> cplx;
+
+ DynamicMatrix<cplx,columnMajor> A;
+ DynamicVector<cplx> tau;
+ // ... Resizing and initialization
+
+ geqrf( A, tau.data() ); // Performing the QR decomposition
+ ungqr( A, tau.data() ); // Reconstructing the Q matrix
+
+ const int m( A.rows() );
+ const int n( A.columns() );
+
+ DynamicMatrix<cplx,columnMajor> Q( submatrix( A, 0, 0, m, min(m,n) ) );
+ \endcode
+
+// For more information on the ungqr() functions (i.e. cungqr() and zungqr()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT, bool SO >
+inline void ungqr( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int k ( min( m, n ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( k == 0 ) {
+ return;
+ }
+
+ int lwork( k*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ ungqr( m, k, k, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ unglq( k, n, k, (~A).data(), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q reconstruction" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/ungrq.h b/src/cpu/blaze/math/lapack/ungrq.h
new file mode 100644
index 00000000..4e285837
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/ungrq.h
@@ -0,0 +1,158 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/ungrq.h
+// \brief Header file for the LAPACK functions to reconstruct Q from a RQ decomposition (ungrq)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_UNGRQ_H_
+#define _BLAZE_MATH_LAPACK_UNGRQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/ungrq.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO RECONSTRUCT Q FROM A RQ DECOMPOSITION (UNGRQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to reconstruct Q from a RQ decomposition (ungrq) */
+//@{
+template< typename MT, bool SO >
+inline void ungrq( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the reconstruction of the orthogonal matrix Q from a RQ decomposition.
+// \ingroup lapack_decomposition
+//
+// \param A The decomposed matrix.
+// \param tau Array for the scalar factors of the elementary reflectors; size >= min( \a m, \a n ).
+// \return void
+//
+// This function reconstructs the orthogonal matrix \a Q of a RQ decomposition based on the LAPACK
+// ungrq() functions from matrices that have already been RQ factorized by the gerqf() functions.
+// Note that this function can only be used for general, non-adapted matrices with \c float or
+// \c double element type. The attempt to call the function with any adapted matrix or matrices
+// of any other element type results in a compile time error!\n
+//
+// The min(\a m,\a n)-by-\a n \a Q matrix is stored within the given matrix \a A:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ typedef complex<double> cplx;
+
+ DynamicMatrix<cplx,columnMajor> A;
+ DynamicVector<cplx> tau;
+ // ... Resizing and initialization
+
+ gerqf( A, tau.data() ); // Performing the RQ decomposition
+ ungrq( A, tau.data() ); // Reconstructing the Q matrix
+
+ const int m( A.rows() );
+ const int n( A.columns() );
+
+ const size_t row( m > n ? m - n : 0UL )
+ DynamicMatrix<cplx,columnMajor> Q( submatrix( A, row, 0UL, min(m,n), n ) );
+ \endcode
+
+// For more information on the ungrq() functions (i.e. cungrq() and zungrq()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT, bool SO >
+inline void ungrq( DenseMatrix<MT,SO>& A, const ElementType_<MT>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT> );
+
+ typedef ElementType_<MT> ET;
+
+ int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
+ int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
+ int k ( min( m, n ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int info( 0 );
+
+ if( k == 0 ) {
+ return;
+ }
+
+ int lwork( k*lda );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ const size_t offset( ( m > n )?( m - n ):( 0UL ) );
+ ungrq( k, n, k, (~A).data()+offset, lda, tau, work.get(), lwork, &info );
+ }
+ else {
+ const size_t offset( ( m < n )?( n - m ):( 0UL ) );
+ ungql( m, k, k, (~A).data(offset), lda, tau, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q reconstruction" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/unmlq.h b/src/cpu/blaze/math/lapack/unmlq.h
new file mode 100644
index 00000000..85159982
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/unmlq.h
@@ -0,0 +1,195 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/unmlq.h
+// \brief Header file for the LAPACK functions to multiply Q from a LQ decomposition with a matrix (unmlq)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_UNMLQ_H_
+#define _BLAZE_MATH_LAPACK_UNMLQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/unmlq.h>
+#include <blaze/math/lapack/clapack/unmqr.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A LQ DECOMPOSITION WITH A MATRIX (UNMLQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a LQ decomposition with a matrix (unmlq) */
+//@{
+template< typename MT1, bool SO, typename MT2 >
+inline void unmlq( DenseMatrix<MT1,SO>& C, const DenseMatrix<MT2,SO>& A,
+ char side, char trans, const ElementType_<MT2>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a LQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param C The matrix multiplier.
+// \param A The decomposed matrix.
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+// \exception std::invalid_argument Invalid size of Q matrix.
+// \exception std::invalid_argument Invalid side argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function multiplies a square \a Q matrix resulting from the LQ decomposition of the
+// gelqf() functions with the given general \a m-by-\a n matrix \a C. Depending on the settings
+// of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// Note that the size of matrix \c C is preserved, which means that the function does not work for
+// non-square Q matrices. Therefore in case the number of rows of \a A is larger than the number
+// of columns, a \a std::invalid_argument exception is thrown. Also Note that this function can
+// only be used for general, non-adapted matrices with \c float or \c double element type. The
+// attempt to call the function with any adapted matrix or matrices of any other element type
+// results in a compile time error!
+//
+// The following code example demonstrates the use of the unmlq() function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicMatrix<double,columnMajor> C;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ gelqf( A, tau.data() ); // Performing the LQ decomposition
+ unmlq( C, A, 'R', 'N', tau.data() ); // Computing C = C * Q
+ \endcode
+
+// For more information on the unmlq() functions (i.e. sunmlq() and dunmlq()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1, bool SO, typename MT2 >
+inline void unmlq( DenseMatrix<MT1,SO>& C, const DenseMatrix<MT2,SO>& A,
+ char side, char trans, const ElementType_<MT2>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( (~A).rows() > (~A).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size of Q matrix" );
+ }
+
+ if( side != 'L' && side != 'R' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid side argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int m ( numeric_cast<int>( SO ? (~C).rows() : (~C).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~C).columns() : (~C).rows() ) );
+ int k ( numeric_cast<int>( min( (~A).rows(), (~A).columns() ) ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldc ( numeric_cast<int>( (~C).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 || k == 0 ) {
+ return;
+ }
+
+ if( !SO ) {
+ ( side == 'L' )?( side = 'R' ):( side = 'L' );
+ }
+
+ int lwork( k*ldc );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ unmlq( side, trans, m, n, k, (~A).data(), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+ else {
+ unmqr( side, trans, m, n, k, (~A).data(), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q multiplication" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/unmql.h b/src/cpu/blaze/math/lapack/unmql.h
new file mode 100644
index 00000000..2841e83a
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/unmql.h
@@ -0,0 +1,196 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/unmql.h
+// \brief Header file for the LAPACK functions to multiply Q from a QL decomposition with a matrix (unmql)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_UNMQL_H_
+#define _BLAZE_MATH_LAPACK_UNMQL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/unmql.h>
+#include <blaze/math/lapack/clapack/unmrq.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A QL DECOMPOSITION WITH A MATRIX (UNMQL)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a QL decomposition with a matrix (unmql) */
+//@{
+template< typename MT1, bool SO, typename MT2 >
+inline void unmql( DenseMatrix<MT1,SO>& C, const DenseMatrix<MT2,SO>& A,
+ char side, char trans, const ElementType_<MT2>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a QL decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param C The matrix multiplier.
+// \param A The decomposed matrix.
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+// \exception std::invalid_argument Invalid size of Q matrix.
+// \exception std::invalid_argument Invalid side argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function multiplies a square \a Q matrix resulting from the QL decomposition of the
+// geqlf() functions with the given general \a m-by-\a n matrix \a C. Depending on the settings
+// of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// Note that the size of matrix \c C is preserved, which means that the function does not work for
+// non-square Q matrices. Therefore in case the number of rows of \a A is smaller than the number
+// of columns, a \a std::invalid_argument exception is thrown. Also note that this function can
+// only be used for general, non-adapted matrices with \c float or \c double element type. The
+// attempt to call the function with any adapted matrix or matrices of any other element type
+// results in a compile time error!
+//
+// The following code example demonstrates the use of the unmql() function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicMatrix<double,columnMajor> C;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ geqlf( A, tau.data() ); // Performing the QL decomposition
+ unmql( C, A, 'R', 'N', tau.data() ); // Computing C = C * Q
+ \endcode
+
+// For more information on the unmql() functions (i.e. cunmql() and zunmql()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1, bool SO, typename MT2 >
+inline void unmql( DenseMatrix<MT1,SO>& C, const DenseMatrix<MT2,SO>& A,
+ char side, char trans, const ElementType_<MT2>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( (~A).rows() < (~A).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size of Q matrix" );
+ }
+
+ if( side != 'L' && side != 'R' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid side argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int m ( numeric_cast<int>( SO ? (~C).rows() : (~C).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~C).columns() : (~C).rows() ) );
+ int k ( numeric_cast<int>( min( (~A).rows(), (~A).columns() ) ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldc ( numeric_cast<int>( (~C).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 || k == 0 ) {
+ return;
+ }
+
+ if( !SO ) {
+ ( side == 'L' )?( side = 'R' ):( side = 'L' );
+ }
+
+ int lwork( k*ldc );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+ const size_t offset( (~A).rows() - (~A).columns() );
+
+ if( SO ) {
+ unmql( side, trans, m, n, k, (~A).data()+offset, lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+ else {
+ unmrq( side, trans, m, n, k, (~A).data(offset), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q multiplication" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/unmqr.h b/src/cpu/blaze/math/lapack/unmqr.h
new file mode 100644
index 00000000..2fcc589e
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/unmqr.h
@@ -0,0 +1,195 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/unmqr.h
+// \brief Header file for the LAPACK functions to multiply Q from a QR decomposition with a matrix (unmqr)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_UNMQR_H_
+#define _BLAZE_MATH_LAPACK_UNMQR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/unmlq.h>
+#include <blaze/math/lapack/clapack/unmqr.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A QR DECOMPOSITION WITH A MATRIX (UNMQR)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a QR decomposition with a matrix (unmqr) */
+//@{
+template< typename MT1, bool SO, typename MT2 >
+inline void unmqr( DenseMatrix<MT1,SO>& C, DenseMatrix<MT2,SO>& A,
+ char side, char trans, ElementType_<MT2>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a QR decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param C The matrix multiplier.
+// \param A The decomposed matrix.
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^H \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'C' for \f$ Q^H \f$.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+// \exception std::invalid_argument Invalid size of Q matrix.
+// \exception std::invalid_argument Invalid side argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function multiplies a square \a Q matrix resulting from the QR decomposition of the
+// geqrf() functions with the given general \a m-by-\a n matrix \a C. Depending on the settings
+// of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'C': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// Note that the size of matrix \c C is preserved, which means that the function does not work for
+// non-square Q matrices. Therefore in case the number of rows of \a A is larger than the number
+// of columns, a \a std::invalid_argument exception is thrown. Also Note that this function can
+// only be used for general, non-adapted matrices with \c float or \c double element type. The
+// attempt to call the function with any adapted matrix or matrices of any other element type
+// results in a compile time error!
+//
+// The following code example demonstrates the use of the unmqr() function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicMatrix<double,columnMajor> C;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ geqrf( A, tau.data() ); // Performing the QR decomposition
+ unmqr( C, A, 'R', 'N', tau.data() ); // Computing C = C * Q
+ \endcode
+
+// For more information on the unmqr() functions (i.e. cunmqr() and zunmqr()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1, bool SO, typename MT2 >
+inline void unmqr( DenseMatrix<MT1,SO>& C, DenseMatrix<MT2,SO>& A,
+ char side, char trans, ElementType_<MT2>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( (~A).rows() > (~A).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size of Q matrix" );
+ }
+
+ if( side != 'L' && side != 'R' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid side argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int m ( numeric_cast<int>( SO ? (~C).rows() : (~C).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~C).columns() : (~C).rows() ) );
+ int k ( numeric_cast<int>( min( (~A).rows(), (~A).columns() ) ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldc ( numeric_cast<int>( (~C).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 || k == 0 ) {
+ return;
+ }
+
+ if( !SO ) {
+ ( side == 'L' )?( side = 'R' ):( side = 'L' );
+ }
+
+ int lwork( k*ldc );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+
+ if( SO ) {
+ unmqr( side, trans, m, n, k, (~A).data(), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+ else {
+ unmlq( side, trans, m, n, k, (~A).data(), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q multiplication" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/lapack/unmrq.h b/src/cpu/blaze/math/lapack/unmrq.h
new file mode 100644
index 00000000..315ade44
--- /dev/null
+++ b/src/cpu/blaze/math/lapack/unmrq.h
@@ -0,0 +1,196 @@
+//=================================================================================================
+/*!
+// \file blaze/math/lapack/unmrq.h
+// \brief Header file for the LAPACK functions to multiply Q from a RQ decomposition with a matrix (unmrq)
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_LAPACK_UNMRQ_H_
+#define _BLAZE_MATH_LAPACK_UNMRQ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <boost/cast.hpp>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Adaptor.h>
+#include <blaze/math/constraints/BLASCompatible.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/lapack/clapack/unmql.h>
+#include <blaze/math/lapack/clapack/unmrq.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LAPACK FUNCTIONS TO MULTIPLY Q FROM A RQ DECOMPOSITION WITH A MATRIX (UNMRQ)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LAPACK functions to multiply Q from a RQ decomposition with a matrix (unmrq) */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline void unmrq( DenseMatrix<MT1,SO1>& C, const DenseMatrix<MT2,SO2>& A,
+ char side, char trans, const ElementType_<MT2>* tau );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief LAPACK kernel for the multiplication of the double precision Q from a RQ decomposition
+// with another matrix.
+// \ingroup lapack_decomposition
+//
+// \param C The matrix multiplier.
+// \param A The decomposed matrix.
+// \param side \c 'L' to apply \f$ Q \f$ or \f$ Q^T \f$ from the left, \c 'R' to apply from the right.
+// \param trans \c 'N' for \f$ Q \f$, \c 'T' for \f$ Q^T \f$.
+// \param tau Array for the scalar factors of the elementary reflectors.
+// \return void
+// \exception std::invalid_argument Invalid size of Q matrix.
+// \exception std::invalid_argument Invalid side argument provided.
+// \exception std::invalid_argument Invalid trans argument provided.
+//
+// This function multiplies a square \a Q matrix resulting from the RQ decomposition of the
+// gerqf() functions with the given general \a m-by-\a n matrix \a C. Depending on the settings
+// of \a side and \a trans it overwrites \a C with
+
+ \code
+ | side = 'L' | side = 'R'
+ -------------|--------------|--------------
+ trans = 'N': | Q * C | C * Q
+ trans = 'T': | trans(Q) * C | C * trans(Q)
+ \endcode
+
+// Note that the size of matrix \c C is preserved, which means that the function does not work for
+// non-square Q matrices. Therefore in case the number of rows of \a A is smaller than the number
+// of columns, a \a std::invalid_argument exception is thrown. Also note that this function can
+// only be used for general, non-adapted matrices with \c float or \c double element type. The
+// attempt to call the function with any adapted matrix or matrices of any other element type
+// results in a compile time error!
+//
+// The following code example demonstrates the use of the unmrq() function:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::columnMajor;
+
+ DynamicMatrix<double,columnMajor> A;
+ DynamicMatrix<double,columnMajor> C;
+ DynamicVector<double> tau;
+ // ... Resizing and initialization
+
+ gerqf( A, tau.data() ); // Performing the RQ decomposition
+ unmrq( C, A, 'R', 'N', tau.data() ); // Computing C = C * Q
+ \endcode
+
+// For more information on the unmrq() functions (i.e. cunmrq() and zunmrq()) see the LAPACK
+// online documentation browser:
+//
+// http://www.netlib.org/lapack/explore-html/
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a call to this function will result in a linker error.
+*/
+template< typename MT1, bool SO, typename MT2 >
+inline void unmrq( DenseMatrix<MT1,SO>& C, const DenseMatrix<MT2,SO>& A,
+ char side, char trans, const ElementType_<MT2>* tau )
+{
+ using boost::numeric_cast;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT1 );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( MT1 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT1> );
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( MT2 );
+ BLAZE_CONSTRAINT_MUST_HAVE_CONST_DATA_ACCESS( MT2 );
+ BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_<MT2> );
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_<MT2> );
+
+ typedef ElementType_<MT1> ET;
+
+ if( (~A).rows() < (~A).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid size of Q matrix" );
+ }
+
+ if( side != 'L' && side != 'R' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid side argument provided" );
+ }
+
+ if( trans != 'N' && trans != 'C' ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid trans argument provided" );
+ }
+
+ int m ( numeric_cast<int>( SO ? (~C).rows() : (~C).columns() ) );
+ int n ( numeric_cast<int>( SO ? (~C).columns() : (~C).rows() ) );
+ int k ( numeric_cast<int>( min( (~A).rows(), (~A).columns() ) ) );
+ int lda ( numeric_cast<int>( (~A).spacing() ) );
+ int ldc ( numeric_cast<int>( (~C).spacing() ) );
+ int info( 0 );
+
+ if( m == 0 || n == 0 || k == 0 ) {
+ return;
+ }
+
+ if( !SO ) {
+ ( side == 'L' )?( side = 'R' ):( side = 'L' );
+ }
+
+ int lwork( k*ldc );
+ const std::unique_ptr<ET[]> work( new ET[lwork] );
+ const size_t offset( (~A).rows() - (~A).columns() );
+
+ if( SO ) {
+ unmrq( side, trans, m, n, k, (~A).data()+offset, lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+ else {
+ unmql( side, trans, m, n, k, (~A).data(offset), lda, tau, (~C).data(), ldc, work.get(), lwork, &info );
+ }
+
+ BLAZE_INTERNAL_ASSERT( info == 0, "Invalid argument for Q multiplication" );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/proxy/ComplexProxy.h b/src/cpu/blaze/math/proxy/ComplexProxy.h
new file mode 100644
index 00000000..d996bd5b
--- /dev/null
+++ b/src/cpu/blaze/math/proxy/ComplexProxy.h
@@ -0,0 +1,227 @@
+//=================================================================================================
+/*!
+// \file blaze/math/proxy/ComplexProxy.h
+// \brief Header file for the ComplexProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PROXY_COMPLEXPROXY_H_
+#define _BLAZE_MATH_PROXY_COMPLEXPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Exception.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/constraints/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Proxy backend for complex types.
+// \ingroup math
+//
+// The ComplexProxy class serves as a backend for the Proxy class. It is used in case the data
+// type represented by the proxy is a complex number and augments the Proxy interface by the
+// complete interface required of complex numbers.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+class ComplexProxy
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef typename CT::value_type value_type; //!< Value type of the represented complex element.
+ typedef value_type ValueType; //!< Value type of the represented complex element.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline ValueType real() const;
+ inline void real( ValueType value ) const;
+ inline ValueType imag() const;
+ inline void imag( ValueType value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operators************************************************************************
+ /*!\name Conversion operators */
+ //@{
+ BLAZE_ALWAYS_INLINE PT& operator~();
+ BLAZE_ALWAYS_INLINE const PT& operator~() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( CT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the real part of the represented complex number.
+//
+// \return The current real part of the represented complex number.
+//
+// This function returns the current value of the real part of the represented complex number.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+inline typename ComplexProxy<PT,CT>::ValueType ComplexProxy<PT,CT>::real() const
+{
+ return (~*this).get().real();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the real part of the represented complex number.
+//
+// \param value The new value for the real part.
+// \return void
+//
+// This function sets a new value to the real part of the represented complex number.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+inline void ComplexProxy<PT,CT>::real( ValueType value ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().real( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the imaginary part of the represented complex number.
+//
+// \return The current imaginary part of the represented complex number.
+//
+// This function returns the current value of the imaginary part of the represented complex number.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+inline typename ComplexProxy<PT,CT>::ValueType ComplexProxy<PT,CT>::imag() const
+{
+ return (~*this).get().imag();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the imaginary part of the represented complex number.
+//
+// \param value The new value for the imaginary part.
+// \return void
+//
+// This function sets a new value to the imaginary part of the represented complex number.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+inline void ComplexProxy<PT,CT>::imag( ValueType value ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().imag( value );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator for non-constant proxies.
+//
+// \return Reference to the actual type of the proxy.
+//
+// This function provides a type-safe downcast to the actual type of the proxy.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+BLAZE_ALWAYS_INLINE PT& ComplexProxy<PT,CT>::operator~()
+{
+ return *static_cast<PT*>( this );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator for constant proxies.
+//
+// \return Reference to the actual type of the proxy.
+//
+// This function provides a type-safe downcast to the actual type of the proxy.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+BLAZE_ALWAYS_INLINE const PT& ComplexProxy<PT,CT>::operator~() const
+{
+ return *static_cast<const PT*>( this );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/proxy/DefaultProxy.h b/src/cpu/blaze/math/proxy/DefaultProxy.h
new file mode 100644
index 00000000..9276f41f
--- /dev/null
+++ b/src/cpu/blaze/math/proxy/DefaultProxy.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/proxy/DefaultProxy.h
+// \brief Header file for the DefaultProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PROXY_DEFAULTPROXY_H_
+#define _BLAZE_MATH_PROXY_DEFAULTPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default proxy backend for built-in and alternate user-specific class types.
+// \ingroup math
+//
+// The DefaultProxy class serves as a backend for the Proxy class. It is used in case the data
+// type represented by the proxy is a built-in or alternate user-specific class type. This proxy
+// does not augment the Proxy interface by any additional interface.
+*/
+template< typename PT // Type of the proxy
+ , typename RT > // Type of the represented element
+class DefaultProxy
+{
+ public:
+ //**Conversion operators************************************************************************
+ /*!\name Conversion operators */
+ //@{
+ BLAZE_ALWAYS_INLINE PT& operator~();
+ BLAZE_ALWAYS_INLINE const PT& operator~() const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator for non-constant proxies.
+//
+// \return Reference to the actual type of the proxy.
+//
+// This function provides a type-safe downcast to the actual type of the proxy.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+BLAZE_ALWAYS_INLINE PT& DefaultProxy<PT,CT>::operator~()
+{
+ return *static_cast<PT*>( this );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator for constant proxies.
+//
+// \return Reference to the actual type of the proxy.
+//
+// This function provides a type-safe downcast to the actual type of the proxy.
+*/
+template< typename PT // Type of the proxy
+ , typename CT > // Type of the complex number
+BLAZE_ALWAYS_INLINE const PT& DefaultProxy<PT,CT>::operator~() const
+{
+ return *static_cast<const PT*>( this );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/proxy/DenseMatrixProxy.h b/src/cpu/blaze/math/proxy/DenseMatrixProxy.h
new file mode 100644
index 00000000..f63e0f2f
--- /dev/null
+++ b/src/cpu/blaze/math/proxy/DenseMatrixProxy.h
@@ -0,0 +1,1109 @@
+//=================================================================================================
+/*!
+// \file blaze/math/proxy/DenseMatrixProxy.h
+// \brief Header file for the DenseMatrixProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PROXY_DENSEMATRIXPROXY_H_
+#define _BLAZE_MATH_PROXY_DENSEMATRIXPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Proxy backend for dense matrix types.
+// \ingroup math
+//
+// The DenseMatrixProxy class serves as a backend for the Proxy class. It is used in case the
+// data type represented by the proxy is a dense matrix and augments the Proxy interface by
+// the complete interface required of dense matrices.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+class DenseMatrixProxy : public DenseMatrix< PT, IsColumnMajorMatrix<MT>::value >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef CompositeType_<MT> CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Pointer_<MT> Pointer; //!< Pointer to a non-constant matrix value.
+ typedef ConstPointer_<MT> ConstPointer; //!< Pointer to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation flag for SMP assignments.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j ) const;
+
+ inline Pointer data () const;
+ inline Pointer data ( size_t i ) const;
+ inline Iterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const;
+ inline size_t columns() const;
+ inline size_t spacing() const;
+ inline size_t capacity() const;
+ inline size_t capacity( size_t i ) const;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset() const;
+ inline void reset( size_t i ) const;
+ inline void clear() const;
+ inline void resize( size_t m, size_t n, bool preserve=true ) const;
+ inline void extend( size_t m, size_t n, bool preserve=true ) const;
+ inline void reserve( size_t n ) const;
+ inline void transpose() const;
+ inline void ctranspose() const;
+
+ template< typename Other > inline void scale( const Other& scalar ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Function call operator for the direct access to matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline typename DenseMatrixProxy<PT,MT>::Reference
+ DenseMatrixProxy<PT,MT>::operator()( size_t i, size_t j ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get()(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline typename DenseMatrixProxy<PT,MT>::Reference
+ DenseMatrixProxy<PT,MT>::at( size_t i, size_t j ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().at(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to matrix elements.
+//
+// \return Pointer to the internal element storage.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function returns a pointer to the internal storage of the dense matrix. Note that you can
+// NOT assume that all matrix elements lie adjacent to each other! The matrix may use techniques
+// such as padding to improve the alignment of the data. Whereas the number of elements within a
+// row/column are given by the \c rows() and \c columns() member functions, respectively, the
+// total number of elements including padding is given by the \c spacing() member function.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline typename DenseMatrixProxy<PT,MT>::Pointer DenseMatrixProxy<PT,MT>::data() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().data();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to matrix elements of row/column \a i.
+//
+// \return Pointer to the internal element storage.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline typename DenseMatrixProxy<PT,MT>::Pointer DenseMatrixProxy<PT,MT>::data( size_t i ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().data(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i of the represented matrix.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline typename DenseMatrixProxy<PT,MT>::Iterator
+ DenseMatrixProxy<PT,MT>::begin( size_t i ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().begin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i of the represented matrix.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the storage order is set to \a rowMajor the function returns an iterator to the first element
+// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
+// to the first element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline typename DenseMatrixProxy<PT,MT>::ConstIterator
+ DenseMatrixProxy<PT,MT>::cbegin( size_t i ) const
+{
+ return (~*this).get().cbegin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i of the represented matrix.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline typename DenseMatrixProxy<PT,MT>::Iterator
+ DenseMatrixProxy<PT,MT>::end( size_t i ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().end(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i of the represented matrix.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator just past
+// the last element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline typename DenseMatrixProxy<PT,MT>::ConstIterator
+ DenseMatrixProxy<PT,MT>::cend( size_t i ) const
+{
+ return (~*this).get().cend(i);
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the represented matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline size_t DenseMatrixProxy<PT,MT>::rows() const
+{
+ return (~*this).get().rows();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the represented matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline size_t DenseMatrixProxy<PT,MT>::columns() const
+{
+ return (~*this).get().columns();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the spacing between the beginning of two rows/columns of the represented matrix.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the
+// total number of elements of a row/column. In case the storage order is set to \a rowMajor
+// the function returns the spacing between two rows, in case the storage flag is set to
+// \a columnMajor the function returns the spacing between two columns.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline size_t DenseMatrixProxy<PT,MT>::spacing() const
+{
+ return (~*this).get().spacing();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the represented matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline size_t DenseMatrixProxy<PT,MT>::capacity() const
+{
+ return (~*this).get().capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column of the represented matrix.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline size_t DenseMatrixProxy<PT,MT>::capacity( size_t i ) const
+{
+ return (~*this).get().capacity(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the represented matrix.
+//
+// \return The number of non-zero elements in the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline size_t DenseMatrixProxy<PT,MT>::nonZeros() const
+{
+ return (~*this).get().nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column of the represented matrix.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline size_t DenseMatrixProxy<PT,MT>::nonZeros( size_t i ) const
+{
+ return (~*this).get().nonZeros(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial value.
+//
+// \return void
+//
+// This function resets all elements of the matrix to the default initial values.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline void DenseMatrixProxy<PT,MT>::reset() const
+{
+ using blaze::reset;
+
+ reset( (~*this).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline void DenseMatrixProxy<PT,MT>::reset( size_t i ) const
+{
+ using blaze::reset;
+
+ reset( (~*this).get(), i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented matrix.
+//
+// \return void
+//
+// This function clears the matrix to its default initial state.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline void DenseMatrixProxy<PT,MT>::clear() const
+{
+ using blaze::clear;
+
+ clear( (~*this).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the represented matrix.
+//
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. Depending on
+// the type of the matrix, during this operation new dynamic memory may be allocated in case
+// the capacity of the matrix is too small. Note that this function may invalidate all existing
+// views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the matrix.
+// Additionally, the resize operation potentially changes all matrix elements. In order to
+// preserve the old matrix values, the \a preserve flag can be set to \a true. However, note
+// that depending on the type of the matrix new matrix elements may not initialized!
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline void DenseMatrixProxy<PT,MT>::resize( size_t m, size_t n, bool preserve ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().resize( m, n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Extending the size of the represented matrix.
+//
+// \param m Number of additional rows.
+// \param n Number of additional columns.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function increases the matrix size by \a m rows and \a n columns. Depending on the type
+// of the matrix, during this operation new dynamic memory may be allocated in case the capacity
+// of the matrix is too small. Therefore this function potentially changes all matrix elements.
+// In order to preserve the old matrix values, the \a preserve flag can be set to \a true.
+// However, note that depending on the type of the matrix new matrix elements may not
+// initialized!
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline void DenseMatrixProxy<PT,MT>::extend( size_t m, size_t n, bool preserve ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().extend( m, n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the represented matrix.
+//
+// \param n The new minimum capacity of the matrix.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function increases the capacity of the dense matrix to at least \a n elements. The
+// current values of the matrix elements are preserved.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline void DenseMatrixProxy<PT,MT>::reserve( size_t n ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().reserve( n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the represented matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline void DenseMatrixProxy<PT,MT>::transpose() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().transpose();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the represented matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+inline void DenseMatrixProxy<PT,MT>::ctranspose() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().ctranspose();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline void DenseMatrixProxy<PT,MT>::scale( const Other& scalar ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().scale( scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DenseMatrixProxy global functions */
+//@{
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE typename DenseMatrixProxy<PT,MT>::Iterator
+ begin( const DenseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE typename DenseMatrixProxy<PT,MT>::ConstIterator
+ cbegin( const DenseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE typename DenseMatrixProxy<PT,MT>::Iterator
+ end( const DenseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE typename DenseMatrixProxy<PT,MT>::ConstIterator
+ cend( const DenseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t rows( const DenseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t columns( const DenseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t capacity( const DenseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t capacity( const DenseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE void resize( const DenseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve=true );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE void reset( const DenseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE void reset( const DenseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE void clear( const DenseMatrixProxy<PT,MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the given matrix is a row-major matrix the function returns an iterator to the first element
+// of row \a i, in case it is a column-major matrix the function returns an iterator to the first
+// element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename DenseMatrixProxy<PT,MT>::Iterator
+ begin( const DenseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.begin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the given matrix is a row-major matrix the function returns an iterator to the first element
+// of row \a i, in case it is a column-major matrix the function returns an iterator to the first
+// element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename DenseMatrixProxy<PT,MT>::ConstIterator
+ cbegin( const DenseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.cbegin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// In case the access proxy represents a matrix-like data structure that provides an end()
+// function, this function returns an iterator just past the last element of row/column \a i of
+// the matrix. In case the given matrix is a row-major matrix the function returns an iterator
+// just past the last element of row \a i, in case it is a column-major matrix the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename DenseMatrixProxy<PT,MT>::Iterator
+ end( const DenseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.end(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// In case the access proxy represents a matrix-like data structure that provides a cend()
+// function, this function returns an iterator just past the last element of row/column \a i of
+// the matrix. In case the given matrix is a row-major matrix the function returns an iterator
+// just past the last element of row \a i, in case it is a column-major matrix the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename DenseMatrixProxy<PT,MT>::ConstIterator
+ cend( const DenseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.cend(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The number of rows of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE size_t rows( const DenseMatrixProxy<PT,MT>& proxy )
+{
+ return proxy.rows();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The number of columns of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE size_t columns( const DenseMatrixProxy<PT,MT>& proxy )
+{
+ return proxy.columns();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The capacity of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE size_t capacity( const DenseMatrixProxy<PT,MT>& proxy )
+{
+ return proxy.capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE size_t capacity( const DenseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.capacity(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The number of non-zero elements in the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseMatrixProxy<PT,MT>& proxy )
+{
+ return proxy.nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.nonZeros(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for non-resizable matrices.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Matrix cannot be resized.
+//
+// This function tries to change the number of rows and columns of a non-resizable matrix. Since
+// the matrix cannot be resized, in case the specified number of rows and columns is not identical
+// to the current number of rows and columns of the matrix, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE DisableIf_< IsResizable<MT> >
+ resize_backend( const DenseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+
+ if( proxy.rows() != m || proxy.columns() != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix cannot be resized" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for resizable, non-square matrices.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function changes the number of rows and columns of the given resizable, non-square matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsResizable<MT>, Not< IsSquare<MT> > > >
+ resize_backend( const DenseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve )
+{
+ proxy.resize( m, n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for resizable, square matrices.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid resize arguments for square matrix.
+//
+// This function changes the number of rows and columns of the given resizable, square matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsResizable<MT>, IsSquare<MT> > >
+ resize_backend( const DenseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve )
+{
+ if( m != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid resize arguments for square matrix" );
+ }
+
+ proxy.resize( m, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid resize arguments for square matrix.
+// \exception std::invalid_argument Matrix cannot be resized.
+//
+// This function resizes the represented matrix to the specified dimensions. In contrast to
+// the \c resize() member function, which is only available on resizable matrix types, this
+// function can be used on both resizable and non-resizable matrices. In case the given matrix
+// of type \a MT is resizable (i.e. provides a \c resize function) the type-specific \c resize()
+// member function is called. Depending on the type \a MT, this may result in the allocation of
+// new dynamic memory and the invalidation of existing views (submatrices, rows, columns, ...).
+// Note that in case the matrix is a compile time square matrix (as for instance the
+// blaze::SymmetricMatrix adaptor, ...) the specified number of rows must be identical to the
+// number of columns. Otherwise a \a std::invalid_argument exception is thrown. If the matrix
+// type \a MT is non-resizable (i.e. does not provide a \c resize() function) and if the specified
+// number of rows and columns is not identical to the current number of rows and columns of the
+// matrix, a \a std::invalid_argument exception is thrown.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void resize( const DenseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve )
+{
+ resize_backend( proxy, m, n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets all elements of the matrix to the default initial values.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void reset( const DenseMatrixProxy<PT,MT>& proxy )
+{
+ proxy.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets all elements in the specified row/column of the given matrix to their
+// default value. In case the given matrix is a \a rowMajor matrix the function resets the values
+// in row \a i, if it is a \a columnMajor matrix the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void reset( const DenseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ proxy.reset(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the matrix to its default initial state.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void clear( const DenseMatrixProxy<PT,MT>& proxy )
+{
+ proxy.clear();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/proxy/DenseVectorProxy.h b/src/cpu/blaze/math/proxy/DenseVectorProxy.h
new file mode 100644
index 00000000..0405c81e
--- /dev/null
+++ b/src/cpu/blaze/math/proxy/DenseVectorProxy.h
@@ -0,0 +1,757 @@
+//=================================================================================================
+/*!
+// \file blaze/math/proxy/DenseVectorProxy.h
+// \brief Header file for the DenseVectorProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PROXY_DENSEVECTORPROXY_H_
+#define _BLAZE_MATH_PROXY_DENSEVECTORPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Proxy backend for dense vector types.
+// \ingroup math
+//
+// The DenseVectorProxy class serves as a backend for the Proxy class. It is used in case the
+// data type represented by the proxy is a dense vector and augments the Proxy interface by
+// the complete interface required of dense vectors.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+class DenseVectorProxy : public DenseVector< PT, IsRowVector<VT>::value >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Type of the vector elements.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations
+ typedef CompositeType_<VT> CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<VT> Reference; //!< Reference to a non-constant vector value.
+ typedef ConstReference_<VT> ConstReference; //!< Reference to a constant vector value.
+ typedef Pointer_<VT> Pointer; //!< Pointer to a non-constant vector value.
+ typedef ConstPointer_<VT> ConstPointer; //!< Pointer to a constant vector value.
+ typedef Iterator_<VT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<VT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SIMD optimization.
+ enum : bool { simdEnabled = VT::simdEnabled };
+
+ //! Compilation flag for SMP assignments.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) const;
+ inline Reference at( size_t index ) const;
+
+ inline Pointer data () const;
+ inline Iterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const;
+ inline size_t capacity() const;
+ inline size_t nonZeros() const;
+ inline void reset() const;
+ inline void clear() const;
+ inline void resize( size_t n, bool preserve=true ) const;
+ inline void extend( size_t n, bool preserve=true ) const;
+ inline void reserve( size_t n ) const;
+
+ template< typename Other > inline void scale( const Other& scalar ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline typename DenseVectorProxy<PT,VT>::Reference
+ DenseVectorProxy<PT,VT>::operator[]( size_t index ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get()[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::out_of_range Invalid vector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline typename DenseVectorProxy<PT,VT>::Reference
+ DenseVectorProxy<PT,VT>::at( size_t index ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().at( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to vector elements.
+//
+// \return Pointer to the internal element storage.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function returns a pointer to the internal storage of the dynamic vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline typename DenseVectorProxy<PT,VT>::Pointer DenseVectorProxy<PT,VT>::data() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().data();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the represented vector.
+//
+// \return Iterator to the first element of the vector.
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline typename DenseVectorProxy<PT,VT>::Iterator DenseVectorProxy<PT,VT>::begin() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().begin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the represented vector.
+//
+// \return Iterator to the first element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline typename DenseVectorProxy<PT,VT>::ConstIterator DenseVectorProxy<PT,VT>::cbegin() const
+{
+ return (~*this).get().cbegin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the represented vector.
+//
+// \return Iterator just past the last element of the vector.
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline typename DenseVectorProxy<PT,VT>::Iterator DenseVectorProxy<PT,VT>::end() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().end();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the represented vector.
+//
+// \return Iterator just past the last element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline typename DenseVectorProxy<PT,VT>::ConstIterator DenseVectorProxy<PT,VT>::cend() const
+{
+ return (~*this).get().cend();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the represented vector.
+//
+// \return The size of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline size_t DenseVectorProxy<PT,VT>::size() const
+{
+ return (~*this).get().size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the represented vector.
+//
+// \return The capacity of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline size_t DenseVectorProxy<PT,VT>::capacity() const
+{
+ return (~*this).get().capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the represented vector.
+//
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline size_t DenseVectorProxy<PT,VT>::nonZeros() const
+{
+ return (~*this).get().nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial value.
+//
+// \return void
+//
+// This function resets all elements of the vector to the default initial values.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline void DenseVectorProxy<PT,VT>::reset() const
+{
+ using blaze::reset;
+
+ reset( (~*this).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented vector.
+//
+// \return void
+//
+// This function clears the vector to its default initial state.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline void DenseVectorProxy<PT,VT>::clear() const
+{
+ using blaze::clear;
+
+ clear( (~*this).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the represented vector.
+//
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function changes the size of the vector. Depending on the type of the vector, during this
+// operation new dynamic memory may be allocated in case the capacity of the vector is too small.
+// Note that this function may invalidate all existing views (subvectors, ...) on the vector if
+// it is used to shrink the vector. Additionally, the resize() operation potentially changes all
+// vector elements. In order to preserve the old vector values, the \a preserve flag can be set
+// to \a true. However, note that depending on the type of the vector new vector elements may not
+// initialized!
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline void DenseVectorProxy<PT,VT>::resize( size_t n, bool preserve ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().resize( n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Extending the size of the represented vector.
+//
+// \param n Number of additional vector elements.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function extends the size of the vector. Depending on the type of the vector, during this
+// operation new dynamic memory may be allocated in case the capacity of the vector is too small.
+// Therefore this function potentially changes all vector elements. In order to preserve the old
+// vector values, the \a preserve flag can be set to \a true. However, note that depending on the
+// type vector new vector elements may not initialized!
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline void DenseVectorProxy<PT,VT>::extend( size_t n, bool preserve ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().extend( n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the represented vector.
+//
+// \param n The new minimum capacity of the vector.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function increases the capacity of the vector to at least \a n elements. The current
+// values of the vector elements are preserved.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+inline void DenseVectorProxy<PT,VT>::reserve( size_t n ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().reserve( n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the vector scaling.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+template< typename Other > // Data type of the scalar value
+inline void DenseVectorProxy<PT,VT>::scale( const Other& scalar ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().scale( scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name DenseVectorProxy global functions */
+//@{
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE typename DenseVectorProxy<PT,VT>::Iterator
+ begin( const DenseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE typename DenseVectorProxy<PT,VT>::ConstIterator
+ cbegin( const DenseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE typename DenseVectorProxy<PT,VT>::Iterator
+ end( const DenseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE typename DenseVectorProxy<PT,VT>::ConstIterator
+ cend( const DenseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE size_t size( const DenseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE size_t capacity( const DenseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE void resize( const DenseVectorProxy<PT,VT>& proxy, size_t n, bool preserve=true );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE void reset( const DenseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE void clear( const DenseVectorProxy<PT,VT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return Iterator to the first element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE typename DenseVectorProxy<PT,VT>::Iterator
+ begin( const DenseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.begin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return Iterator to the first element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE typename DenseVectorProxy<PT,VT>::ConstIterator
+ cbegin( const DenseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.cbegin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return Iterator just past the last element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE typename DenseVectorProxy<PT,VT>::Iterator
+ end( const DenseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.end();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return Iterator just past the last element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE typename DenseVectorProxy<PT,VT>::ConstIterator
+ cend( const DenseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.cend();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The size of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE size_t size( const DenseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The capacity of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE size_t capacity( const DenseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for non-resizable vectors.
+// \ingroup math
+//
+// \param proxy The given access proxy
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Vector cannot be resized.
+//
+// This function tries to change the number of rows and columns of a non-resizable vector. Since
+// the vector cannot be resized, in case the specified size is not identical to the current size
+// of the vector, a \a std::invalid_argument exception is thrown.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE DisableIf_< IsResizable<VT> >
+ resize_backend( const DenseVectorProxy<PT,VT>& proxy, size_t n, bool preserve )
+{
+ UNUSED_PARAMETER( preserve );
+
+ if( proxy.size() != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector cannot be resized" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for resizable vectors.
+// \ingroup math
+//
+// \param proxy The given access proxy
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+//
+// This function changes the size of the given resizable vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE EnableIf_< IsResizable<VT> >
+ resize_backend( const DenseVectorProxy<PT,VT>& proxy, size_t n, bool preserve )
+{
+ proxy.resize( n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Vector cannot be resized.
+//
+// This function resizes the represented vector to the specified \a size. Note that in contrast
+// to the \c resize() member function, which is only available on resizable vector types, this
+// function can be used on both resizable and non-resizable vectors. In case the type \a VT of
+// the represented vector is resizable (i.e. provides a \c resize() function), the type-specific
+// \c resize() member function is called. Depending on the type \a VT, this may result in the
+// allocation of new dynamic memory and the invalidation of existing views (subvectors, ...). In
+// case \a VT is non-resizable (i.e. does not provide a \c resize() function) and if the specified
+// size is not identical to the current size of the vector, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE void resize( const DenseVectorProxy<PT,VT>& proxy, size_t n, bool preserve )
+{
+ resize_backend( proxy, n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented vector to the default initial values.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets all elements of the vector to the default initial values.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE void reset( const DenseVectorProxy<PT,VT>& proxy )
+{
+ proxy.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the vector to its default initial state.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the dense vector
+BLAZE_ALWAYS_INLINE void clear( const DenseVectorProxy<PT,VT>& proxy )
+{
+ proxy.clear();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/proxy/Forward.h b/src/cpu/blaze/math/proxy/Forward.h
new file mode 100644
index 00000000..8e0d6f3c
--- /dev/null
+++ b/src/cpu/blaze/math/proxy/Forward.h
@@ -0,0 +1,57 @@
+//=================================================================================================
+/*!
+// \file blaze/math/proxy/Forward.h
+// \brief Header file for all forward declarations for proxies
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PROXY_FORWARD_H_
+#define _BLAZE_MATH_PROXY_FORWARD_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+template< typename, typename > class ComplexProxy;
+template< typename, typename > class DefaultProxy;
+template< typename, typename > class DenseMatrixProxy;
+template< typename, typename > class DenseVectorProxy;
+template< typename, typename > class Proxy;
+template< typename, typename > class SparseMatrixProxy;
+template< typename, typename > class SparseVectorProxy;
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/proxy/Proxy.h b/src/cpu/blaze/math/proxy/Proxy.h
new file mode 100644
index 00000000..1547296c
--- /dev/null
+++ b/src/cpu/blaze/math/proxy/Proxy.h
@@ -0,0 +1,1793 @@
+//=================================================================================================
+/*!
+// \file blaze/math/proxy/Proxy.h
+// \brief Header file for the Proxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PROXY_PROXY_H_
+#define _BLAZE_MATH_PROXY_PROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/InversionFlag.h>
+#include <blaze/math/proxy/ComplexProxy.h>
+#include <blaze/math/proxy/DefaultProxy.h>
+#include <blaze/math/proxy/DenseMatrixProxy.h>
+#include <blaze/math/proxy/DenseVectorProxy.h>
+#include <blaze/math/proxy/SparseMatrixProxy.h>
+#include <blaze/math/proxy/SparseVectorProxy.h>
+#include <blaze/math/shims/Abs.h>
+#include <blaze/math/shims/Acos.h>
+#include <blaze/math/shims/Acosh.h>
+#include <blaze/math/shims/Asin.h>
+#include <blaze/math/shims/Asinh.h>
+#include <blaze/math/shims/Atan.h>
+#include <blaze/math/shims/Atanh.h>
+#include <blaze/math/shims/Cbrt.h>
+#include <blaze/math/shims/Ceil.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Cos.h>
+#include <blaze/math/shims/Cosh.h>
+#include <blaze/math/shims/Erf.h>
+#include <blaze/math/shims/Erfc.h>
+#include <blaze/math/shims/Exp.h>
+#include <blaze/math/shims/Floor.h>
+#include <blaze/math/shims/Imaginary.h>
+#include <blaze/math/shims/InvCbrt.h>
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/InvSqrt.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Pow.h>
+#include <blaze/math/shims/Real.h>
+#include <blaze/math/shims/Sin.h>
+#include <blaze/math/shims/Sinh.h>
+#include <blaze/math/shims/Sqrt.h>
+#include <blaze/math/shims/Tan.h>
+#include <blaze/math/shims/Tanh.h>
+#include <blaze/math/traits/AddExprTrait.h>
+#include <blaze/math/traits/DivExprTrait.h>
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/math/traits/SubExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsProxy.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Proxy base class.
+// \ingroup math
+//
+// The Proxy class is a base class for all proxy classes within the \b Blaze library that may
+// represent non-numeric data types (vectors, matrices, ...). It augments the interface of the
+// deriving proxy class depending on the data type represented by the proxy. In addition, it
+// provides an abstraction from the actual type of the proxy, but enables a type-safe conversion
+// back to this type via the 'Curiously Recurring Template Pattern' (CRTP).
+//
+// In order to use the Proxy class it is necessary to publicly derive from it and to provide
+// an accessible member function called \a get(), which grants access to the represented element
+// via non-const reference. The following example demonstrates these requirements by means of
+// the VectorAccessProxy class:
+
+ \code
+ template< typename VT >
+ class VectorAccessProxy : public Proxy< VectorAccessProxy<VT>, typename VT::ElementType >
+ {
+ // ...
+ typedef typename VT::ElementType RepresentedType;
+ inline RepresentedType& get() const;
+ // ...
+ };
+ \endcode
+
+// The first template parameter specifies the type of the deriving proxy class (CRTP), the second
+// template parameter specifies the type of the element represented by the proxy. Within the
+// context of the VectorAccessProxy this is the type of the elements of the vector to be accessed.
+// Depending on this type the proxy selects the additional interface to provide to the deriving
+// class.
+*/
+template< typename PT // Type of the proxy
+ , typename RT = int > // Type of the represented element
+class Proxy : public If_< IsVector<RT>
+ , If_< IsDenseVector<RT>
+ , DenseVectorProxy<PT,RT>
+ , SparseVectorProxy<PT,RT> >
+ , If_< IsMatrix<RT>
+ , If_< IsDenseMatrix<RT>
+ , DenseMatrixProxy<PT,RT>
+ , SparseMatrixProxy<PT,RT> >
+ , If_< IsComplex<RT>
+ , ComplexProxy<PT,RT>
+ , DefaultProxy<PT,RT> > > >
+{};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Proxy operators */
+//@{
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline AddExprTrait_<RT1,RT2>
+ operator+( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, AddExprTrait_<RT,T> >
+ operator+( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, AddExprTrait_<T,RT> >
+ operator+( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline SubExprTrait_<RT1,RT2>
+ operator-( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, SubExprTrait_<RT,T> >
+ operator-( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, SubExprTrait_<T,RT> >
+ operator-( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline MultExprTrait_<RT1,RT2>
+ operator*( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, MultExprTrait_<RT,T> >
+ operator*( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, MultExprTrait_<T,RT> >
+ operator*( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline DivExprTrait_<RT1,RT2>
+ operator/( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, DivExprTrait_<RT,T> >
+ operator/( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, DivExprTrait_<T,RT> >
+ operator/( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator==( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator==( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator==( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator!=( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator!=( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator!=( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator<( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator<( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator<( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator>( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator>( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator>( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator<=( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator<=( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator<=( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator>=( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs );
+
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator>=( const Proxy<PT,RT>& lhs, const T& rhs );
+
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator>=( const T& lhs, const Proxy<PT,RT>& rhs );
+
+template< typename PT, typename RT >
+inline std::ostream& operator<<( std::ostream& os, const Proxy<PT,RT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return The result of the addition.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline AddExprTrait_<RT1,RT2>
+ operator+( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return (~lhs).get() + (~rhs).get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return The result of the addition.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, AddExprTrait_<RT,T> >
+ operator+( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return (~lhs).get() + rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return The result of the addition.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, AddExprTrait_<T,RT> >
+ operator+( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return lhs + (~rhs).get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return The result of the subtraction.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline SubExprTrait_<RT1,RT2>
+ operator-( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return (~lhs).get() - (~rhs).get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return The result of the subtraction.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, SubExprTrait_<RT,T> >
+ operator-( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return (~lhs).get() - rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return The result of the subtraction.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, SubExprTrait_<T,RT> >
+ operator-( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return lhs - (~rhs).get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return The result of the multiplication.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline MultExprTrait_<RT1,RT2>
+ operator*( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return (~lhs).get() * (~rhs).get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return The result of the multiplication.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, MultExprTrait_<RT,T> >
+ operator*( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return (~lhs).get() * rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return The result of the multiplication.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, MultExprTrait_<T,RT> >
+ operator*( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return lhs * (~rhs).get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return The result of the division.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline DivExprTrait_<RT1,RT2>
+ operator/( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return (~lhs).get() / (~rhs).get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return The result of the division.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, DivExprTrait_<RT,T> >
+ operator/( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return (~lhs).get() / rhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return The result of the division.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, DivExprTrait_<T,RT> >
+ operator/( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return lhs / (~rhs).get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if both referenced values are equal, \a false if they are not.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator==( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return ( (~lhs).get() == (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return \a true if the referenced value and the other object are equal, \a false if they are not.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator==( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return ( (~lhs).get() == rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the other object and the referenced value are equal, \a false if they are not.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator==( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return ( lhs == (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if both referenced values are not equal, \a false if they are.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator!=( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return ( (~lhs).get() != (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return \a true if the referenced value and the other object are not equal, \a false if they are.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator!=( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return ( (~lhs).get() != rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inquality comparison between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the other object and the referenced value are not equal, \a false if they are.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator!=( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return ( lhs != (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the left-hand side referenced value is smaller, \a false if not.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator<( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return ( (~lhs).get() < (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return \a true if the left-hand side referenced value is smaller, \a false if not.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator<( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return ( (~lhs).get() < rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the left-hand side other object is smaller, \a false if not.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator<( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return ( lhs < rhs.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the left-hand side referenced value is greater, \a false if not.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator>( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return ( (~lhs).get() > (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return \a true if the left-hand side referenced value is greater, \a false if not.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator>( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return ( (~lhs).get() > rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the left-hand side other object is greater, \a false if not.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator>( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return ( lhs > (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the left-hand side referenced value is smaller or equal, \a false if not.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator<=( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return ( (~lhs).get() <= (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return \a true if the left-hand side referenced value is smaller or equal, \a false if not.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator<=( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return ( (~lhs).get() <= rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the left-hand side other object is smaller or equal, \a false if not.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator<=( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return ( lhs <= (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between two Proxy objects.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the left-hand side referenced value is greater or equal, \a false if not.
+*/
+template< typename PT1, typename RT1, typename PT2, typename RT2 >
+inline bool operator>=( const Proxy<PT1,RT1>& lhs, const Proxy<PT2,RT2>& rhs )
+{
+ return ( (~lhs).get() >= (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between a Proxy object and an object of different type.
+// \ingroup math
+//
+// \param lhs The left-hand side Proxy object.
+// \param rhs The right-hand side object of other type.
+// \return \a true if the left-hand side referenced value is greater or equal, \a false if not.
+*/
+template< typename PT, typename RT, typename T >
+inline DisableIf_< IsProxy<T>, bool >
+ operator>=( const Proxy<PT,RT>& lhs, const T& rhs )
+{
+ return ( (~lhs).get() >= rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between an object of different type and a Proxy object.
+// \ingroup math
+//
+// \param lhs The left-hand side object of other type.
+// \param rhs The right-hand side Proxy object.
+// \return \a true if the left-hand side other object is greater or equal, \a false if not.
+*/
+template< typename T, typename PT, typename RT >
+inline DisableIf_< IsProxy<T>, bool >
+ operator>=( const T& lhs, const Proxy<PT,RT>& rhs )
+{
+ return ( lhs >= (~rhs).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Global output operator for the Proxy class template.
+// \ingroup math
+//
+// \param os Reference to the output stream.
+// \param proxy Reference to a constant proxy object.
+// \return Reference to the output stream.
+*/
+template< typename PT, typename RT >
+inline std::ostream& operator<<( std::ostream& os, const Proxy<PT,RT>& proxy )
+{
+ return os << (~proxy).get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Proxy global functions */
+//@{
+template< typename PT, typename RT >
+inline auto trans( const Proxy<PT,RT>& proxy )
+ -> decltype( trans( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto ctrans( const Proxy<PT,RT>& proxy )
+ -> decltype( ctrans( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto abs( const Proxy<PT,RT>& proxy )
+ -> decltype( abs( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto conj( const Proxy<PT,RT>& proxy )
+ -> decltype( conj( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto real( const Proxy<PT,RT>& proxy )
+ -> decltype( real( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto imag( const Proxy<PT,RT>& proxy )
+ -> decltype( imag( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto sqrt( const Proxy<PT,RT>& proxy )
+ -> decltype( sqrt( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto invsqrt( const Proxy<PT,RT>& proxy )
+ -> decltype( invsqrt( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto cbrt( const Proxy<PT,RT>& proxy )
+ -> decltype( cbrt( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto invcbrt( const Proxy<PT,RT>& proxy )
+ -> decltype( invcbrt( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto floor( const Proxy<PT,RT>& proxy )
+ -> decltype( floor( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto ceil( const Proxy<PT,RT>& proxy )
+ -> decltype( ceil( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT, typename ET >
+inline auto pow( const Proxy<PT,RT>& proxy, const ET& exp )
+ -> decltype( pow( std::declval< RepresentedType_<PT> >(), exp ) );
+
+template< typename PT, typename RT >
+inline auto exp( const Proxy<PT,RT>& proxy )
+ -> decltype( exp( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto sin( const Proxy<PT,RT>& proxy )
+ -> decltype( sin( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto asin( const Proxy<PT,RT>& proxy )
+ -> decltype( asin( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto sinh( const Proxy<PT,RT>& proxy )
+ -> decltype( sinh( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto asinh( const Proxy<PT,RT>& proxy )
+ -> decltype( asinh( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto cos( const Proxy<PT,RT>& proxy )
+ -> decltype( cos( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto acos( const Proxy<PT,RT>& proxy )
+ -> decltype( acos( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto cosh( const Proxy<PT,RT>& proxy )
+ -> decltype( cosh( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto acosh( const Proxy<PT,RT>& proxy )
+ -> decltype( acosh( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto tan( const Proxy<PT,RT>& proxy )
+ -> decltype( tan( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto atan( const Proxy<PT,RT>& proxy )
+ -> decltype( atan( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto tanh( const Proxy<PT,RT>& proxy )
+ -> decltype( tanh( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline auto atanh( const Proxy<PT,RT>& proxy )
+ -> decltype( atanh( std::declval< RepresentedType_<PT> >() ) );
+
+template< typename PT, typename RT >
+inline void transpose( const Proxy<PT,RT>& proxy );
+
+template< typename PT, typename RT >
+inline void ctranspose( const Proxy<PT,RT>& proxy );
+
+template< typename PT, typename RT >
+inline void invert( const Proxy<PT,RT>& proxy );
+
+template< InversionFlag IF, typename PT, typename RT >
+inline void invert( const Proxy<PT,RT>& proxy );
+
+template< typename PT, typename RT >
+inline bool isReal( const Proxy<PT,RT>& proxy );
+
+template< typename PT, typename RT >
+inline bool isZero( const Proxy<PT,RT>& proxy );
+
+template< typename PT, typename RT >
+inline bool isOne( const Proxy<PT,RT>& proxy );
+
+template< typename PT, typename RT >
+inline bool isnan( const Proxy<PT,RT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the transpose of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The transpose of the represented element.
+//
+// This function returns an expression representing the transpose of the element represented by
+// the proxy.
+*/
+template< typename PT, typename RT >
+inline auto trans( const Proxy<PT,RT>& proxy )
+ -> decltype( trans( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::trans;
+
+ return trans( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the conjugate transpose of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The conjugate transpose of the represented element.
+//
+// This function returns an expression representing the conjugate transpose of the element
+// represented by the proxy.
+*/
+template< typename PT, typename RT >
+inline auto ctrans( const Proxy<PT,RT>& proxy )
+ -> decltype( ctrans( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::ctrans;
+
+ return ctrans( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the absolute value of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The absolute value of the represented element.
+//
+// This function computes the absolute value of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the absolute values of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto abs( const Proxy<PT,RT>& proxy )
+ -> decltype( abs( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::abs;
+
+ return abs( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the complex conjugate of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The complex conjugate of the represented element.
+//
+// This function computes the complex conjugate of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns an
+// expression representing the complex conjugate of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto conj( const Proxy<PT,RT>& proxy )
+ -> decltype( conj( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::conj;
+
+ return conj( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the real part of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The real part of the represented element.
+//
+// This function returns the real part of the element represented by the proxy. In case the
+// proxy represents a vector- or matrix-like data structure the function returns an expression
+// representing the real part of each each element of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto real( const Proxy<PT,RT>& proxy )
+ -> decltype( real( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::real;
+
+ return real( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the imaginary part of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The imaginary part of the represented element.
+//
+// This function returns the imaginary part of the element represented by the proxy. In case the
+// proxy represents a vector- or matrix-like data structure the function returns an expression
+// representing the real part of each each element of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto imag( const Proxy<PT,RT>& proxy )
+ -> decltype( imag( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::imag;
+
+ return imag( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the square root of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The square root of the represented element.
+//
+// This function computes the square root of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the square roots of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto sqrt( const Proxy<PT,RT>& proxy )
+ -> decltype( sqrt( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::sqrt;
+
+ return sqrt( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the inverse square root of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The inverse square root of the represented element.
+//
+// This function computes the inverse square root of the element represented by the proxy.
+// In case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the inverse square roots of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto invsqrt( const Proxy<PT,RT>& proxy )
+ -> decltype( invsqrt( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::invsqrt;
+
+ return invsqrt( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the cubic root of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The cubic root of the represented element.
+//
+// This function computes the cubic root of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the cubic roots of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto cbrt( const Proxy<PT,RT>& proxy )
+ -> decltype( cbrt( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::cbrt;
+
+ return cbrt( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the inverse cubic root of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The inverse cubic root of the represented element.
+//
+// This function computes the inverse cubic root of the element represented by the proxy.
+// In case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the inverse cubic roots of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto invcbrt( const Proxy<PT,RT>& proxy )
+ -> decltype( invcbrt( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::invcbrt;
+
+ return invcbrt( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the largest integral value that is not greater than the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The largest integral value that is not greater than the represented element.
+//
+// This function computes the largest integral value that is not greater than the element
+// represented by the proxy. In case the proxy represents a vector- or matrix-like data
+// structure the function returns an expression representing the operation.
+*/
+template< typename PT, typename RT >
+inline auto floor( const Proxy<PT,RT>& proxy )
+ -> decltype( floor( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::floor;
+
+ return floor( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computes the smallest integral value that is not less than the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The smallest integral value that is not less than the represented element.
+//
+// This function computes the smallest integral value that is not less than the element
+// represented by the proxy. In case the proxy represents a vector- or matrix-like data
+// structure the function returns an expression representing the operation.
+*/
+template< typename PT, typename RT >
+inline auto ceil( const Proxy<PT,RT>& proxy )
+ -> decltype( ceil( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::ceil;
+
+ return ceil( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the exponential value of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \param exp The exponent.
+// \return The exponential value of the represented element.
+//
+// This function computes the exponential value of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the exponential value of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT, typename ET >
+inline auto pow( const Proxy<PT,RT>& proxy, const ET& exp )
+ -> decltype( pow( std::declval< RepresentedType_<PT> >(), exp ) )
+{
+ using blaze::pow;
+
+ return pow( (~proxy).get(), exp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the base-e exponential of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The base-e exponential of the represented element.
+//
+// This function computes the base-e exponential of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the base-e exponentials of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto exp( const Proxy<PT,RT>& proxy )
+ -> decltype( exp( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::exp;
+
+ return exp( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the sine of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The sine of the represented element.
+//
+// This function computes the sine of the element represented by the proxy. In case the
+// proxy represents a vector- or matrix-like data structure the function returns an expression
+// representing the sines of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto sin( const Proxy<PT,RT>& proxy )
+ -> decltype( sin( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::sin;
+
+ return sin( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the inverse sine of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The inverse sine of the represented element.
+//
+// This function computes the inverse sine of the element represented by the proxy. In case the
+// proxy represents a vector- or matrix-like data structure the function returns an expression
+// representing the inverse sines of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto asin( const Proxy<PT,RT>& proxy )
+ -> decltype( asin( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::asin;
+
+ return asin( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the hyperbolic sine of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The hyperbolic sine of the represented element.
+//
+// This function computes the hyperbolic sine of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the hyperbolic sines of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto sinh( const Proxy<PT,RT>& proxy )
+ -> decltype( sinh( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::sinh;
+
+ return sinh( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the inverse hyperbolic sine of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The inverse hyperbolic sine of the represented element.
+//
+// This function computes the inverse hyperbolic sine of the element represented by the proxy.
+// In case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the inverse hyperbolic sines of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto asinh( const Proxy<PT,RT>& proxy )
+ -> decltype( asinh( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::asinh;
+
+ return asinh( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the cosine of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The cosine of the represented element.
+//
+// This function computes the cosine of the element represented by the proxy. In case the
+// proxy represents a vector- or matrix-like data structure the function returns an expression
+// representing the cosines of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto cos( const Proxy<PT,RT>& proxy )
+ -> decltype( cos( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::cos;
+
+ return cos( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the inverse cosine of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The inverse cosine of the represented element.
+//
+// This function computes the inverse cosine of the element represented by the proxy. In case the
+// proxy represents a vector- or matrix-like data structure the function returns an expression
+// representing the inverse cosines of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto acos( const Proxy<PT,RT>& proxy )
+ -> decltype( acos( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::acos;
+
+ return acos( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the hyperbolic cosine of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The hyperbolic cosine of the represented element.
+//
+// This function computes the hyperbolic cosine of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the hyperbolic cosines of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto cosh( const Proxy<PT,RT>& proxy )
+ -> decltype( cosh( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::cosh;
+
+ return cosh( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the inverse hyperbolic cosine of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The inverse hyperbolic cosine of the represented element.
+//
+// This function computes the inverse hyperbolic cosine of the element represented by the proxy.
+// In case the proxy represents a vector- or matrix-like data structure the function returns an
+// expression representing the inverse hyperbolic cosines of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto acosh( const Proxy<PT,RT>& proxy )
+ -> decltype( acosh( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::acosh;
+
+ return acosh( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the tangent of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The tangent of the represented element.
+//
+// This function computes the tangent of the element represented by the proxy. In case the
+// proxy represents a vector- or matrix-like data structure the function returns an expression
+// representing the tangents of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto tan( const Proxy<PT,RT>& proxy )
+ -> decltype( tan( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::tan;
+
+ return tan( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the inverse tangent of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The inverse tangent of the represented element.
+//
+// This function computes the inverse tangent of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the inverse tangents of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto atan( const Proxy<PT,RT>& proxy )
+ -> decltype( atan( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::atan;
+
+ return atan( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the hyperbolic tangent of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The hyperbolic tangent of the represented element.
+//
+// This function computes the hyperbolic tangent of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the hyperbolic tangents of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto tanh( const Proxy<PT,RT>& proxy )
+ -> decltype( tanh( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::tanh;
+
+ return tanh( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the inverse hyperbolic tangent of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The inverse hyperbolic tangent of the represented element.
+//
+// This function computes the inverse hyperbolic tangent of the element represented by the proxy.
+// In case the proxy represents a vector- or matrix-like data structure the function returns an
+// expression representing the inverse hyperbolic tangents of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto atanh( const Proxy<PT,RT>& proxy )
+ -> decltype( atanh( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::atanh;
+
+ return atanh( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the error function of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The error function of the represented element.
+//
+// This function computes the error function of the element represented by the proxy. In
+// case the proxy represents a vector- or matrix-like data structure the function returns
+// an expression representing the error functions of the elements of the vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto erf( const Proxy<PT,RT>& proxy )
+ -> decltype( erf( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::erf;
+
+ return erf( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Computing the complementary error function of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return The complementary error function of the represented element.
+//
+// This function computes the complementary error function of the element represented by the
+// proxy. In case the proxy represents a vector- or matrix-like data structure the function
+// returns an expression representing the complementary error functions of the elements of the
+// vector/matrix.
+*/
+template< typename PT, typename RT >
+inline auto erfc( const Proxy<PT,RT>& proxy )
+ -> decltype( erfc( std::declval< RepresentedType_<PT> >() ) )
+{
+ using blaze::erfc;
+
+ return erfc( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the represented matrix element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::logic_error Matrix cannot be transposed.
+//
+// This function transposes the represented matrix in-place. The transpose operation fails if ...
+//
+// - ... the represented matrix has a fixed size and is non-square;
+// - ... the represented matrix is a triangular matrix.
+//
+// In all failure cases a \a std::logic_error exception is thrown. Additionally, in case the
+// represented matrix cannot be modified, a \a std::invalid_argument exception is thrown.
+*/
+template< typename PT, typename RT >
+inline void transpose( const Proxy<PT,RT>& proxy )
+{
+ if( (~proxy).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ transpose( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the represented matrix element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::logic_error Matrix cannot be transposed.
+//
+// This function transposes the represented matrix in-place. The transpose operation fails if ...
+//
+// - ... the represented matrix has a fixed size and is non-square;
+// - ... the represented matrix is a triangular matrix.
+//
+// In all failure cases a \a std::logic_error exception is thrown. Additionally, in case the
+// represented matrix cannot be modified, a \a std::invalid_argument exception is thrown.
+*/
+template< typename PT, typename RT >
+inline void ctranspose( const Proxy<PT,RT>& proxy )
+{
+ if( (~proxy).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ ctranspose( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::invalid_argument Inversion of singular matrix failed.
+// \exception std::invalid_argument Invalid non-square matrix provided.
+//
+// This function inverts the represented scalar or dense matrix element. The inversion fails if
+// the represented element is a dense matrix, which ...
+//
+// - ... is not a square matrix;
+// - ... is singular and not invertible.
+//
+// In all failure cases either a compilation error is created if the failure can be predicted at
+// compile time or a \a std::invalid_argument exception is thrown. Additionally, in case the
+// represented scalar or matrix cannot be modified, a \a std::invalid_argument exception is thrown.
+//
+// \note In case the represented element is a dense matrix, this function does not provide any
+// exception safety guarantee, i.e. in case an exception is thrown the matrix may already have
+// been modified.
+//
+// \note In case the represented element is a dense matrix, this function can only be used if the
+// fitting LAPACK library is available and linked to the executable. Otherwise a linker error will
+// be created.
+*/
+template< typename PT, typename RT >
+inline void invert( const Proxy<PT,RT>& proxy )
+{
+ if( (~proxy).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ invert( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the represented element.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::invalid_argument Inversion of singular matrix failed.
+// \exception std::invalid_argument Invalid non-square matrix provided.
+//
+// This function inverts the represented dense matrix element by means of the specified matrix
+// inversion algorithm \c IF:
+
+ \code
+ invert<byLU>( A ); // Inversion of a general matrix
+ invert<byLDLT>( A ); // Inversion of a symmetric indefinite matrix
+ invert<byLDLH>( A ); // Inversion of a Hermitian indefinite matrix
+ invert<byLLH>( A ); // Inversion of a Hermitian positive definite matrix
+ \endcode
+
+// The inversion fails if the represented dense matrix element ...
+//
+// - ... is not a square matrix;
+// - ... is singular and not invertible.
+//
+// In all failure cases either a compilation error is created if the failure can be predicted at
+// compile time or a \a std::invalid_argument exception is thrown. Additionally, in case the
+// represented scalar or matrix cannot be modified, a \a std::invalid_argument exception is thrown.
+//
+// \note In case the represented element is a dense matrix, this function does not provide any
+// exception safety guarantee, i.e. in case an exception is thrown the matrix may already have
+// been modified.
+//
+// \note In case the represented element is a dense matrix, this function can only be used if the
+// fitting LAPACK library is available and linked to the executable. Otherwise a linker error will
+// be created.
+*/
+template< InversionFlag IF, typename PT, typename RT >
+inline void invert( const Proxy<PT,RT>& proxy )
+{
+ if( (~proxy).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ invert<IF>( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the element represents a real number.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return \a true in case the element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the proxy represents the a real
+// number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is
+// equal to 0. Otherwise it returns \a false.
+*/
+template< typename PT, typename RT >
+inline bool isReal( const Proxy<PT,RT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename PT, typename RT >
+inline bool isZero( const Proxy<PT,RT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename PT, typename RT >
+inline bool isOne( const Proxy<PT,RT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( (~proxy).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup math
+//
+// \param proxy The given proxy instance.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename PT, typename RT >
+inline bool isnan( const Proxy<PT,RT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( (~proxy).get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/proxy/SparseMatrixProxy.h b/src/cpu/blaze/math/proxy/SparseMatrixProxy.h
new file mode 100644
index 00000000..89448807
--- /dev/null
+++ b/src/cpu/blaze/math/proxy/SparseMatrixProxy.h
@@ -0,0 +1,1339 @@
+//=================================================================================================
+/*!
+// \file blaze/math/proxy/SparseMatrixProxy.h
+// \brief Header file for the SparseMatrixProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PROXY_SPARSEMATRIXPROXY_H_
+#define _BLAZE_MATH_PROXY_SPARSEMATRIXPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Proxy backend for sparse matrix types.
+// \ingroup math
+//
+// The SparseMatrixProxy class serves as a backend for the Proxy class. It is used in case the
+// data type represented by the proxy is a sparse matrix and augments the Proxy interface by
+// the complete interface required of sparse matrices.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+class SparseMatrixProxy : public SparseMatrix< PT, IsColumnMajorMatrix<MT>::value >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<MT> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<MT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the sparse matrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations.
+ typedef CompositeType_<MT> CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<MT> Reference; //!< Reference to a non-constant matrix value.
+ typedef ConstReference_<MT> ConstReference; //!< Reference to a constant matrix value.
+ typedef Iterator_<MT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<MT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SMP assignments.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j ) const;
+
+ inline Iterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const;
+ inline size_t columns() const;
+ inline size_t capacity() const;
+ inline size_t capacity( size_t i ) const;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset() const;
+ inline void reset( size_t i ) const;
+ inline void clear() const;
+ inline Iterator set( size_t i, size_t j, const ElementType& value ) const;
+ inline Iterator insert( size_t i, size_t j, const ElementType& value ) const;
+ inline void append( size_t i, size_t j, const ElementType& value, bool check=false ) const;
+ inline void finalize( size_t i ) const;
+ inline void erase( size_t i, size_t j ) const;
+ inline Iterator erase( size_t i, Iterator pos ) const;
+ inline Iterator erase( size_t i, Iterator first, Iterator last ) const;
+ inline void resize( size_t m, size_t n, bool preserve=true ) const;
+ inline void reserve( size_t n ) const;
+ inline void reserve( size_t i, size_t n ) const;
+ inline void trim() const;
+ inline void trim( size_t i ) const;
+ inline void transpose() const;
+ inline void ctranspose() const;
+
+ template< typename Other > inline void scale( const Other& scalar ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Function call operator for the direct access to matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function returns a reference to the accessed value at position (\a i,\a j). In case
+// the sparse matrix does not yet store an element at position (\a i,\a j) , a new element is
+// inserted into the sparse matrix. Note that this function only performs an index check in
+// case BLAZE_USER_ASSERT() is active. In contrast, the at() function is guaranteed to perform
+// a check of the given access indices.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Reference
+ SparseMatrixProxy<PT,MT>::operator()( size_t i, size_t j ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get()(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// This function returns a reference to the accessed value at position (\a i,\a j). In case
+// the sparse matrix does not yet store an element at position (\a i,\a j) , a new element is
+// inserted into the sparse matrix. In contrast to the subscript operator this function always
+// performs a check of the given access indices.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Reference
+ SparseMatrixProxy<PT,MT>::at( size_t i, size_t j ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().at(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i of the represented matrix.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::begin( size_t i ) const
+{
+ return (~*this).get().begin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i of the represented matrix.
+//
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::ConstIterator
+ SparseMatrixProxy<PT,MT>::cbegin( size_t i ) const
+{
+ return (~*this).get().cbegin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i of the represented matrix.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::end( size_t i ) const
+{
+ return (~*this).get().end(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i of the represented matrix.
+//
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::ConstIterator
+ SparseMatrixProxy<PT,MT>::cend( size_t i ) const
+{
+ return (~*this).get().cend(i);
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the represented matrix.
+//
+// \return The number of rows of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline size_t SparseMatrixProxy<PT,MT>::rows() const
+{
+ return (~*this).get().rows();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the represented matrix.
+//
+// \return The number of columns of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline size_t SparseMatrixProxy<PT,MT>::columns() const
+{
+ return (~*this).get().columns();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the represented matrix.
+//
+// \return The capacity of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline size_t SparseMatrixProxy<PT,MT>::capacity() const
+{
+ return (~*this).get().capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column of the represented matrix.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline size_t SparseMatrixProxy<PT,MT>::capacity( size_t i ) const
+{
+ return (~*this).get().capacity(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the represented matrix.
+//
+// \return The number of non-zero elements in the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline size_t SparseMatrixProxy<PT,MT>::nonZeros() const
+{
+ return (~*this).get().nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column of the represented matrix.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline size_t SparseMatrixProxy<PT,MT>::nonZeros( size_t i ) const
+{
+ return (~*this).get().nonZeros(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial value.
+//
+// \return void
+//
+// This function resets all elements of the matrix to the default initial values.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::reset() const
+{
+ using blaze::reset;
+
+ reset( (~*this).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::reset( size_t i ) const
+{
+ using blaze::reset;
+
+ reset( (~*this).get(), i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented vector.
+//
+// \return void
+//
+// This function clears the matrix to its default initial state.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::clear() const
+{
+ using blaze::clear;
+
+ clear( (~*this).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting an element of the represented sparse matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+//
+// This function sets the value of an element of the sparse matrix. In case the sparse matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::set( size_t i, size_t j, const ElementType& value ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().set( i, j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting an element into the represented sparse matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::invalid_argument Invalid sparse matrix access index.
+//
+// This function inserts a new element into the sparse matrix. However, duplicate elements are
+// not allowed. In case the sparse matrix already contains an element with row index \a i and
+// column index \a j, a \a std::invalid_argument exception is thrown.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::insert( size_t i, size_t j, const ElementType& value ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().insert( i, j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Appending an element to the specified row/column of the sparse matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function provides a very efficient way to fill a sparse matrix with elements. It appends
+// a new element to the end of the specified row/column without any additional memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::append( size_t i, size_t j, const ElementType& value, bool check ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().append( i, j, value, check );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..M-1]\f$.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::finalize( size_t i ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().finalize( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing an element from the sparse matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function erases an element from the sparse matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::erase( size_t i, size_t j ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().erase( i, j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing an element from the sparse matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function erases an element from the sparse matrix. In case the storage order is set to
+// \a rowMajor the function erases an element from row \a i, in case the storage flag is set to
+// \a columnMajor the function erases an element from column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::erase( size_t i, Iterator pos ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().erase( i, pos );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing a range of elements from the sparse matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function erases a range of element from the sparse matrix. In case the storage order is
+// set to \a rowMajor the function erases a range of elements from row \a i, in case the storage
+// flag is set to \a columnMajor the function erases a range of elements from column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::erase( size_t i, Iterator first, Iterator last ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().erase( i, first, last );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the represented matrix.
+//
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. Depending on
+// the type of the matrix, during this operation new dynamic memory may be allocated in case
+// the capacity of the matrix is too small. Note that this function may invalidate all existing
+// views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the matrix.
+// Additionally, the resize operation potentially changes all matrix elements. In order to
+// preserve the old matrix values, the \a preserve flag can be set to \a true.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::resize( size_t m, size_t n, bool preserve ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().resize( m, n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the represented matrix.
+//
+// \param n The new minimum capacity of the matrix.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function increases the capacity of the sparse matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::reserve( size_t n ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().reserve( n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of a specific row/column of the sparse matrix.
+//
+// \param i The row/column index of the new element \f$[0..M-1]\f$ or \f$[0..N-1]\f$.
+// \param n The new minimum capacity of the specified row/column.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function increases the capacity of row/column \a i of the sparse matrix to at least
+// \a nonzeros elements. The current values of the sparse matrix and all other individual
+// row/column capacities are preserved. In case the storage order is set to \a rowMajor, the
+// function reserves capacity for row \a i and the index has to be in the range \f$[0..M-1]\f$.
+// In case the storage order is set to \a columnMajor, the function reserves capacity for column
+// \a i and the index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::reserve( size_t i, size_t n ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().reserve( i, n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::trim() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().trim();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing all excessive capacity of a specific row/column of the sparse matrix.
+//
+// \param i The index of the row/column to be trimmed (\f$[0..M-1]\f$ or \f$[0..N-1]\f$).
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::trim( size_t i ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().trim( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the represented matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::transpose() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().transpose();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the represented matrix.
+//
+// \return Reference to the transposed matrix.
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline void SparseMatrixProxy<PT,MT>::ctranspose() const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().ctranspose();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the sparse matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the scalar value
+inline void SparseMatrixProxy<PT,MT>::scale( const Other& scalar ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().scale( scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned sparse matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::find( size_t i, size_t j ) const
+{
+ return (~*this).get().find( i, j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::lowerBound( size_t i, size_t j ) const
+{
+ return (~*this).get().lowerBound( i, j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+inline typename SparseMatrixProxy<PT,MT>::Iterator
+ SparseMatrixProxy<PT,MT>::upperBound( size_t i, size_t j ) const
+{
+ return (~*this).get().upperBound( i, j );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SparseMatrixProxy global functions */
+//@{
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE typename SparseMatrixProxy<PT,MT>::Iterator
+ begin( const SparseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE typename SparseMatrixProxy<PT,MT>::ConstIterator
+ cbegin( const SparseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE typename SparseMatrixProxy<PT,MT>::Iterator
+ end( const SparseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE typename SparseMatrixProxy<PT,MT>::ConstIterator
+ cend( const SparseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t rows( const SparseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t columns( const SparseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t capacity( const SparseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t capacity( const SparseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE void resize( const SparseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve=true );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE void reset( const SparseMatrixProxy<PT,MT>& proxy );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE void reset( const SparseMatrixProxy<PT,MT>& proxy, size_t i );
+
+template< typename PT, typename MT >
+BLAZE_ALWAYS_INLINE void clear( const SparseMatrixProxy<PT,MT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the given matrix is a row-major matrix the function returns an iterator to the first element
+// of row \a i, in case it is a column-major matrix the function returns an iterator to the first
+// element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE typename SparseMatrixProxy<PT,MT>::Iterator
+ begin( const SparseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.begin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of row/column \a i of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The row/column index.
+// \return Iterator to the first element of row/column \a i.
+//
+// This function returns a row/column iterator to the first element of row/column \a i. In case
+// the given matrix is a row-major matrix the function returns an iterator to the first element
+// of row \a i, in case it is a column-major matrix the function returns an iterator to the first
+// element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE typename SparseMatrixProxy<PT,MT>::ConstIterator
+ cbegin( const SparseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.cbegin(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// In case the access proxy represents a matrix-like data structure that provides an end()
+// function, this function returns an iterator just past the last element of row/column \a i of
+// the matrix. In case the given matrix is a row-major matrix the function returns an iterator
+// just past the last element of row \a i, in case it is a column-major matrix the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE typename SparseMatrixProxy<PT,MT>::Iterator
+ end( const SparseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.end(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of row/column \a i of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The row/column index.
+// \return Iterator just past the last element of row/column \a i.
+//
+// In case the access proxy represents a matrix-like data structure that provides a cend()
+// function, this function returns an iterator just past the last element of row/column \a i of
+// the matrix. In case the given matrix is a row-major matrix the function returns an iterator
+// just past the last element of row \a i, in case it is a column-major matrix the function
+// returns an iterator just past the last element of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE typename SparseMatrixProxy<PT,MT>::ConstIterator
+ cend( const SparseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.cend(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The number of rows of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE size_t rows( const SparseMatrixProxy<PT,MT>& proxy )
+{
+ return proxy.rows();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The number of columns of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE size_t columns( const SparseMatrixProxy<PT,MT>& proxy )
+{
+ return proxy.columns();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The capacity of the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE size_t capacity( const SparseMatrixProxy<PT,MT>& proxy )
+{
+ return proxy.capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE size_t capacity( const SparseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.capacity(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The number of non-zero elements in the matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseMatrixProxy<PT,MT>& proxy )
+{
+ return proxy.nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ return proxy.nonZeros(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for non-square matrices.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function changes the number of rows and columns of the given non-square matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE DisableIf_< IsSquare<MT> >
+ resize_backend( const SparseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve )
+{
+ proxy.resize( m, n, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation of the \c resize() function for square matrices.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid resize arguments for square matrix.
+//
+// This function changes the number of rows and columns of the given square matrix.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE EnableIf_< IsSquare<MT> >
+ resize_backend( const SparseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve )
+{
+ if( m != n ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid resize arguments for square matrix" );
+ }
+
+ proxy.resize( m, preserve );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param m The new number of rows of the matrix.
+// \param n The new number of columns of the matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid resize arguments for square matrix.
+//
+// This function resizes the represented matrix to the specified dimensions. Note that in case
+// the matrix is a compile time square matrix (as for instance the blaze::SymmetricMatrix adaptor,
+// ...) the specified number of rows must be identical to the number of columns. Otherwise a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE void resize( const SparseMatrixProxy<PT,MT>& proxy, size_t m, size_t n, bool preserve )
+{
+ resize_backend( proxy, m, n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets all elements of the matrix to the default initial values.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE void reset( const SparseMatrixProxy<PT,MT>& proxy )
+{
+ proxy.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column of the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets all elements in the specified row/column of the given matrix to their
+// default value. In case the given matrix is a \a rowMajor matrix the function resets the values
+// in row \a i, if it is a \a columnMajor matrix the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE void reset( const SparseMatrixProxy<PT,MT>& proxy, size_t i )
+{
+ proxy.reset(i);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented matrix.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the matrix to its default initial state.
+*/
+template< typename PT // Type of the proxy
+ , typename MT > // Type of the sparse matrix
+BLAZE_ALWAYS_INLINE void clear( const SparseMatrixProxy<PT,MT>& proxy )
+{
+ proxy.clear();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/proxy/SparseVectorProxy.h b/src/cpu/blaze/math/proxy/SparseVectorProxy.h
new file mode 100644
index 00000000..7786e164
--- /dev/null
+++ b/src/cpu/blaze/math/proxy/SparseVectorProxy.h
@@ -0,0 +1,886 @@
+//=================================================================================================
+/*!
+// \file blaze/math/proxy/SparseVectorProxy.h
+// \brief Header file for the SparseVectorProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_PROXY_SPARSEVECTORPROXY_H_
+#define _BLAZE_MATH_PROXY_SPARSEVECTORPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Proxy backend for sparse vector types.
+// \ingroup math
+//
+// The SparseVectorProxy class serves as a backend for the Proxy class. It is used in case the
+// data type represented by the proxy is a sparse vector and augments the Proxy interface by
+// the complete interface required of sparse vectors.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+class SparseVectorProxy : public SparseVector< PT, IsRowVector<VT>::value >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef ResultType_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<VT> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Type of the sparse vector elements.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations.
+ typedef CompositeType_<VT> CompositeType; //!< Data type for composite expression templates.
+ typedef Reference_<VT> Reference; //!< Reference to a non-constant vector value.
+ typedef ConstReference_<VT> ConstReference; //!< Reference to a constant vector value.
+ typedef Iterator_<VT> Iterator; //!< Iterator over non-constant elements.
+ typedef ConstIterator_<VT> ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SMP assignments.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) const;
+ inline Reference at( size_t index ) const;
+
+ inline Iterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const;
+ inline size_t capacity() const;
+ inline size_t nonZeros() const;
+ inline void reset() const;
+ inline void clear() const;
+ inline Iterator set( size_t index, const ElementType& value ) const;
+ inline Iterator insert( size_t index, const ElementType& value ) const;
+ inline void append( size_t index, const ElementType& value, bool check=false ) const;
+ inline void erase( size_t index ) const;
+ inline Iterator erase( Iterator pos ) const;
+ inline Iterator erase( Iterator first, Iterator last ) const;
+ inline void resize( size_t n, bool preserve=true ) const;
+ inline void reserve( size_t n ) const;
+
+ template< typename Other > inline void scale( const Other& scalar ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index ) const;
+ inline Iterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t index ) const;
+ inline Iterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t index ) const;
+ inline Iterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function returns a reference to the accessed value at position \a index. In case the
+// sparse vector does not yet store an element for index \a index, a new element is inserted
+// into the sparse vector. A more efficient alternative for traversing the non-zero elements
+// of the sparse vector are the begin() and end() functions.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Reference
+ SparseVectorProxy<PT,VT>::operator[]( size_t index ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get()[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::out_of_range Invalid vector access index.
+//
+// This function returns a reference to the accessed value at position \a index. In case the
+// sparse vector does not yet store an element for index \a index, a new element is inserted
+// into the sparse vector. In contrast to the subscript operator this function always performs
+// a check of the given access index.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Reference
+ SparseVectorProxy<PT,VT>::at( size_t index ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().at( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the represented vector.
+//
+// \return Iterator to the first element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator SparseVectorProxy<PT,VT>::begin() const
+{
+ return (~*this).get().begin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the represented vector.
+//
+// \return Iterator to the first element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::ConstIterator SparseVectorProxy<PT,VT>::cbegin() const
+{
+ return (~*this).get().cbegin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the represented vector.
+//
+// \return Iterator just past the last element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator SparseVectorProxy<PT,VT>::end() const
+{
+ return (~*this).get().end();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the represented vector.
+//
+// \return Iterator just past the last element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::ConstIterator SparseVectorProxy<PT,VT>::cend() const
+{
+ return (~*this).get().cend();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the represented vector.
+//
+// \return The size of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline size_t SparseVectorProxy<PT,VT>::size() const
+{
+ return (~*this).get().size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the represented vector.
+//
+// \return The capacity of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline size_t SparseVectorProxy<PT,VT>::capacity() const
+{
+ return (~*this).get().capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the represented vector.
+//
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always smaller than the current size of the
+// sparse vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline size_t SparseVectorProxy<PT,VT>::nonZeros() const
+{
+ return (~*this).get().nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial value.
+//
+// \return void
+//
+// This function resets all elements of the vector to the default initial values.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline void SparseVectorProxy<PT,VT>::reset() const
+{
+ using blaze::reset;
+
+ reset( (~*this).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented vector.
+//
+// \return void
+//
+// This function clears the vector to its default initial state.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline void SparseVectorProxy<PT,VT>::clear() const
+{
+ using blaze::clear;
+
+ clear( (~*this).get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting an element of the represented sparse vector.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::invalid_argument Invalid compressed vector access index.
+//
+// This function sets the value of an element of the sparse vector. In case the sparse vector
+// already contains an element with index \a index its value is modified, else a new element
+// with the given \a value is inserted.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator
+ SparseVectorProxy<PT,VT>::set( size_t index, const ElementType& value ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().set( index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting an element into the represented sparse vector.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid access to restricted element.
+// \exception std::invalid_argument Invalid compressed vector access index.
+//
+// This function inserts a new element into the sparse vector. However, duplicate elements are
+// not allowed. In case the sparse vector already contains an element with index \a index, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator
+ SparseVectorProxy<PT,VT>::insert( size_t index, const ElementType& value ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().insert( index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Appending an element to the represented sparse vector.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function provides a very efficient way to fill a compressed vector with elements. It
+// appends a new element to the end of the compressed vector without any memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the compressed vector
+// - the current number of non-zero elements must be smaller than the capacity of the vector
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline void SparseVectorProxy<PT,VT>::append( size_t index, const ElementType& value, bool check ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().append( index, value, check );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing an element from the sparse vector.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function erases an element from the sparse vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline void SparseVectorProxy<PT,VT>::erase( size_t index ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().erase( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing an element from the sparse vector.
+//
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function erases an element from the sparse vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator SparseVectorProxy<PT,VT>::erase( Iterator pos ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().erase( pos );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing a range of elements from the compressed vector.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function erases a range of elements from the sparse vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator
+ SparseVectorProxy<PT,VT>::erase( Iterator first, Iterator last ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ return (~*this).get().erase( first, last );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the represented vector.
+//
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function changes the size of the vector. Depending on the type of the vector, during this
+// operation new dynamic memory may be allocated in case the capacity of the vector is too small.
+// Note that this function may invalidate all existing views (subvectors, ...) on the vector if
+// it is used to shrink the vector. Additionally, the resize() operation potentially
+// changes all vector elements. In order to preserve the old vector values, the \a preserve flag
+// can be set to \a true.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline void SparseVectorProxy<PT,VT>::resize( size_t n, bool preserve ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().resize( n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the represented vector.
+//
+// \param n The new minimum capacity of the vector.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+//
+// This function increases the capacity of the compressed vector to at least \a n elements. The
+// current values of the vector elements are preserved.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline void SparseVectorProxy<PT,VT>::reserve( size_t n ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().reserve( n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the sparse vector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the vector scaling.
+// \return void
+// \exception std::invalid_argument Invalid access to restricted element.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+template< typename Other > // Data type of the scalar value
+inline void SparseVectorProxy<PT,VT>::scale( const Other& scalar ) const
+{
+ if( (~*this).isRestricted() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" );
+ }
+
+ (~*this).get().scale( scalar );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Searches for a specific vector element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// vector. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the compressed vector (the end() iterator) is returned. Note
+// that the returned compressed vector iterator is subject to invalidation due to inserting
+// operations via the subscript operator or the insert() function!
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator
+ SparseVectorProxy<PT,VT>::find( size_t index ) const
+{
+ return (~*this).get().find( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed vector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator
+ SparseVectorProxy<PT,VT>::lowerBound( size_t index ) const
+{
+ return (~*this).get().lowerBound( index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the lowerBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed vector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+inline typename SparseVectorProxy<PT,VT>::Iterator
+ SparseVectorProxy<PT,VT>::upperBound( size_t index ) const
+{
+ return (~*this).get().upperBound( index );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SparseVectorProxy global functions */
+//@{
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE typename SparseVectorProxy<PT,VT>::Iterator
+ begin( const SparseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE typename SparseVectorProxy<PT,VT>::ConstIterator
+ cbegin( const SparseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE typename SparseVectorProxy<PT,VT>::Iterator
+ end( const SparseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE typename SparseVectorProxy<PT,VT>::ConstIterator
+ cend( const SparseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE size_t size( const SparseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE size_t capacity( const SparseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE void resize( const SparseVectorProxy<PT,VT>& proxy, size_t n, bool preserve=true );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE void reset( const SparseVectorProxy<PT,VT>& proxy );
+
+template< typename PT, typename VT >
+BLAZE_ALWAYS_INLINE void clear( const SparseVectorProxy<PT,VT>& proxy );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return Iterator to the first element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE typename SparseVectorProxy<PT,VT>::Iterator
+ begin( const SparseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.begin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return Iterator to the first element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE typename SparseVectorProxy<PT,VT>::ConstIterator
+ cbegin( const SparseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.cbegin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return Iterator just past the last element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE typename SparseVectorProxy<PT,VT>::Iterator
+ end( const SparseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.end();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return Iterator just past the last element of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE typename SparseVectorProxy<PT,VT>::ConstIterator
+ cend( const SparseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.cend();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The size of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE size_t size( const SparseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The capacity of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE size_t capacity( const SparseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return The number of non-zero elements in the vector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the vector.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseVectorProxy<PT,VT>& proxy )
+{
+ return proxy.nonZeros();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the represented vector.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \param n The new size of the vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the represented vector to the specified \a size.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE void resize( const SparseVectorProxy<PT,VT>& proxy, size_t n, bool preserve )
+{
+ proxy.resize( n, preserve );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets all elements of the vector to the default initial values.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE void reset( const SparseVectorProxy<PT,VT>& proxy )
+{
+ proxy.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup math
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the vector to its default initial state.
+*/
+template< typename PT // Type of the proxy
+ , typename VT > // Type of the sparse vector
+BLAZE_ALWAYS_INLINE void clear( const SparseVectorProxy<PT,VT>& proxy )
+{
+ proxy.clear();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/serialization/MatrixSerializer.h b/src/cpu/blaze/math/serialization/MatrixSerializer.h
new file mode 100644
index 00000000..cdea06b5
--- /dev/null
+++ b/src/cpu/blaze/math/serialization/MatrixSerializer.h
@@ -0,0 +1,1298 @@
+//=================================================================================================
+/*!
+// \file blaze/math/serialization/MatrixSerializer.h
+// \brief Serialization of dense and sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SERIALIZATION_MATRIXSERIALIZER_H_
+#define _BLAZE_MATH_SERIALIZATION_MATRIXSERIALIZER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/dense/DynamicMatrix.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/math/serialization/TypeValueMapping.h>
+#include <blaze/math/sparse/CompressedMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Serializer for dense and sparse matrices.
+// \ingroup math_serialization
+//
+// The MatrixSerializer implements the necessary logic to serialize dense and sparse matrices,
+// i.e. to convert them into a portable, binary representation. The following example demonstrates
+// the (de-)serialization process of matrices:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Serialization of both matrices
+ {
+ blaze::StaticMatrix<double,3UL,5UL,rowMajor> D;
+ blaze::CompressedMatrix<int,columnMajor> S;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "matrices.blaze"
+ blaze::Archive<std::ofstream> archive( "matrices.blaze" );
+
+ // Serialization of both matrices into the same archive. Note that D lies before S!
+ archive << D << S;
+ }
+
+ // Reconstitution of both matrices
+ {
+ blaze::DynamicMatrix<double,rowMajor> D1;
+ blaze::DynamicMatrix<int,rowMajor> D2;
+
+ // Creating an archive that reads from the file "matrices.blaze"
+ blaze::Archive<std::ofstream> archive( "matrices.blaze" );
+
+ // Reconstituting the former D matrix into D1. Note that it is possible to reconstitute
+ // the matrix into a differrent kind of matrix (StaticMatrix -> DynamicMatrix), but that
+ // the type of elements has to be the same.
+ archive >> D1;
+
+ // Reconstituting the former S matrix into D2. Note that is is even possible to reconstitute
+ // a sparse matrix as a dense matrix (also the reverse is possible) and that a column-major
+ // matrix can be reconstituted as row-major matrix (and vice versa). Note however that also
+ // in this case the type of elements is the same!
+ archive >> D2
+ }
+ \endcode
+
+// Note that it is even possible to (de-)serialize matrices with vector or matrix elements:
+
+ \code
+ // Serialization
+ {
+ blaze::CompressedMatrix< blaze::DynamicMatrix< blaze::complex<double> > > mat;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "matrix.blaze"
+ blaze::Archive<std::ofstream> archive( "matrix.blaze" );
+
+ // Serialization of the matrix into the archive
+ archive << mat;
+ }
+
+ // Deserialization
+ {
+ blaze::CompressedMatrix< blaze::DynamicMatrix< blaze::complex<double> > > mat;
+
+ // Creating an archive that reads from the file "matrix.blaze"
+ blaze::Archive<std::ofstream> archive( "matrix.blaze" );
+
+ // Reconstitution of the matrix from the archive
+ archive >> mat;
+ }
+ \endcode
+
+// As the examples demonstrates, the matrix serialization offers an enormous flexibility. However,
+// several actions result in errors:
+//
+// - matrices cannot be reconstituted as vectors (and vice versa)
+// - the element type of the serialized and reconstituted matrix must match, which means
+// that on the source and destination platform the general type (signed/unsigned integral
+// or floating point) and the size of the type must be exactly the same
+// - when reconstituting a StaticMatrix, the number of rows and columns must match those of
+// the serialized matrix
+//
+// In case an error is encountered during (de-)serialization, a \a std::runtime_exception is
+// thrown.
+*/
+class MatrixSerializer
+{
+ private:
+ //**Private class MatrixValueMappingHelper******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary helper class for the MatrixValueMapping class template.
+ //
+ // The MatrixValueMapping class template is an auxiliary class for the MatrixSerializer. It
+ // maps a matrix type into an integral representation. For the mapping, the following bit
+ // mapping is used:
+
+ \code
+ 0x01 - Vector/Matrix flag
+ 0x02 - Dense/Sparse flag
+ 0x04 - Row-/Column-major flag
+ \endcode
+ */
+ template< bool IsDenseMatrix, bool IsRowMajorMatrix >
+ struct MatrixValueMappingHelper;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Private class MatrixValueMapping************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Serialization of the type of a matrix.
+ //
+ // This class template converts the given matrix type into an integral representation suited
+ // for serialization. Depending on the given matrix type, the \a value member enumeration is
+ // set to the according integral representation.
+ */
+ template< typename T >
+ struct MatrixValueMapping
+ {
+ enum { value = MatrixValueMappingHelper< IsDenseMatrix<T>::value, IsRowMajorMatrix<T>::value >::value };
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE( T );
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline MatrixSerializer();
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ // No explicitly declared copy assignment operator.
+ //**********************************************************************************************
+
+ //**Serialization functions*********************************************************************
+ /*!\name Serialization functions */
+ //@{
+ template< typename Archive, typename MT, bool SO >
+ void serialize( Archive& archive, const Matrix<MT,SO>& mat );
+ //@}
+ //**********************************************************************************************
+
+ //**Deserialization functions*******************************************************************
+ /*!\name Deserialization functions */
+ //@{
+ template< typename Archive, typename MT, bool SO >
+ void deserialize( Archive& archive, Matrix<MT,SO>& mat );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Serialization functions*********************************************************************
+ /*!\name Serialization functions */
+ //@{
+ template< typename Archive, typename MT >
+ void serializeHeader( Archive& archive, const MT& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ void serializeMatrix( Archive& archive, const DenseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ void serializeMatrix( Archive& archive, const SparseMatrix<MT,SO>& mat );
+ //@}
+ //**********************************************************************************************
+
+ //**Deserialization functions*******************************************************************
+ /*!\name Deserialization functions */
+ //@{
+ template< typename Archive, typename MT >
+ void deserializeHeader( Archive& archive, const MT& mat );
+
+ template< typename MT, bool SO >
+ DisableIf_< IsResizable<MT> > prepareMatrix( DenseMatrix<MT,SO>& mat );
+
+ template< typename MT, bool SO >
+ DisableIf_< IsResizable<MT> > prepareMatrix( SparseMatrix<MT,SO>& mat );
+
+ template< typename MT >
+ EnableIf_< IsResizable<MT> > prepareMatrix( MT& mat );
+
+ template< typename Archive, typename MT >
+ void deserializeMatrix( Archive& archive, MT& mat );
+
+ template< typename Archive, typename MT >
+ EnableIfTrue_< MT::simdEnabled >
+ deserializeDenseRowMatrix( Archive& archive, DenseMatrix<MT,rowMajor>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ void deserializeDenseRowMatrix( Archive& archive, DenseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ DisableIf_< IsNumeric< ElementType_<MT> > >
+ deserializeDenseRowMatrix( Archive& archive, SparseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ EnableIf_< IsNumeric< ElementType_<MT> > >
+ deserializeDenseRowMatrix( Archive& archive, SparseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT >
+ EnableIfTrue_< MT::simdEnabled>
+ deserializeDenseColumnMatrix( Archive& archive, DenseMatrix<MT,columnMajor>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ void deserializeDenseColumnMatrix( Archive& archive, DenseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ DisableIf_< IsNumeric< ElementType_<MT> > >
+ deserializeDenseColumnMatrix( Archive& archive, SparseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ EnableIf_< IsNumeric< ElementType_<MT> > >
+ deserializeDenseColumnMatrix( Archive& archive, SparseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ void deserializeSparseRowMatrix( Archive& archive, DenseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT >
+ void deserializeSparseRowMatrix( Archive& archive, SparseMatrix<MT,rowMajor>& mat );
+
+ template< typename Archive, typename MT >
+ void deserializeSparseRowMatrix( Archive& archive, SparseMatrix<MT,columnMajor>& mat );
+
+ template< typename Archive, typename MT, bool SO >
+ void deserializeSparseColumnMatrix( Archive& archive, DenseMatrix<MT,SO>& mat );
+
+ template< typename Archive, typename MT >
+ void deserializeSparseColumnMatrix( Archive& archive, SparseMatrix<MT,rowMajor>& mat );
+
+ template< typename Archive, typename MT >
+ void deserializeSparseColumnMatrix( Archive& archive, SparseMatrix<MT,columnMajor>& mat );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ uint8_t version_; //!< The version of the archive.
+ uint8_t type_; //!< The type of the matrix.
+ uint8_t elementType_; //!< The type of an element.
+ uint8_t elementSize_; //!< The size in bytes of a single element of the matrix.
+ uint64_t rows_; //!< The number of rows of the matrix.
+ uint64_t columns_; //!< The number of columns of the matrix.
+ uint64_t number_; //!< The total number of elements contained in the matrix.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor of the MatrixSerializer class.
+*/
+MatrixSerializer::MatrixSerializer()
+ : version_ ( 0U ) // The version of the archive
+ , type_ ( 0U ) // The type of the matrix
+ , elementType_( 0U ) // The type of an element
+ , elementSize_( 0U ) // The size in bytes of a single element of the matrix
+ , rows_ ( 0UL ) // The number of rows of the matrix
+ , columns_ ( 0UL ) // The number of columns of the matrix
+ , number_ ( 0UL ) // The total number of elements contained in the matrix
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SERIALIZATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Serializes the given matrix and writes it to the archive.
+//
+// \param archive The archive to be written.
+// \param mat The matrix to be serialized.
+// \return void
+// \exception std::runtime_error Error during serialization.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void MatrixSerializer::serialize( Archive& archive, const Matrix<MT,SO>& mat )
+{
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Faulty archive detected" );
+ }
+
+ serializeHeader( archive, ~mat );
+ serializeMatrix( archive, ~mat );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Serializes all meta information about the given matrix.
+//
+// \param archive The archive to be written.
+// \param mat The matrix to be serialized.
+// \return void
+// \exception std::runtime_error File header could not be serialized.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+void MatrixSerializer::serializeHeader( Archive& archive, const MT& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ archive << uint8_t ( 1U );
+ archive << uint8_t ( MatrixValueMapping<MT>::value );
+ archive << uint8_t ( TypeValueMapping<ET>::value );
+ archive << uint8_t ( sizeof( ET ) );
+ archive << uint64_t( mat.rows() );
+ archive << uint64_t( mat.columns() );
+ archive << uint64_t( ( IsDenseMatrix<MT>::value ) ? ( mat.rows()*mat.columns() ) : ( mat.nonZeros() ) );
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "File header could not be serialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Serializes the elements of a dense matrix.
+//
+// \param archive The archive to be written.
+// \param mat The matrix to be serialized.
+// \return void
+// \exception std::runtime_error Dense matrix could not be serialized.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void MatrixSerializer::serializeMatrix( Archive& archive, const DenseMatrix<MT,SO>& mat )
+{
+ if( IsRowMajorMatrix<MT>::value ) {
+ for( size_t i=0UL; i<(~mat).rows(); ++i ) {
+ for( size_t j=0UL; j<(~mat).columns(); ++j ) {
+ archive << (~mat)(i,j);
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<(~mat).columns(); ++j ) {
+ for( size_t i=0UL; i<(~mat).rows(); ++i ) {
+ archive << (~mat)(i,j);
+ }
+ }
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be serialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Serializes the elements of a sparse matrix.
+//
+// \param archive The archive to be written.
+// \param mat The matrix to be serialized.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be serialized.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void MatrixSerializer::serializeMatrix( Archive& archive, const SparseMatrix<MT,SO>& mat )
+{
+ typedef ConstIterator_<MT> ConstIterator;
+
+ if( IsRowMajorMatrix<MT>::value ) {
+ for( size_t i=0UL; i<(~mat).rows(); ++i ) {
+ archive << uint64_t( (~mat).nonZeros( i ) );
+ for( ConstIterator element=(~mat).begin(i); element!=(~mat).end(i); ++element ) {
+ archive << element->index() << element->value();
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<(~mat).columns(); ++j ) {
+ archive << uint64_t( (~mat).nonZeros( j ) );
+ for( ConstIterator element=(~mat).begin(j); element!=(~mat).end(j); ++element ) {
+ archive << element->index() << element->value();
+ }
+ }
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be serialized" );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESERIALIZATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Deserializes a matrix from the given archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be deserialized.
+// \return void
+// \exception std::runtime_error Error during deserialization.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void MatrixSerializer::deserialize( Archive& archive, Matrix<MT,SO>& mat )
+{
+ if( !archive ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Faulty archive detected" );
+ }
+
+ deserializeHeader( archive, ~mat );
+ prepareMatrix( ~mat );
+ deserializeMatrix( archive, ~mat );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes all meta information about the given matrix.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be deserialized.
+// \return void
+// \exception std::runtime_error Error during deserialization.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+void MatrixSerializer::deserializeHeader( Archive& archive, const MT& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ if( !( archive >> version_ >> type_ >> elementType_ >> elementSize_ >> rows_ >> columns_ >> number_ ) ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Corrupt archive detected" );
+ }
+ else if( version_ != 1UL ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid version detected" );
+ }
+ else if( ( type_ & 1U ) != 1U || ( type_ & (~7U) ) != 0U ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid matrix type detected" );
+ }
+ else if( elementType_ != TypeValueMapping<ET>::value ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid element type detected" );
+ }
+ else if( elementSize_ != sizeof( ET ) ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid element size detected" );
+ }
+ else if( !IsResizable<MT>::value && ( rows_ != mat.rows() || columns_ != mat.columns() ) ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid matrix size detected" );
+ }
+ else if( number_ > rows_*columns_ ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid number of elements detected" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Prepares the given non-resizable dense matrix for the deserialization process.
+//
+// \param mat The dense matrix to be prepared.
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+DisableIf_< IsResizable<MT> > MatrixSerializer::prepareMatrix( DenseMatrix<MT,SO>& mat )
+{
+ reset( ~mat );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Prepares the given non-resizable sparse matrix for the deserialization process.
+//
+// \param mat The sparse matrix to be prepared.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+DisableIf_< IsResizable<MT> > MatrixSerializer::prepareMatrix( SparseMatrix<MT,SO>& mat )
+{
+ (~mat).reserve( number_ );
+ reset( ~mat );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Prepares the given resizable matrix for the deserialization process.
+//
+// \param mat The matrix to be prepared.
+// \return void
+*/
+template< typename MT > // Type of the matrix
+EnableIf_< IsResizable<MT> > MatrixSerializer::prepareMatrix( MT& mat )
+{
+ mat.resize ( rows_, columns_, false );
+ mat.reserve( number_ );
+ reset( mat );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Error during deserialization.
+//
+// This function deserializes the contents of the matrix from the archive and reconstitutes the
+// given matrix.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+void MatrixSerializer::deserializeMatrix( Archive& archive, MT& mat )
+{
+ if( type_ == 1U ) {
+ deserializeDenseRowMatrix( archive, ~mat );
+ }
+ else if( type_ == 5UL ) {
+ deserializeDenseColumnMatrix( archive, ~mat );
+ }
+ else if( type_ == 3UL ) {
+ deserializeSparseRowMatrix( archive, ~mat );
+ }
+ else if( type_ == 7UL ) {
+ deserializeSparseColumnMatrix( archive, ~mat );
+ }
+ else {
+ BLAZE_INTERNAL_ASSERT( false, "Undefined type flag" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a row-major dense matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The dense matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense matrix could not be deserialized.
+//
+// This function deserializes a row-major dense matrix from the archive and reconstitutes
+// the given row-major dense matrix. In case any error is detected during the deserialization
+// process, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+EnableIfTrue_< MT::simdEnabled >
+ MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, DenseMatrix<MT,rowMajor>& mat )
+{
+ if( columns_ == 0UL ) return;
+
+ for( size_t i=0UL; i<rows_; ++i ) {
+ archive.read( &(~mat)(i,0), columns_ );
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a row-major dense matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The dense matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense matrix could not be deserialized.
+//
+// This function deserializes a row-major dense matrix from the archive and reconstitutes
+// the given dense matrix. In case any error is detected during the deserialization process,
+// a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, DenseMatrix<MT,SO>& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ ET value = ET();
+
+ for( size_t i=0UL; i<rows_; ++i ) {
+ size_t j( 0UL );
+ while( ( j != columns_ ) && ( archive >> value ) ) {
+ (~mat)(i,j) = value;
+ ++j;
+ }
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a row-major dense matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The dense matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be deserialized.
+//
+// This function deserializes a row-major dense matrix from the archive and reconstitutes
+// the given sparse matrix. In case any error is detected during the deserialization
+// process, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+EnableIf_< IsNumeric< ElementType_<MT> > >
+ MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, SparseMatrix<MT,SO>& mat )
+{
+ DynamicMatrix< ElementType_<MT>, rowMajor > tmp( rows_, columns_ );
+ deserializeDenseRowMatrix( archive, tmp );
+ (~mat) = tmp;
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a row-major dense matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The dense matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be deserialized.
+//
+// This function deserializes a row-major dense matrix from the archive and reconstitutes
+// the given sparse matrix. In case any error is detected during the deserialization
+// process, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+DisableIf_< IsNumeric< ElementType_<MT> > >
+ MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, SparseMatrix<MT,SO>& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ ET value = ET();
+
+ const size_t dim1( ( SO == rowMajor )?( rows_ ):( columns_ ) );
+ const size_t dim2( ( SO != rowMajor )?( rows_ ):( columns_ ) );
+
+ for( size_t i=0UL; i<dim1; ++i ) {
+ (~mat).reserve( i, dim2 );
+ }
+
+ for( size_t i=0UL; i<rows_; ++i ) {
+ size_t j( 0UL );
+ while( ( j != columns_ ) && ( archive >> value ) ) {
+ (~mat).append( i, j, value, false );
+ ++j;
+ }
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a column-major dense matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The dense matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense matrix could not be deserialized.
+//
+// This function deserializes a column-major dense matrix from the archive and reconstitutes
+// the given column-major dense matrix. In case any error is detected during the deserialization
+// process, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+EnableIfTrue_< MT::simdEnabled >
+ MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, DenseMatrix<MT,columnMajor>& mat )
+{
+ if( rows_ == 0UL ) return;
+
+ for( size_t j=0UL; j<columns_; ++j ) {
+ archive.read( &(~mat)(0,j), rows_ );
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a column-major dense matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The dense matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense matrix could not be deserialized.
+//
+// This function deserializes a column-major dense matrix from the archive and reconstitutes
+// the given dense matrix. In case any error is detected during the deserialization process,
+// a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, DenseMatrix<MT,SO>& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ ET value = ET();
+
+ for( size_t j=0UL; j<columns_; ++j ) {
+ size_t i( 0UL );
+ while( ( i != rows_ ) && ( archive >> value ) ) {
+ (~mat)(i,j) = value;
+ ++i;
+ }
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a column-major dense matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The sparse matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be deserialized.
+//
+// This function deserializes a column-major dense matrix from the archive and reconstitutes
+// the given sparse matrix. In case any error is detected during the deserialization process,
+// a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+EnableIf_< IsNumeric< ElementType_<MT> > >
+ MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, SparseMatrix<MT,SO>& mat )
+{
+ DynamicMatrix< ElementType_<MT>, columnMajor > tmp( rows_, columns_ );
+ deserializeDenseColumnMatrix( archive, tmp );
+ (~mat) = tmp;
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a column-major dense matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The sparse matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be deserialized.
+//
+// This function deserializes a column-major dense matrix from the archive and reconstitutes
+// the given sparse matrix. In case any error is detected during the deserialization process,
+// a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+DisableIf_< IsNumeric< ElementType_<MT> > >
+ MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, SparseMatrix<MT,SO>& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ ET value = ET();
+
+ const size_t dim1( ( SO == rowMajor )?( rows_ ):( columns_ ) );
+ const size_t dim2( ( SO != rowMajor )?( rows_ ):( columns_ ) );
+
+ for( size_t i=0UL; i<dim1; ++i ) {
+ (~mat).reserve( i, dim2 );
+ }
+
+ for( size_t j=0UL; j<columns_; ++j ) {
+ size_t i( 0UL );
+ while( ( i != rows_ ) && ( archive >> value ) ) {
+ (~mat).append( i, j, value, false );
+ ++i;
+ }
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a row-major sparse matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense matrix could not be deserialized.
+//
+// This function deserializes a row-major sparse matrix from the archive and reconstitutes
+// the given dense matrix. In case any error is detected during the deserialization process,
+// a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void MatrixSerializer::deserializeSparseRowMatrix( Archive& archive, DenseMatrix<MT,SO>& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ uint64_t number( 0UL );
+ size_t index ( 0UL );
+ ET value = ET();
+
+ for( size_t i=0UL; i<rows_; ++i ) {
+ archive >> number;
+ size_t j( 0UL );
+ while( ( j != number ) && ( archive >> index >> value ) ) {
+ (~mat)(i,index) = value;
+ ++j;
+ }
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a row-major sparse matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be deserialized.
+//
+// This function deserializes a row-major sparse matrix from the archive and reconstitutes
+// the given row-major sparse matrix. In case any error is detected during the deserialization
+// process, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+void MatrixSerializer::deserializeSparseRowMatrix( Archive& archive, SparseMatrix<MT,rowMajor>& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ uint64_t number( 0UL );
+ size_t index ( 0UL );
+ ET value = ET();
+
+ for( size_t i=0UL; i<rows_; ++i )
+ {
+ archive >> number;
+
+ size_t j( 0UL );
+ while( ( j != number ) && ( archive >> index >> value ) ) {
+ (~mat).append( i, index, value, false );
+ ++j;
+ }
+
+ (~mat).finalize( i );
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a row-major sparse matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be deserialized.
+//
+// This function deserializes a row-major sparse matrix from the archive and reconstitutes
+// the given column-major sparse matrix. In case any error is detected during the deserialization
+// process, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+void MatrixSerializer::deserializeSparseRowMatrix( Archive& archive, SparseMatrix<MT,columnMajor>& mat )
+{
+ CompressedMatrix< ElementType_<MT>, rowMajor > tmp( rows_, columns_, number_ );
+ deserializeSparseRowMatrix( archive, tmp );
+ (~mat) = tmp;
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a column-major sparse matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense matrix could not be deserialized.
+//
+// This function deserializes a column-major sparse matrix from the archive and reconstitutes
+// the given dense matrix. In case any error is detected during the deserialization process,
+// a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void MatrixSerializer::deserializeSparseColumnMatrix( Archive& archive, DenseMatrix<MT,SO>& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ uint64_t number( 0UL );
+ size_t index ( 0UL );
+ ET value = ET();
+
+ for( size_t j=0UL; j<columns_; ++j ) {
+ archive >> number;
+ size_t i( 0UL );
+ while( ( i != number ) && ( archive >> index >> value ) ) {
+ (~mat)(index,j) = value;
+ ++i;
+ }
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a column-major sparse matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be deserialized.
+//
+// This function deserializes a column-major sparse matrix from the archive and reconstitutes
+// the given row-major sparse matrix. In case any error is detected during the deserialization
+// process, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+void MatrixSerializer::deserializeSparseColumnMatrix( Archive& archive, SparseMatrix<MT,rowMajor>& mat )
+{
+ CompressedMatrix< ElementType_<MT>, columnMajor > tmp( rows_, columns_, number_ );
+ deserializeSparseColumnMatrix( archive, tmp );
+ (~mat) = tmp;
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a column-major sparse matrix from the archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse matrix could not be deserialized.
+//
+// This function deserializes a column-major sparse matrix from the archive and reconstitutes
+// the given column-major sparse matrix. In case any error is detected during the deserialization
+// process, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT > // Type of the matrix
+void MatrixSerializer::deserializeSparseColumnMatrix( Archive& archive, SparseMatrix<MT,columnMajor>& mat )
+{
+ typedef ElementType_<MT> ET;
+
+ uint64_t number( 0UL );
+ size_t index ( 0UL );
+ ET value = ET();
+
+ for( size_t j=0UL; j<columns_; ++j )
+ {
+ archive >> number;
+
+ size_t i( 0UL );
+ while( ( i != number ) && ( archive >> index >> value ) ) {
+ (~mat).append( index, j, value, false );
+ ++i;
+ }
+
+ (~mat).finalize( j );
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse matrix could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATRIXVALUEMAPPINGHELPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the MatrixValueMappingHelper class template for row-major dense matrices.
+*/
+template<>
+struct MatrixSerializer::MatrixValueMappingHelper<true,true>
+{
+ enum { value = 1 };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the MatrixValueMappingHelper class template for column-major dense matrices.
+*/
+template<>
+struct MatrixSerializer::MatrixValueMappingHelper<true,false>
+{
+ enum { value = 5 };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the MatrixValueMappingHelper class template for row-major sparse matrices.
+*/
+template<>
+struct MatrixSerializer::MatrixValueMappingHelper<false,true>
+{
+ enum { value = 3 };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the MatrixValueMappingHelper class template for column-major sparse matrices.
+*/
+template<>
+struct MatrixSerializer::MatrixValueMappingHelper<false,false>
+{
+ enum { value = 7 };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Serializes the given matrix and writes it to the archive.
+//
+// \param archive The archive to be written.
+// \param mat The matrix to be serialized.
+// \return void
+// \exception std::runtime_error Matrix could not be serialized.
+//
+// The serialize() function converts the given matrix into a portable, binary representation.
+// The following example demonstrates the (de-)serialization process of matrices:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Serialization of both matrices
+ {
+ blaze::StaticMatrix<double,3UL,5UL,rowMajor> D;
+ blaze::CompressedMatrix<int,columnMajor> S;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "matrices.blaze"
+ blaze::Archive<std::ofstream> archive( "matrices.blaze" );
+
+ // Serialization of both matrices into the same archive. Note that D lies before S!
+ archive << D << S;
+ }
+
+ // Reconstitution of both matrices
+ {
+ blaze::DynamicMatrix<double,rowMajor> D1;
+ blaze::DynamicMatrix<int,rowMajor> D2;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that reads from the file "matrices.blaze"
+ blaze::Archive<std::ofstream> archive( "matrices.blaze" );
+
+ // Reconstituting the former D matrix into D1. Note that it is possible to reconstitute
+ // the matrix into a differrent kind of matrix (StaticMatrix -> DynamicMatrix), but that
+ // the type of elements has to be the same.
+ archive >> D1;
+
+ // Reconstituting the former S matrix into D2. Note that is is even possible to reconstitute
+ // a sparse matrix as a dense matrix (also the reverse is possible) and that a column-major
+ // matrix can be reconstituted as row-major matrix (and vice versa). Note however that also
+ // in this case the type of elements is the same!
+ archive >> D2
+ }
+ \endcode
+
+// As the example demonstrates, the matrix serialization offers an enormous flexibility. However,
+// several actions result in errors:
+//
+// - matrices cannot be reconstituted as vectors (and vice versa)
+// - the element type of the serialized and reconstituted matrix must match, which means
+// that on the source and destination platform the general type (signed/unsigned integral
+// or floating point) and the size of the type must be exactly the same
+// - when reconstituting a StaticMatrix, the number of rows and columns must match those of
+// the serialized matrix
+//
+// In case an error is encountered during (de-)serialization, a \a std::runtime_exception is
+// thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void serialize( Archive& archive, const Matrix<MT,SO>& mat )
+{
+ MatrixSerializer().serialize( archive, ~mat );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a matrix from the given archive.
+//
+// \param archive The archive to be read from.
+// \param mat The matrix to be deserialized.
+// \return void
+// \exception std::runtime_error Matrix could not be deserialized.
+//
+// The deserialize() function converts the portable, binary representation contained in the
+// given archive into the given matrix type. For a detailed example that demonstrates the
+// (de-)serialization process of matrices, see the serialize() function.
+*/
+template< typename Archive // Type of the archive
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+void deserialize( Archive& archive, Matrix<MT,SO>& mat )
+{
+ MatrixSerializer().deserialize( archive, ~mat );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/serialization/Serialization.h b/src/cpu/blaze/math/serialization/Serialization.h
new file mode 100644
index 00000000..bcaaf9c9
--- /dev/null
+++ b/src/cpu/blaze/math/serialization/Serialization.h
@@ -0,0 +1,126 @@
+//=================================================================================================
+/*!
+// \file blaze/math/serialization/Serialization.h
+// \brief Mathematical serialization module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SERIALIZATION_SERIALIZATION_H_
+#define _BLAZE_MATH_SERIALIZATION_SERIALIZATION_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup math_serialization Serialization
+// \ingroup math
+//
+// The math serialization module provides the functionality to create platform independent,
+// portable, binary representations of vectors and matrices. The resulting data structures
+// can be used to reconstitute the vectors and matrices in a different context, on another
+// platform, etc.
+//
+// The following example demonstrates the functionality of this module by means of vectors:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ // Serialization of both vectors
+ {
+ blaze::StaticVector<double,5UL,rowVector> d;
+ blaze::CompressedVector<int,columnVector> s;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "vectors.blaze"
+ blaze::Archive<std::ofstream> archive( "vectors.blaze" );
+
+ // Serialization of both vectors into the same archive. Note that d lies before s!
+ archive << d << s;
+ }
+
+ // Reconstitution of both vectors
+ {
+ blaze::DynamicVector<double,rowVector> d1;
+ blaze::DynamicVector<int,rowVector> d2;
+
+ // Creating an archive that reads from the file "vectors.blaze"
+ blaze::Archive<std::ofstream> archive( "vectors.blaze" );
+
+ // Reconstituting the former d vector into d1. Note that it is possible to reconstitute
+ // the vector into a differrent kind of vector (StaticVector -> DynamicVector), but that
+ // the type of elements has to be the same.
+ archive >> d1;
+
+ // Reconstituting the former s vector into d2. Note that is is even possible to reconstitute
+ // a sparse vector as a dense vector (also the reverse is possible) and that a column vector
+ // can be reconstituted as row vector (and vice versa). Note however that also in this case
+ // the type of elements is the same!
+ archive >> d2
+ }
+ \endcode
+
+// The (de-)serialization of vectors is not restricted to vectors of built-in data type, but can
+// also be used for vectors with vector or matrix element type:
+
+ \code
+ // Serialization
+ {
+ blaze::CompressedVector< blaze::DynamicVector< blaze::complex<double> > > vec;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "vector.blaze"
+ blaze::Archive<std::ofstream> archive( "vector.blaze" );
+
+ // Serialization of the vector into the archive
+ archive << vec;
+ }
+
+ // Deserialization
+ {
+ blaze::CompressedVector< blaze::DynamicVector< blaze::complex<double> > > vec;
+
+ // Creating an archive that reads from the file "vector.blaze"
+ blaze::Archive<std::ofstream> archive( "vector.blaze" );
+
+ // Reconstitution of the vector from the archive
+ archive >> vec;
+ }
+ \endcode
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/serialization/TypeValueMapping.h b/src/cpu/blaze/math/serialization/TypeValueMapping.h
new file mode 100644
index 00000000..502c2a04
--- /dev/null
+++ b/src/cpu/blaze/math/serialization/TypeValueMapping.h
@@ -0,0 +1,180 @@
+//=================================================================================================
+/*!
+// \file blaze/math/serialization/TypeValueMapping.h
+// \brief Header file for the TypeValueMapping class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SERIALIZATION_TypeValueMapping_H_
+#define _BLAZE_MATH_SERIALIZATION_TypeValueMapping_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsSigned.h>
+#include <blaze/util/typetraits/IsUnsigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TypeValueMapping class template.
+// \ingroup math_serialization
+*/
+template< bool IsSignedIntegral, bool IsUnsignedIntegral, bool IsFloatingPoint, bool IsComplex >
+struct TypeValueMappingHelper;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TypeValueMappingHelper for compound data types.
+// \ingroup math_serialization
+*/
+template<>
+struct TypeValueMappingHelper<false,false,false,false>
+{
+ public:
+ //**********************************************************************************************
+ enum { value = 0 };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TypeValueMappingHelper for signed integral data types.
+// \ingroup math_serialization
+*/
+template<>
+struct TypeValueMappingHelper<true,false,false,false>
+{
+ public:
+ //**********************************************************************************************
+ enum { value = 1 };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TypeValueMappingHelper for unsigned integral data types.
+// \ingroup math_serialization
+*/
+template<>
+struct TypeValueMappingHelper<false,true,false,false>
+{
+ public:
+ //**********************************************************************************************
+ enum { value = 2 };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TypeValueMappingHelper for floating-point data types.
+// \ingroup math_serialization
+*/
+template<>
+struct TypeValueMappingHelper<false,false,true,false>
+{
+ public:
+ //**********************************************************************************************
+ enum { value = 3 };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TypeValueMappingHelper for complex data types.
+// \ingroup math_serialization
+*/
+template<>
+struct TypeValueMappingHelper<false,false,false,true>
+{
+ public:
+ //**********************************************************************************************
+ enum { value = 4 };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion from a data type to a serial representation.
+// \ingroup math_serialization
+//
+// This class template converts the given data type into an integral representation suited for
+// serialization. Depending on the given data type, the \a value member enumeration is set to
+// the according serial representation.
+*/
+template< typename T >
+struct TypeValueMapping
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum { value = TypeValueMappingHelper< IsIntegral<T>::value && IsSigned<T>::value
+ , IsIntegral<T>::value && IsUnsigned<T>::value
+ , IsFloatingPoint<T>::value
+ , IsComplex<T>::value
+ >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/serialization/VectorSerializer.h b/src/cpu/blaze/math/serialization/VectorSerializer.h
new file mode 100644
index 00000000..d66a2345
--- /dev/null
+++ b/src/cpu/blaze/math/serialization/VectorSerializer.h
@@ -0,0 +1,887 @@
+//=================================================================================================
+/*!
+// \file blaze/math/serialization/VectorSerializer.h
+// \brief Serialization of dense and sparse vectors
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SERIALIZATION_VECTORSERIALIZER_H_
+#define _BLAZE_MATH_SERIALIZATION_VECTORSERIALIZER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Vector.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/Vector.h>
+#include <blaze/math/serialization/TypeValueMapping.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Serializer for dense and sparse vectors.
+// \ingroup math_serialization
+//
+// The VectorSerializer implements the necessary logic to serialize dense and sparse vectors, i.e.
+// to convert them into a portable, binary representation. The following example demonstrates the
+// (de-)serialization process of vectors:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ // Serialization of both vectors
+ {
+ blaze::StaticVector<double,5UL,rowVector> d;
+ blaze::CompressedVector<int,columnVector> s;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "vectors.blaze"
+ blaze::Archive<std::ofstream> archive( "vectors.blaze" );
+
+ // Serialization of both vectors into the same archive. Note that d lies before s!
+ archive << d << s;
+ }
+
+ // Reconstitution of both vectors
+ {
+ blaze::DynamicVector<double,rowVector> d1;
+ blaze::DynamicVector<int,rowVector> d2;
+
+ // Creating an archive that reads from the file "vectors.blaze"
+ blaze::Archive<std::ofstream> archive( "vectors.blaze" );
+
+ // Reconstituting the former d vector into d1. Note that it is possible to reconstitute
+ // the vector into a differrent kind of vector (StaticVector -> DynamicVector), but that
+ // the type of elements has to be the same.
+ archive >> d1;
+
+ // Reconstituting the former s vector into d2. Note that is is even possible to reconstitute
+ // a sparse vector as a dense vector (also the reverse is possible) and that a column vector
+ // can be reconstituted as row vector (and vice versa). Note however that also in this case
+ // the type of elements is the same!
+ archive >> d2
+ }
+ \endcode
+
+// Note that it is even possible to (de-)serialize vectors with vector or matrix elements:
+
+ \code
+ // Serialization
+ {
+ blaze::CompressedVector< blaze::DynamicVector< blaze::complex<double> > > vec;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "vector.blaze"
+ blaze::Archive<std::ofstream> archive( "vector.blaze" );
+
+ // Serialization of the vector into the archive
+ archive << vec;
+ }
+
+ // Deserialization
+ {
+ blaze::CompressedVector< blaze::DynamicVector< blaze::complex<double> > > vec;
+
+ // Creating an archive that reads from the file "vector.blaze"
+ blaze::Archive<std::ofstream> archive( "vector.blaze" );
+
+ // Reconstitution of the vector from the archive
+ archive >> vec;
+ }
+ \endcode
+
+// As the examples demonstrates, the vector serialization offers an enormous flexibility. However,
+// several actions result in errors:
+//
+// - vectors cannot be reconstituted as matrices (and vice versa)
+// - the element type of the serialized and reconstituted vector must match, which means
+// that on the source and destination platform the general type (signed/unsigned integral
+// or floating point) and the size of the type must be exactly the same
+// - when reconstituting a StaticVector, its size must match the size of the serialized vector
+//
+// In case an error is encountered during (de-)serialization, a \a std::runtime_exception is
+// thrown.
+*/
+class VectorSerializer
+{
+ private:
+ //**Private class VectorValueMappingHelper******************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Auxiliary helper class for the VectorValueMapping class template.
+ //
+ // The VectorValueMapping class template is an auxiliary class for the VectorSerializer. It
+ // maps a vector type into an integral representation. For the mapping, the following bit
+ // mapping is used:
+
+ \code
+ 0x01 - Vector/Matrix flag
+ 0x02 - Dense/Sparse flag
+ 0x04 - Row-/Column-major flag
+ \endcode
+ */
+ template< bool IsDenseVector >
+ struct VectorValueMappingHelper;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Private class VectorValueMapping************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Serialization of the type of a vector.
+ //
+ // This class template converts the given vector type into an integral representation suited
+ // for serialization. Depending on the given vector type, the \a value member enumeration is
+ // set to the according integral representation.
+ */
+ template< typename T >
+ struct VectorValueMapping
+ {
+ enum { value = VectorValueMappingHelper< IsDenseVector<T>::value >::value };
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_TYPE( T );
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline VectorSerializer();
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ // No explicitly declared copy assignment operator.
+ //**********************************************************************************************
+
+ //**Serialization functions*********************************************************************
+ /*!\name Serialization functions */
+ //@{
+ template< typename Archive, typename VT, bool TF >
+ void serialize( Archive& archive, const Vector<VT,TF>& vec );
+ //@}
+ //**********************************************************************************************
+
+ //**Deserialization functions*********************************************************************
+ /*!\name Deserialization functions */
+ //@{
+ template< typename Archive, typename VT, bool TF >
+ void deserialize( Archive& archive, Vector<VT,TF>& vec );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Serialization functions*********************************************************************
+ /*!\name Serialization functions */
+ //@{
+ template< typename Archive, typename VT >
+ void serializeHeader( Archive& archive, const VT& vec );
+
+ template< typename Archive, typename VT, bool TF >
+ void serializeVector( Archive& archive, const DenseVector<VT,TF>& vec );
+
+ template< typename Archive, typename VT, bool TF >
+ void serializeVector( Archive& archive, const SparseVector<VT,TF>& vec );
+ //@}
+ //**********************************************************************************************
+
+ //**Deserialization functions*******************************************************************
+ /*!\name Deserialization functions */
+ //@{
+ template< typename Archive, typename VT >
+ void deserializeHeader( Archive& archive, const VT& vec );
+
+ template< typename VT, bool TF >
+ DisableIf_< IsResizable<VT> > prepareVector( DenseVector<VT,TF>& vec );
+
+ template< typename VT, bool TF >
+ DisableIf_< IsResizable<VT> > prepareVector( SparseVector<VT,TF>& vec );
+
+ template< typename VT >
+ EnableIf_< IsResizable<VT> > prepareVector( VT& vec );
+
+ template< typename Archive, typename VT >
+ void deserializeVector( Archive& archive, VT& vec );
+
+ template< typename Archive, typename VT, bool TF >
+ typename DisableIfTrue< VT::simdEnabled >::Type
+ deserializeDenseVector( Archive& archive, DenseVector<VT,TF>& vec );
+
+ template< typename Archive, typename VT, bool TF >
+ EnableIfTrue_< VT::simdEnabled >
+ deserializeDenseVector( Archive& archive, DenseVector<VT,TF>& vec );
+
+ template< typename Archive, typename VT, bool TF >
+ void deserializeDenseVector( Archive& archive, SparseVector<VT,TF>& vec );
+
+ template< typename Archive, typename VT, bool TF >
+ void deserializeSparseVector( Archive& archive, DenseVector<VT,TF>& vec );
+
+ template< typename Archive, typename VT, bool TF >
+ void deserializeSparseVector( Archive& archive, SparseVector<VT,TF>& vec );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ uint8_t version_; //!< The version of the archive.
+ uint8_t type_; //!< The type of the vector.
+ uint8_t elementType_; //!< The type of an element.
+ uint8_t elementSize_; //!< The size in bytes of a single element of the vector.
+ uint64_t size_; //!< The size of the vector.
+ uint64_t number_; //!< The total number of elements contained in the vector.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor of the VectorSerializer class.
+*/
+VectorSerializer::VectorSerializer()
+ : version_ ( 0U ) // The version of the archive
+ , type_ ( 0U ) // The type of the vector
+ , elementType_( 0U ) // The type of an element
+ , elementSize_( 0U ) // The size in bytes of a single element of the vector
+ , size_ ( 0UL ) // The size of the vector
+ , number_ ( 0UL ) // The total number of elements contained in the vector
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SERIALIZATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Serializes the given vector and writes it to the archive.
+//
+// \param archive The archive to be written.
+// \param vec The vector to be serialized.
+// \return void
+// \exception std::runtime_error Error during serialization.
+//
+// This function serializes the given vector and writes it to the given archive. In case any
+// error is detected during the serialization, a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void VectorSerializer::serialize( Archive& archive, const Vector<VT,TF>& vec )
+{
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Faulty archive detected" );
+ }
+
+ serializeHeader( archive, ~vec );
+ serializeVector( archive, ~vec );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Serializes all meta information about the given vector.
+//
+// \param archive The archive to be written.
+// \param vec The vector to be serialized.
+// \return void
+// \exception std::runtime_error File header could not be serialized.
+*/
+template< typename Archive // Type of the archive
+ , typename VT > // Type of the vector
+void VectorSerializer::serializeHeader( Archive& archive, const VT& vec )
+{
+ typedef ElementType_<VT> ET;
+
+ archive << uint8_t ( 1U );
+ archive << uint8_t ( VectorValueMapping<VT>::value );
+ archive << uint8_t ( TypeValueMapping<ET>::value );
+ archive << uint8_t ( sizeof( ET ) );
+ archive << uint64_t( vec.size() );
+ archive << uint64_t( IsDenseVector<VT>::value ? vec.size() : vec.nonZeros() );
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "File header could not be serialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Serializes the elements of a dense vector.
+//
+// \param archive The archive to be written.
+// \param vec The vector to be serialized.
+// \return void
+// \exception std::runtime_error Dense vector could not be serialized.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void VectorSerializer::serializeVector( Archive& archive, const DenseVector<VT,TF>& vec )
+{
+ size_t i( 0UL );
+ while( ( i < (~vec).size() ) && ( archive << (~vec)[i] ) ) {
+ ++i;
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense vector could not be serialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Serializes the elements of a sparse vector.
+//
+// \param archive The archive to be written.
+// \param vec The vector to be serialized.
+// \return void
+// \exception std::runtime_error Sparse vector could not be serialized.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void VectorSerializer::serializeVector( Archive& archive, const SparseVector<VT,TF>& vec )
+{
+ typedef ConstIterator_<VT> ConstIterator;
+
+ ConstIterator element( (~vec).begin() );
+ while( ( element != (~vec).end() ) &&
+ ( archive << element->index() << element->value() ) ) {
+ ++element;
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse vector could not be serialized" );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESERIALIZATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Deserializes a vector from the given archive.
+//
+// \param archive The archive to be read from.
+// \param vec The vector to be deserialized.
+// \return void
+// \exception std::runtime_error Error during deserialization.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void VectorSerializer::deserialize( Archive& archive, Vector<VT,TF>& vec )
+{
+ if( !archive ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Faulty archive detected" );
+ }
+
+ deserializeHeader( archive, ~vec );
+ prepareVector( ~vec );
+ deserializeVector( archive, ~vec );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes all meta information about the given vector.
+//
+// \param archive The archive to be read from.
+// \param vec The vector to be deserialized.
+// \return void
+// \exception std::runtime_error Error during deserialization.
+//
+// This function deserializes all meta information about the given vector contained in the
+// header of the given archive. In case any error is detected during the deserialization
+// process (for instance an invalid type of vector, element type, element size, or vector
+// size) a \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename VT > // Type of the vector
+void VectorSerializer::deserializeHeader( Archive& archive, const VT& vec )
+{
+ typedef ElementType_<VT> ET;
+
+ if( !( archive >> version_ >> type_ >> elementType_ >> elementSize_ >> size_ >> number_ ) ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Corrupt archive detected" );
+ }
+ else if( version_ != 1UL ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid version detected" );
+ }
+ else if( ( type_ & 1U ) != 0U || ( type_ & (~3U) ) != 0U ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid vector type detected" );
+ }
+ else if( elementType_ != TypeValueMapping<ET>::value ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid element type detected" );
+ }
+ else if( elementSize_ != sizeof( ET ) ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid element size detected" );
+ }
+ else if( !IsResizable<VT>::value && size_ != vec.size() ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid vector size detected" );
+ }
+ else if( number_ > size_ ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Invalid number of elements detected" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Prepares the given non-resizable dense vector for the deserialization process.
+//
+// \param vec The dense vector to be prepared.
+// \return void
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+DisableIf_< IsResizable<VT> > VectorSerializer::prepareVector( DenseVector<VT,TF>& vec )
+{
+ reset( ~vec );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Prepares the given non-resizable sparse vector for the deserialization process.
+//
+// \param vec The sparse vector to be prepared.
+// \return void
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+DisableIf_< IsResizable<VT> > VectorSerializer::prepareVector( SparseVector<VT,TF>& vec )
+{
+ (~vec).reserve( number_ );
+ reset( ~vec );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Prepares the given resizable vector for the deserialization process.
+//
+// \param vec The vector to be prepared.
+// \return void
+*/
+template< typename VT > // Type of the vector
+EnableIf_< IsResizable<VT> > VectorSerializer::prepareVector( VT& vec )
+{
+ vec.resize ( size_, false );
+ vec.reserve( number_ );
+ reset( vec );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a vector from the archive.
+//
+// \param archive The archive to be read from.
+// \param vec The vector to be reconstituted.
+// \return void
+// \exception std::runtime_error Error during deserialization.
+//
+// This function deserializes the contents of the vector from the archive and reconstitutes the
+// given vector.
+*/
+template< typename Archive // Type of the archive
+ , typename VT > // Type of the vector
+void VectorSerializer::deserializeVector( Archive& archive, VT& vec )
+{
+ if( type_ == 0U ) {
+ deserializeDenseVector( archive, vec );
+ }
+ else if( type_ == 2U ) {
+ deserializeSparseVector( archive, vec );
+ }
+ else {
+ BLAZE_INTERNAL_ASSERT( false, "Undefined type flag" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a dense vector from the archive.
+//
+// \param archive The archive to be read from.
+// \param vec The dense vector to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense vector could not be deserialized.
+//
+// This function deserializes a dense vector from the archive and reconstitutes the given
+// dense vector. In case any error is detected during the deserialization process, a
+// \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+typename DisableIfTrue< VT::simdEnabled >::Type
+ VectorSerializer::deserializeDenseVector( Archive& archive, DenseVector<VT,TF>& vec )
+{
+ typedef ElementType_<VT> ET;
+
+ size_t i( 0UL );
+ ET value = ET();
+
+ while( ( i != size_ ) && ( archive >> value ) ) {
+ (~vec)[i] = value;
+ ++i;
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense vector could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a dense vector from the archive.
+//
+// \param archive The archive to be read from.
+// \param vec The dense vector to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense vector could not be deserialized.
+//
+// This function deserializes a dense vector from the archive and reconstitutes the given
+// dense vector. In case any error is detected during the deserialization process, a
+// \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+EnableIfTrue_< VT::simdEnabled >
+ VectorSerializer::deserializeDenseVector( Archive& archive, DenseVector<VT,TF>& vec )
+{
+ if( size_ == 0UL ) return;
+ archive.read( &(~vec)[0], size_ );
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense vector could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a dense vector from the archive.
+//
+// \param archive The archive to be read from.
+// \param vec The sparse vector to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse vector could not be deserialized.
+//
+// This function deserializes a dense vector from the archive and reconstitutes the given
+// sparse vector. In case any error is detected during the deserialization process, a
+// \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void VectorSerializer::deserializeDenseVector( Archive& archive, SparseVector<VT,TF>& vec )
+{
+ typedef ElementType_<VT> ET;
+
+ size_t i( 0UL );
+ ET value = ET();
+
+ while( ( i != size_ ) && ( archive >> value ) ) {
+ (~vec)[i] = value;
+ ++i;
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse vector could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a sparse vector from the archive.
+//
+// \param archive The archive to be read from.
+// \param vec The dense vector to be reconstituted.
+// \return void
+// \exception std::runtime_error Dense vector could not be deserialized.
+//
+// This function deserializes a sparse vector from the archive and reconstitutes the given
+// dense vector. In case any error is detected during the deserialization process, a
+// \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void VectorSerializer::deserializeSparseVector( Archive& archive, DenseVector<VT,TF>& vec )
+{
+ typedef ElementType_<VT> ET;
+
+ size_t i( 0UL );
+ size_t index( 0UL );
+ ET value = ET();
+
+ while( ( i != number_ ) && ( archive >> index >> value ) ) {
+ (~vec)[index] = value;
+ ++i;
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Dense vector could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a sparse vector from the archive.
+//
+// \param archive The archive to be read from.
+// \param vec The sparse vector to be reconstituted.
+// \return void
+// \exception std::runtime_error Sparse vector could not be deserialized.
+//
+// This function deserializes a sparse vector from the archive and reconstitutes the given
+// sparse vector. In case any error is detected during the deserialization process, a
+// \a std::runtime_error is thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void VectorSerializer::deserializeSparseVector( Archive& archive, SparseVector<VT,TF>& vec )
+{
+ typedef ElementType_<VT> ET;
+
+ size_t i( 0UL );
+ size_t index( 0UL );
+ ET value = ET();
+
+ while( ( i != number_ ) && ( archive >> index >> value ) ) {
+ (~vec).append( index, value, false );
+ ++i;
+ }
+
+ if( !archive ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Sparse vector could not be deserialized" );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// VECTORVALUEMAPPINGHELPER SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the VectorValueMappingHelper class template for dense vectors.
+*/
+template<>
+struct VectorSerializer::VectorValueMappingHelper<true>
+{
+ enum { value = 0 };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the VectorValueMappingHelper class template for sparse vectors.
+*/
+template<>
+struct VectorSerializer::VectorValueMappingHelper<false>
+{
+ enum { value = 2 };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Serializes the given vector and writes it to the archive.
+//
+// \param archive The archive to be written.
+// \param vec The vector to be serialized.
+// \return void
+// \exception std::runtime_error Error during serialization.
+//
+// The serialize() function converts the given vector into a portable, binary representation.
+// The following example demonstrates the (de-)serialization process of vectors:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ // Serialization of both vectors
+ {
+ blaze::StaticVector<double,5UL,rowVector> d;
+ blaze::CompressedVector<int,columnVector> s;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that writes into a the file "vectors.blaze"
+ blaze::Archive<std::ofstream> archive( "vectors.blaze" );
+
+ // Serialization of both vectors into the same archive. Note that d lies before s!
+ archive << d << s;
+ }
+
+ // Reconstitution of both vectors
+ {
+ blaze::DynamicVector<double,rowVector> d1;
+ blaze::DynamicVector<int,rowVector> d2;
+
+ // ... Resizing and initialization
+
+ // Creating an archive that reads from the file "vectors.blaze"
+ blaze::Archive<std::ofstream> archive( "vectors.blaze" );
+
+ // Reconstituting the former d vector into d1. Note that it is possible to reconstitute
+ // the vector into a differrent kind of vector (StaticVector -> DynamicVector), but that
+ // the type of elements has to be the same.
+ archive >> d1;
+
+ // Reconstituting the former s vector into d2. Note that is is even possible to reconstitute
+ // a sparse vector as a dense vector (also the reverse is possible) and that a column vector
+ // can be reconstituted as row vector (and vice versa). Note however that also in this case
+ // the type of elements is the same!
+ archive >> d2
+ }
+ \endcode
+
+// As the example demonstrates, the vector serialization offers an enormous flexibility. However,
+// several actions result in errors:
+//
+// - vectors cannot be reconstituted as matrices (and vice versa)
+// - the element type of the serialized and reconstituted vector must match, which means
+// that on the source and destination platform the general type (signed/unsigned integral
+// or floating point) and the size of the type must be exactly the same
+// - when reconstituting a StaticVector, its size must match the size of the serialized vector
+//
+// In case an error is encountered during (de-)serialization, a \a std::runtime_exception is
+// thrown.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void serialize( Archive& archive, const Vector<VT,TF>& vec )
+{
+ VectorSerializer().serialize( archive, ~vec );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a vector from the given archive.
+//
+// \param archive The archive to be read from.
+// \param vec The vector to be deserialized.
+// \return void
+// \exception std::runtime_error Vector could not be deserialized.
+//
+// The deserialize() function converts the portable, binary representation contained in
+// the given archive into the given vector type. For a detailed example that demonstrates
+// the (de-)serialization process of vectors, see the serialize() function.
+*/
+template< typename Archive // Type of the archive
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+void deserialize( Archive& archive, Vector<VT,TF>& vec )
+{
+ VectorSerializer().deserialize( archive, ~vec );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Abs.h b/src/cpu/blaze/math/shims/Abs.h
new file mode 100644
index 00000000..509ef742
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Abs.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Abs.h
+// \brief Header file for the abs shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ABS_H_
+#define _BLAZE_MATH_SHIMS_ABS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ABS SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::abs() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::abs;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Acos.h b/src/cpu/blaze/math/shims/Acos.h
new file mode 100644
index 00000000..8d3d2fe5
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Acos.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Acos.h
+// \brief Header file for the acos shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ACOS_H_
+#define _BLAZE_MATH_SHIMS_ACOS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ACOS SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::acos() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::acos;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Acosh.h b/src/cpu/blaze/math/shims/Acosh.h
new file mode 100644
index 00000000..a85be4ff
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Acosh.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Acosh.h
+// \brief Header file for the acosh shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ACOSH_H_
+#define _BLAZE_MATH_SHIMS_ACOSH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ACOSH SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::acosh() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::acosh;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Asin.h b/src/cpu/blaze/math/shims/Asin.h
new file mode 100644
index 00000000..fb7fb2dc
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Asin.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Asin.h
+// \brief Header file for the asin shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ASIN_H_
+#define _BLAZE_MATH_SHIMS_ASIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ASIN SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::asin() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::asin;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Asinh.h b/src/cpu/blaze/math/shims/Asinh.h
new file mode 100644
index 00000000..6317e528
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Asinh.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Asinh.h
+// \brief Header file for the asinh shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ASINH_H_
+#define _BLAZE_MATH_SHIMS_ASINH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ASINH SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::asinh() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::asinh;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Atan.h b/src/cpu/blaze/math/shims/Atan.h
new file mode 100644
index 00000000..d90c503c
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Atan.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Atan.h
+// \brief Header file for the atan shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ATAN_H_
+#define _BLAZE_MATH_SHIMS_ATAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ATAN SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::atan() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::atan;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Atanh.h b/src/cpu/blaze/math/shims/Atanh.h
new file mode 100644
index 00000000..d7186915
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Atanh.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Atanh.h
+// \brief Header file for the atanh shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ATANH_H_
+#define _BLAZE_MATH_SHIMS_ATANH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ATANH SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::atanh() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::atanh;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Cbrt.h b/src/cpu/blaze/math/shims/Cbrt.h
new file mode 100644
index 00000000..26393d39
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Cbrt.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Cbrt.h
+// \brief Header file for the cbrt shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_CBRT_H_
+#define _BLAZE_MATH_SHIMS_CBRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CBRT SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::cbrt() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::cbrt;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Ceil.h b/src/cpu/blaze/math/shims/Ceil.h
new file mode 100644
index 00000000..d08bd72f
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Ceil.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Ceil.h
+// \brief Header file for the ceil shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_CEIL_H_
+#define _BLAZE_MATH_SHIMS_CEIL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CEIL SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::ceil() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::ceil;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Clear.h b/src/cpu/blaze/math/shims/Clear.h
new file mode 100644
index 00000000..25ccd693
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Clear.h
@@ -0,0 +1,73 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Clear.h
+// \brief Header file for the clear shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_CLEAR_H_
+#define _BLAZE_MATH_SHIMS_CLEAR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLEAR SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Clearing the given value/object to the default state.
+// \ingroup math_shims
+//
+// \param clearable The value/object to be cleared.
+// \return void
+//
+// The \a clear shim represents an abstract interface for clearing a value/object of any given
+// data type to its default state. Values of built-in data type are reset to zero.
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE void clear( Type& clearable )
+{
+ clearable = Type(0);
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Conjugate.h b/src/cpu/blaze/math/shims/Conjugate.h
new file mode 100644
index 00000000..eded8b36
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Conjugate.h
@@ -0,0 +1,203 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Conjugate.h
+// \brief Header file for the conjugate shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_CONJUGATE_H_
+#define _BLAZE_MATH_SHIMS_CONJUGATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/system/Inline.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CONJ SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computing the conjugate of the given value/object.
+// \ingroup math_shims
+//
+// \param a The given value/object.
+// \return The complex conjugate of the given value.
+//
+// The \a conj shim represents an abstract interface for the computation of the complex conjugate
+// of any given data type. In case the given value is of complex type the function computes the
+// complex conjugate by reversing the sign of the imaginary part:
+
+ \code
+ const blaze::complex<double> a( 1.0, 2.0 );
+ const blaze::complex<double> b( conj( a ) ); // Results in ( 1, -2 )
+ \endcode
+
+// Values of other data types, such as all built-in data types, are considered complex numbers
+// with an imaginary part of 0. Thus the returned value corresponds to the given value. For more
+// information on complex conjugates, see
+//
+// https://en.wikipedia.org/wiki/Complex_conjugate
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE constexpr EnableIf_< IsBuiltin<T>, T > conj( T a ) noexcept
+{
+ return a;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONJUGATE SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief In-place conjugation of the given value/object.
+// \ingroup math_shims
+//
+// \param a The given value/object to be conjugated.
+// \return void
+//
+// The \a conjugate shim represents an abstract interface for the in-place conjugation of any
+// given value/object. In case the given value is of complex type the function computes the
+// complex conjugate by reversing the sign of the imaginary part:
+
+ \code
+ blaze::complex<double> a( 1.0, 2.0 );
+ conjugate( a ); // Results in ( 1, -2 )
+ \endcode
+
+// Values of other data types, such as all built-in data types, are considered complex numbers
+// with an imaginary part of 0. Thus the returned value corresponds to the given value. For more
+// information on complex conjugates, see
+//
+// https://en.wikipedia.org/wiki/Complex_conjugate
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE void conjugate( T& a ) noexcept( IsNumeric<T>::value )
+{
+ a = conj( a );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CSWAP SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend function of the \a cswap function for non-numeric data types.
+// \ingroup math_shims
+//
+// \param a The first value/object to be swapped and conjugated.
+// \param b The second value/object to be swapped and conjugated.
+// \return void
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE DisableIf_< IsNumeric<T> > cswap_backend( T& a, T& b )
+{
+ using std::swap;
+
+ swap( a, b );
+ conjugate( a );
+ conjugate( b );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend function of the \a cswap function for numeric data types.
+// \ingroup math_shims
+//
+// \param a The first value to be swapped and conjugated.
+// \param b The second value to be swapped and conjugated.
+// \return void
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE EnableIf_< IsNumeric<T> > cswap_backend( T& a, T& b ) noexcept
+{
+ const T tmp( a );
+ a = conj( b );
+ b = conj( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping two conjugated values/objects.
+// \ingroup math_shims
+//
+// \param a The first value/object to be swapped and conjugated.
+// \param b The second value/object to be swapped and conjugated.
+// \return void
+//
+// The \a cswap shim implements the most efficient way to swap and conjugate two values/objects.
+// Semantically \a cswap is equivalent to the following sequence of operations:
+
+ \code
+ swap( a, b );
+ conjugate( a );
+ conjugate( b );
+ \endcode
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE void cswap( T& a, T& b ) noexcept( IsNumeric<T>::value )
+{
+ cswap_backend( a, b );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Cos.h b/src/cpu/blaze/math/shims/Cos.h
new file mode 100644
index 00000000..c6830b06
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Cos.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Cos.h
+// \brief Header file for the cos shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_COS_H_
+#define _BLAZE_MATH_SHIMS_COS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// COS SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::cos() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::cos;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Cosh.h b/src/cpu/blaze/math/shims/Cosh.h
new file mode 100644
index 00000000..2214f800
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Cosh.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Cosh.h
+// \brief Header file for the cosh shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_COSH_H_
+#define _BLAZE_MATH_SHIMS_COSH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// COSH SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::cosh() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::cosh;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Equal.h b/src/cpu/blaze/math/shims/Equal.h
new file mode 100644
index 00000000..a42d8812
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Equal.h
@@ -0,0 +1,383 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Equal.h
+// \brief Header file for the equal shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_EQUAL_H_
+#define _BLAZE_MATH_SHIMS_EQUAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Accuracy.h>
+#include <blaze/math/Functions.h>
+#include <blaze/util/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// EQUAL SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic equality check.
+// \ingroup math_shims
+//
+// \param a First value/object.
+// \param b Second value/object.
+// \return \a true if the two values/objects are equal, \a false if not.
+//
+// The equal shim represents an abstract interface for testing two values/objects for equality.
+// In case the two values/objects are equal, the function returns \a true, otherwise it returns
+// \a false. Per default, the comparison of the two values/objects uses the equality operator
+// operator==(). For built-in floating point data types a special comparison is selected that
+// takes the limited machine accuracy into account.
+*/
+template< typename T1 // Type of the left-hand side value/object
+ , typename T2 > // Type of the right-hand side value/object
+inline bool equal( const T1& a, const T2& b )
+{
+ return a == b;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for two single precision floating point values.
+// \ingroup math_shims
+//
+// \param a The left-hand side single precision floating point value.
+// \param b The right-hand side single precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of two single precision floating point numbers. Due to the
+// limited machine accuracy, a direct comparison of two floating point numbers should be avoided.
+// This function offers the possibility to compare two floating-point values with a certain
+// accuracy margin.
+//
+// For more information on comparing float point numbers, see
+//
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+*/
+inline bool equal( float a, float b )
+{
+ const float acc( static_cast<float>( accuracy ) );
+ return ( std::fabs( a - b ) <= max( acc, acc * std::fabs( a ) ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for a single precision and a double precision floating point value.
+// \ingroup math_shims
+//
+// \param a The left-hand side single precision floating point value.
+// \param b The right-hand side double precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of a single precision and a double precision floating point
+// number. Due to the limited machine accuracy, a direct comparison of two floating point numbers
+// should be avoided. This function offers the possibility to compare two floating-point values
+// with a certain accuracy margin.
+//
+// For more information on comparing float point numbers, see
+//
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+*/
+inline bool equal( float a, double b )
+{
+ return equal( a, static_cast<float>( b ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for a single precision and an extended precision floating point value.
+// \ingroup math_shims
+//
+// \param a The left-hand side single precision floating point value.
+// \param b The right-hand side extended precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of a single precision and an extended precision floating point
+// number. Due to the limited machine accuracy, a direct comparison of two floating point numbers
+// should be avoided. This function offers the possibility to compare two floating-point values
+// with a certain accuracy margin.
+//
+// For more information on comparing float point numbers, see
+//
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+*/
+inline bool equal( float a, long double b )
+{
+ return equal( a, static_cast<float>( b ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for a double precision and a single precision floating point value.
+// \ingroup math_shims
+//
+// \param a The left-hand side double precision floating point value.
+// \param b The right-hand side single precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of a double precision and a single precision floating point
+// number. Due to the limited machine accuracy, a direct comparison of two floating point numbers
+// should be avoided. This function offers the possibility to compare two floating-point values
+// with a certain accuracy margin.
+*/
+inline bool equal( double a, float b )
+{
+ return equal( static_cast<float>( a ), b );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for two double precision floating point values.
+// \ingroup math_shims
+//
+// \param a The left-hand side double precision floating point value.
+// \param b The right-hand side double precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of two double precision floating point numbers. Due to the
+// limited machine accuracy, a direct comparison of two floating point numbers should be avoided.
+// This function offers the possibility to compare two floating-point values with a certain
+// accuracy margin.
+//
+// For more information on comparing float point numbers, see
+//
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+*/
+inline bool equal( double a, double b )
+{
+ const double acc( static_cast<double>( accuracy ) );
+ return ( std::fabs( a - b ) <= max( acc, acc * std::fabs( a ) ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for a double precision and an extended precision floating point value.
+// \ingroup math_shims
+//
+// \param a The left-hand side double precision floating point value.
+// \param b The right-hand side extended precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of a double precision and an extended precision floating point
+// number. Due to the limited machine accuracy, a direct comparison of two floating point numbers
+// should be avoided. This function offers the possibility to compare two floating-point values
+// with a certain accuracy margin.
+//
+// For more information on comparing float point numbers, see
+//
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+*/
+inline bool equal( double a, long double b )
+{
+ return equal( a, static_cast<double>( b ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for an extended precision and a single precision floating point value.
+// \ingroup math_shims
+//
+// \param a The left-hand side extended precision floating point value.
+// \param b The right-hand side single precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of an extended precision and a single precision floating point
+// number. Due to the limited machine accuracy, a direct comparison of two floating point numbers
+// should be avoided. This function offers the possibility to compare two floating-point values
+// with a certain accuracy margin.
+//
+// For more information on comparing float point numbers, see
+//
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+*/
+inline bool equal( long double a, float b )
+{
+ return equal( static_cast<float>( a ), b );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for an extended precision and a double precision floating point value.
+// \ingroup math_shims
+//
+// \param a The left-hand side extended precision floating point value.
+// \param b The right-hand side double precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of an extended precision and a double precision floating point
+// number. Due to the limited machine accuracy, a direct comparison of two floating point numbers
+// should be avoided. This function offers the possibility to compare two floating-point values
+// with a certain accuracy margin.
+//
+// For more information on comparing float point numbers, see
+//
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+*/
+inline bool equal( long double a, double b )
+{
+ return equal( static_cast<double>( a ), b );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for two long double precision floating point values.
+// \ingroup math_shims
+//
+// \param a The left-hand side extended precision floating point value.
+// \param b The right-hand side extended precision floating point value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of two long double precision floating point numbers. Due
+// to the limited machine accuracy, a direct comparison of two floating point numbers should be
+// avoided. This function offers the possibility to compare two floating-point values with a
+// certain accuracy margin.
+//
+// For more information on comparing float point numbers, see
+//
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+*/
+inline bool equal( long double a, long double b )
+{
+ const long double acc( static_cast<long double>( accuracy ) );
+ return ( std::fabs( a - b ) <= max( acc, acc * std::fabs( a ) ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for a complex and a scalar value.
+// \ingroup math_shims
+//
+// \param a The left-hand side complex value.
+// \param b The right-hand side scalar value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of a complex and a scalar value. The function compares the
+// real part of the complex value with the scalar. In case these two values match and in case
+// the imaginary part is zero, the function returns \a true. Otherwise it returns \a false.
+*/
+template< typename T1 // Type of the left-hand side complex value
+ , typename T2 > // Type of the right-hand side scalar value
+inline bool equal( complex<T1> a, T2 b )
+{
+ return equal( real( a ), b ) && equal( imag( a ), T1() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for a scalar and a complex value.
+// \ingroup math_shims
+//
+// \param a The left-hand side scalar value.
+// \param b The right-hand side complex value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of a scalar and a complex value. The function compares the
+// scalar with the real part of the complex value. In case these two values match and in case
+// the imaginary part is zero, the function returns \a true. Otherwise it returns \a false.
+*/
+template< typename T1 // Type of the left-hand side scalar value
+ , typename T2 > // Type of the right-hand side complex value
+inline bool equal( T1 a, complex<T2> b )
+{
+ return equal( a, real( b ) ) && equal( imag( b ), T2() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Equality check for two complex values.
+// \ingroup math_shims
+//
+// \param a The left-hand side complex value.
+// \param b The right-hand side complex value.
+// \return \a true if the two values are equal, \a false if not.
+//
+// Equal function for the comparison of two complex numbers. Due to the limited machine accuracy,
+// a direct comparison of two floating point numbers should be avoided. This function offers the
+// possibility to compare two floating-point values with a certain accuracy margin.
+*/
+template< typename T1 // Type of the left-hand side complex value
+ , typename T2 > // Type of the right-hand side complex value
+inline bool equal( complex<T1> a, complex<T2> b )
+{
+ return equal( real( a ), real( b ) ) && equal( imag( a ), imag( b ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Erf.h b/src/cpu/blaze/math/shims/Erf.h
new file mode 100644
index 00000000..6944ffa2
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Erf.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Erf.h
+// \brief Header file for the erf shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ERF_H_
+#define _BLAZE_MATH_SHIMS_ERF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ERF SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::erf() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::erf;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Erfc.h b/src/cpu/blaze/math/shims/Erfc.h
new file mode 100644
index 00000000..56c86893
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Erfc.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Erfc.h
+// \brief Header file for the erfc shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ERFC_H_
+#define _BLAZE_MATH_SHIMS_ERFC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ERFC SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::erfc() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::erfc;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Exp.h b/src/cpu/blaze/math/shims/Exp.h
new file mode 100644
index 00000000..e2b9b023
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Exp.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Exp.h
+// \brief Header file for the exp shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_EXP_H_
+#define _BLAZE_MATH_SHIMS_EXP_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// EXP SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::exp() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::exp;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Floor.h b/src/cpu/blaze/math/shims/Floor.h
new file mode 100644
index 00000000..aedf17be
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Floor.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Floor.h
+// \brief Header file for the floor shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_FLOOR_H_
+#define _BLAZE_MATH_SHIMS_FLOOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// FLOOR SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::floor() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::floor;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Imaginary.h b/src/cpu/blaze/math/shims/Imaginary.h
new file mode 100644
index 00000000..232d1215
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Imaginary.h
@@ -0,0 +1,94 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Imaginary.h
+// \brief Header file for the imaginary shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_IMAGINARY_H_
+#define _BLAZE_MATH_SHIMS_IMAGINARY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// IMAGINARY SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Computing the imaginary part of the given value/object.
+// \ingroup math_shims
+//
+// \param a The given value/object.
+// \return The imaginary part of the given value.
+//
+// The \a imag shim represents an abstract interface for the computation of the imaginary part
+// of any given data type. In case the given value is of complex type the function returns the
+// imaginary part:
+
+ \code
+ const blaze::complex<double> a( 3.0, -2.0 );
+ const double b( imag( a ) ); // Results in -2.0
+ \endcode
+
+// Values of built-in data type are considered complex numbers with an imaginary part of 0. Thus
+// the returned value is 0:
+
+ \code
+ const double a( -3.0 );
+ const double b( imag( a ) ); // Results in 0.0
+ \endcode
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE EnableIf_< IsBuiltin<T>, T > imag( T a ) noexcept
+{
+ UNUSED_PARAMETER( a );
+
+ return T(0);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/InvCbrt.h b/src/cpu/blaze/math/shims/InvCbrt.h
new file mode 100644
index 00000000..cf343282
--- /dev/null
+++ b/src/cpu/blaze/math/shims/InvCbrt.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/InvCbrt.h
+// \brief Header file for the invcbrt shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_INVCBRT_H_
+#define _BLAZE_MATH_SHIMS_INVCBRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/Cbrt.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// INVCBRT SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the inverse cubic root of the given built-in value.
+// \ingroup math_shims
+//
+// \param a The given built-in value \f$[0..\infty)\f$.
+// \return The inverse cubic root of the given value.
+//
+// \note The given value must be in the range \f$[0..\infty)\f$. The validity of the value is
+// only checked by an user assert.
+*/
+template< typename T, typename = EnableIf_< IsBuiltin<T> > >
+inline auto invcbrt( T a ) noexcept -> decltype( inv( cbrt( a ) ) )
+{
+ BLAZE_USER_ASSERT( abs( a ) != T(0), "Invalid built-in value detected" );
+
+ return inv( cbrt( a ) );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/InvSqrt.h b/src/cpu/blaze/math/shims/InvSqrt.h
new file mode 100644
index 00000000..501e761e
--- /dev/null
+++ b/src/cpu/blaze/math/shims/InvSqrt.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/InvSqrt.h
+// \brief Header file for the invsqrt shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_INVSQRT_H_
+#define _BLAZE_MATH_SHIMS_INVSQRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Invert.h>
+#include <blaze/math/shims/Sqrt.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// INVSQRT SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the inverse square root of the given built-in value.
+// \ingroup math_shims
+//
+// \param a The given built-in value \f$[0..\infty)\f$.
+// \return The inverse square root of the given value.
+//
+// \note The given value must be in the range \f$[0..\infty)\f$. The validity of the value is
+// only checked by an user assert.
+*/
+template< typename T, typename = EnableIf_< IsBuiltin<T> > >
+inline auto invsqrt( T a ) noexcept -> decltype( inv( sqrt( a ) ) )
+{
+ BLAZE_USER_ASSERT( a > T(0), "Invalid built-in value detected" );
+
+ return inv( sqrt( a ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the inverse square root of the given complex number.
+// \ingroup math_shims
+//
+// \param a The given complex number.
+// \return The inverse square root of the given complex number.
+//
+// \note The given complex number must not be zero. The validity of the value is only checked by
+// an user assert.
+*/
+template< typename T, typename = EnableIf_< IsBuiltin<T> > >
+inline auto invsqrt( const complex<T>& a ) noexcept -> decltype( inv( sqrt( a ) ) )
+{
+ BLAZE_USER_ASSERT( abs( a ) != T(0), "Invalid complex value detected" );
+
+ return inv( sqrt( a ) );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Invert.h b/src/cpu/blaze/math/shims/Invert.h
new file mode 100644
index 00000000..a2875c92
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Invert.h
@@ -0,0 +1,318 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Invert.h
+// \brief Header file for the invert shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_INVERT_H_
+#define _BLAZE_MATH_SHIMS_INVERT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Square.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// INV SHIMS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverting the given single precision value.
+// \ingroup math_shims
+//
+// \param a The single precision value to be inverted.
+// \return The inverse of the given value.
+//
+// The \a inv shim represents an abstract interface for inverting a value/object of any given
+// data type. For single precision floating point values this results in \f$ \frac{1}{a} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE float inv( float a ) noexcept
+{
+ BLAZE_USER_ASSERT( a != 0.0F, "Division by zero detected" );
+ return ( 1.0F / a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inverting the given double precision value.
+// \ingroup math_shims
+//
+// \param a The double precision value to be inverted.
+// \return The inverse of the given value.
+//
+// The \a inv shim represents an abstract interface for inverting a value/object of any given
+// data type. For double precision floating point values this results in \f$ \frac{1}{a} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE double inv( double a ) noexcept
+{
+ BLAZE_USER_ASSERT( a != 0.0, "Division by zero detected" );
+ return ( 1.0 / a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inverting the given extended precision value.
+// \ingroup math_shims
+//
+// \param a The extended precision value to be inverted.
+// \return The inverse of the given value.
+//
+// The \a inv shim represents an abstract interface for inverting a value/object of any given
+// data type. For extended precision floating point values this results in \f$ \frac{1}{a} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE long double inv( long double a ) noexcept
+{
+ BLAZE_USER_ASSERT( a != 0.0L, "Division by zero detected" );
+ return ( 1.0L / a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inverting the given single precision complex number.
+// \ingroup math_shims
+//
+// \param a The single precision complex number to be inverted.
+// \return The inverse of the given value.
+//
+// The \a inv shim represents an abstract interface for inverting a value/object of any given
+// data type. For a single precision floating point complex number \f$ z = x + yi \f$ this
+// results in \f$ \frac{\overline{z}}{x^2+y^2} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE complex<float> inv( const complex<float>& a ) noexcept
+{
+ const float abs( sq( real(a) ) + sq( imag(a) ) );
+ BLAZE_USER_ASSERT( abs != 0.0F, "Division by zero detected" );
+
+ const float iabs( 1.0F / abs );
+ return complex<float>( iabs*real(a), -iabs*imag(a) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inverting the given double precision complex number.
+// \ingroup math_shims
+//
+// \param a The double precision complex number to be inverted.
+// \return The inverse of the given value.
+//
+// The \a inv shim represents an abstract interface for inverting a value/object of any given
+// data type. For a double precision floating point complex number \f$ z = x + yi \f$ this
+// results in \f$ \frac{\overline{z}}{x^2+y^2} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE complex<double> inv( const complex<double>& a ) noexcept
+{
+ const double abs( sq( real(a) ) + sq( imag(a) ) );
+ BLAZE_USER_ASSERT( abs != 0.0, "Division by zero detected" );
+
+ const double iabs( 1.0 / abs );
+ return complex<double>( iabs*real(a), -iabs*imag(a) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inverting the given extended precision complex number.
+// \ingroup math_shims
+//
+// \param a The extended precision complex number to be inverted.
+// \return The inverse of the given value.
+//
+// The \a inv shim represents an abstract interface for inverting a value/object of any given
+// data type. For an extended precision floating point complex number \f$ z = x + yi \f$ this
+// results in \f$ \frac{\overline{z}}{x^2+y^2} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE complex<long double> inv( const complex<long double>& a ) noexcept
+{
+ const long double abs( sq( real(a) ) + sq( imag(a) ) );
+ BLAZE_USER_ASSERT( abs != 0.0L, "Division by zero detected" );
+
+ const long double iabs( 1.0L / abs );
+ return complex<long double>( iabs*real(a), -iabs*imag(a) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// INVERT SHIMS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the given single precision value.
+// \ingroup math_shims
+//
+// \param a The single precision value to be inverted.
+// \return The inverse of the given value.
+//
+// The \a invert shim represents an abstract interface for inverting a value/object of any
+// given data type in-place. For single precision floating point values this results in
+// \f$ \frac{1}{a} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE void invert( float& a ) noexcept
+{
+ a = inv( a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the given double precision value.
+// \ingroup math_shims
+//
+// \param a The double precision value to be inverted.
+// \return The inverse of the given value.
+//
+// The \a invert shim represents an abstract interface for inverting a value/object of any
+// given data type in-place. For double precision floating point values this results in
+// \f$ \frac{1}{a} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE void invert( double& a ) noexcept
+{
+ a = inv( a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the given extended precision value.
+// \ingroup math_shims
+//
+// \param a The extended precision value to be inverted.
+// \return The inverse of the given value.
+//
+// The \a invert shim represents an abstract interface for inverting a value/object of any
+// given data type in-place. For extended precision floating point values this results in
+// \f$ \frac{1}{a} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE void invert( long double& a ) noexcept
+{
+ a = inv( a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the given single precision complex number.
+// \ingroup math_shims
+//
+// \param a The single precision complex number to be inverted.
+// \return The inverse of the given value.
+//
+// The \a invert shim represents an abstract interface for inverting a value/object of any given
+// data type in-place. For a single precision floating point complex number \f$ z = x + yi \f$
+// this results in \f$ \frac{\overline{z}}{x^2+y^2} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE void invert( complex<float>& a ) noexcept
+{
+ a = inv( a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the given double precision complex number.
+// \ingroup math_shims
+//
+// \param a The double precision complex number to be inverted.
+// \return The inverse of the given value.
+//
+// The \a invert shim represents an abstract interface for inverting a value/object of any given
+// data type in-place. For a double precision floating point complex number \f$ z = x + yi \f$
+// this results in \f$ \frac{\overline{z}}{x^2+y^2} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE void invert( complex<double>& a ) noexcept
+{
+ a = inv( a );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place inversion of the given extended precision complex number.
+// \ingroup math_shims
+//
+// \param a The extended precision complex number to be inverted.
+// \return The inverse of the given value.
+//
+// The \a invert shim represents an abstract interface for inverting a value/object of any given
+// data type in-place. For an extended precision floating point complex number \f$ z = x + yi \f$
+// this results in \f$ \frac{\overline{z}}{x^2+y^2} \f$.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+BLAZE_ALWAYS_INLINE void invert( complex<long double>& a ) noexcept
+{
+ a = inv( a );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/IsDefault.h b/src/cpu/blaze/math/shims/IsDefault.h
new file mode 100644
index 00000000..bdc5878f
--- /dev/null
+++ b/src/cpu/blaze/math/shims/IsDefault.h
@@ -0,0 +1,168 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/IsDefault.h
+// \brief Header file for the isDefault shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ISDEFAULT_H_
+#define _BLAZE_MATH_SHIMS_ISDEFAULT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Accuracy.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ISDEFAULT SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the given value/object is in default state.
+// \ingroup math_shims
+//
+// \param v The value/object to be tested for its default state.
+// \return \a true in case the given value/object is in its default state, \a false otherwise.
+//
+// The \a isDefault shim represents an abstract interface for testing a value/object whether
+// it is in its default state or not. In case the value/object is in its default state, the
+// function returns \a true, otherwise it returns \a false. For built-in data types, the
+// function returns \a true in case the current value is zero.
+
+ \code
+ const int i = 0; // isDefault( i ) returns true
+ double d = 2.0; // isDefault( d ) returns false
+ Vec3 v1; // isDefault( v1 ) returns true
+ Vec3 v2( 0, 0, 0 ); // isDefault( v2 ) returns true since (0,0,0) is the default state
+ Vec3 v3( 1, 2, 3 ); // isDefault( v3 ) returns false
+ \endcode
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE bool isDefault( const Type& v ) noexcept( IsBuiltin<Type>::value )
+{
+ return v == Type();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given single precision floating point value is zero.
+// \ingroup math_shims
+//
+// \param v The single precision floating point value to be tested for zero.
+// \return \a true in case the given value is zero, \a false otherwise.
+//
+// This overload of the \a isDefault shim tests whether the given single precision floating point
+// value is exactly zero or within an epsilon range to zero. In case the value is zero or close
+// to zero the function returns \a true, otherwise it returns \a false.
+*/
+BLAZE_ALWAYS_INLINE bool isDefault( float v ) noexcept
+{
+ return std::fabs( v ) <= accuracy;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given double precision floating point value is zero.
+// \ingroup math_shims
+//
+// \param v The double precision floating point value to be tested for zero.
+// \return \a true in case the given value is zero, \a false otherwise.
+//
+// This overload of the \a isDefault shim tests whether the given double precision floating point
+// value is exactly zero or within an epsilon range to zero. In case the value is zero or close
+// to zero the function returns \a true, otherwise it returns \a false.
+*/
+BLAZE_ALWAYS_INLINE bool isDefault( double v ) noexcept
+{
+ return std::fabs( v ) <= accuracy;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given extended precision floating point value is zero.
+// \ingroup math_shims
+//
+// \param v The extended precision floating point value to be tested for zero.
+// \return \a true in case the given value is zero, \a false otherwise.
+//
+// This overload of the \a isDefault shim tests whether the given extended precision floating
+// point value is exactly zero or within an epsilon range to zero. In case the value is zero or
+// close to zero the function returns \a true, otherwise it returns \a false.
+*/
+BLAZE_ALWAYS_INLINE bool isDefault( long double v ) noexcept
+{
+ return std::fabs( v ) <= accuracy;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given complex number is zero.
+// \ingroup math_shims
+//
+// \param v The complex number to be tested for zero.
+// \return \a true in case the given value is zero, \a false otherwise.
+//
+// This overload of the \a isDefault shim tests whether both the real and the imaginary part of
+// the given complex number are exactly zero or within an epsilon range to zero. In case the both
+// parts are zero or close to zero the function returns \a true, otherwise it returns \a false.
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE bool isDefault( const complex<T>& v ) noexcept( IsBuiltin<T>::value )
+{
+ return isDefault( real( v ) ) && isDefault( imag( v ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/IsDivisor.h b/src/cpu/blaze/math/shims/IsDivisor.h
new file mode 100644
index 00000000..c354da24
--- /dev/null
+++ b/src/cpu/blaze/math/shims/IsDivisor.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/IsDivisor.h
+// \brief Header file for the isDivisor shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ISDIVISOR_H_
+#define _BLAZE_MATH_SHIMS_ISDIVISOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Equal.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ISDIVISOR SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the given value/object is a valid divisor.
+// \ingroup math_shims
+//
+// \param v The value to be tested.
+// \return \a true in case the given value is a valid divisor, \a false otherwise.
+//
+// The \a isDivisor shim provides an abstract interface for testing a value/object of any type
+// whether it represents a valid divisor. In case the value/object can be used as divisor, the
+// function returns \a true, otherwise it returns \a false.
+
+ \code
+ const int i1 = 1; // isDivisor( i1 ) returns true
+ double d1 = 0.1; // isDivisor( d1 ) returns true
+ complex<double> c1( 0.2, -0.1 ); // isDivisor( c1 ) returns true
+
+ const int i2 = 0; // isDivisor( i2 ) returns false
+ double d2 = 0.0; // isDivisor( d2 ) returns false
+ complex<double> c2( 0.0, 0.0 ); // isDivisor( c2 ) returns false
+ \endcode
+*/
+template< typename Type, typename = EnableIf_< IsNumeric<Type> > >
+BLAZE_ALWAYS_INLINE bool isDivisor( const Type& v )
+{
+ return v != Type(0);
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/IsNaN.h b/src/cpu/blaze/math/shims/IsNaN.h
new file mode 100644
index 00000000..b1d44da3
--- /dev/null
+++ b/src/cpu/blaze/math/shims/IsNaN.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/IsNaN.h
+// \brief Header file for the isnan shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ISNAN_H_
+#define _BLAZE_MATH_SHIMS_ISNAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+//*************************************************************************************************
+// Macro undefinition
+//*************************************************************************************************
+
+#ifdef isnan
+# undef isnan
+#endif
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ISNAN SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Platform independent implementation of the C99 \a isnan function.
+// \ingroup math_shims
+//
+// \param a Value to be checked.
+// \return \a true if \a a is not a number (NaN), \a false otherwise.
+//
+// This function provides a platform independent check for NaN values. In contrast to the \a isnan
+// function from the C standard, which is only supporting all floating point types, this function
+// can be used for all numeric data types (i.e. all integral, floating point, and complex data
+// types). The function returns \a true in case the given value is not a number (NaN). In all
+// other cases the function returns \a false.
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE EnableIf_< IsNumeric<T>, bool > isnan( T a ) noexcept
+{
+ return a != a;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/IsOne.h b/src/cpu/blaze/math/shims/IsOne.h
new file mode 100644
index 00000000..564e49c9
--- /dev/null
+++ b/src/cpu/blaze/math/shims/IsOne.h
@@ -0,0 +1,108 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/IsOne.h
+// \brief Header file for the isOne shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ISONE_H_
+#define _BLAZE_MATH_SHIMS_ISONE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/Equal.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ISONE SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the given value/object represents the numeric value 1.
+// \ingroup math_shims
+//
+// \param v The value to be tested.
+// \return \a true in case the given value is 1, \a false otherwise.
+//
+// The \a isOne shim provides an abstract interface for testing a value/object of any type
+// whether it represents the numeric value 1. In case the value/object is 1, the function
+// returns \a true, otherwise it returns \a false.
+
+ \code
+ const int i1 = 1; // isOne( i1 ) returns true
+ double d1 = 1.0; // isOne( d1 ) returns true
+ complex<double> c1( 1.0, 0.0 ); // isOne( c1 ) returns true
+
+ const int i2 = 2; // isOne( i2 ) returns false
+ double d2 = -1.0; // isOne( d2 ) returns false
+ complex<double> c2( 0.0, 1.0 ); // isOne( c2 ) returns false
+ \endcode
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE EnableIf_< IsNumeric<Type>, bool > isOne( const Type& v )
+{
+ return equal( v, Type(1) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Overload of the \a isOne function for non-numeric data types.
+// \ingroup math_shims
+//
+// \param v The value/object to be tested.
+// \return \a false.
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE DisableIf_< IsNumeric<Type>, bool > isOne( const Type& v ) noexcept
+{
+ UNUSED_PARAMETER( v );
+
+ return false;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/IsReal.h b/src/cpu/blaze/math/shims/IsReal.h
new file mode 100644
index 00000000..d98b2d1c
--- /dev/null
+++ b/src/cpu/blaze/math/shims/IsReal.h
@@ -0,0 +1,109 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/IsReal.h
+// \brief Header file for the isReal shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ISREAL_H_
+#define _BLAZE_MATH_SHIMS_ISREAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ISREAL SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the given value/object represents a real number.
+// \ingroup math_shims
+//
+// \param v The value to be tested.
+// \return \a true in case the given value represents a real number, \a false otherwise.
+//
+// The \a isReal shim provides an abstract interface for testing a value/object of any type
+// whether it represents the a real number. In case the value/object is of built-in type, the
+// function returns \a true. In case the value/object is of complex type, the function returns
+// \a true if the imaginary part is equal to 0. Otherwise it returns \a false.
+
+ \code
+ int i = 1; // isReal( i ) returns true
+ double d = 1.0; // isReal( d ) returns true
+
+ complex<double> c1( 1.0, 0.0 ); // isReal( c1 ) returns true
+ complex<double> c2( 0.0, 1.0 ); // isReal( c2 ) returns false
+
+ blaze::DynamicVector<int> vec; // isReal( vec ) returns false
+ blaze::DynamicMatrix<double> mat; // isReal( mat ) returns false
+ \endcode
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE bool isReal( const Type& v ) noexcept
+{
+ UNUSED_PARAMETER( v );
+
+ return IsBuiltin<Type>::value;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Overload of the \a isReal function for complex data types.
+// \ingroup math_shims
+//
+// \param v The complex number to be tested.
+// \return \a true in case the imaginary part is equal to 0, \a false if not.
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE bool isReal( const complex<Type>& v ) noexcept( IsBuiltin<Type>::value )
+{
+ return IsBuiltin<Type>::value && isZero( v.imag() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/IsZero.h b/src/cpu/blaze/math/shims/IsZero.h
new file mode 100644
index 00000000..9207fa02
--- /dev/null
+++ b/src/cpu/blaze/math/shims/IsZero.h
@@ -0,0 +1,108 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/IsZero.h
+// \brief Header file for the isZero shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_ISZERO_H_
+#define _BLAZE_MATH_SHIMS_ISZERO_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/system/Inline.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ISZERO SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the given value/object represents the numeric value 0.
+// \ingroup math_shims
+//
+// \param v The value to be tested.
+// \return \a true in case the given value is 0, \a false otherwise.
+//
+// The \a isZero shim provides an abstract interface for testing a value/object of any type
+// whether it represents the numeric value 0. In case the value/object is 0, the function
+// returns \a true, otherwise it returns \a false.
+
+ \code
+ const int i1 = 0; // isZero( i1 ) returns true
+ double d1 = 0.0; // isZero( d1 ) returns true
+ complex<double> c1( 0.0, 0.0 ); // isZero( c1 ) returns true
+
+ const int i2 = 1; // isZero( i2 ) returns false
+ double d2 = -1.0; // isZero( d2 ) returns false
+ complex<double> c2( 1.0, 0.0 ); // isZero( c2 ) returns false
+ \endcode
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE EnableIf_< IsNumeric<Type>, bool > isZero( const Type& v ) noexcept
+{
+ return isDefault( v );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Overload of the \a isZero function for non-numeric data types.
+// \ingroup math_shims
+//
+// \param v The value/object to be tested.
+// \return \a false.
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE DisableIf_< IsNumeric<Type>, bool > isZero( const Type& v ) noexcept
+{
+ UNUSED_PARAMETER( v );
+
+ return false;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Log.h b/src/cpu/blaze/math/shims/Log.h
new file mode 100644
index 00000000..af2bd497
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Log.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Log.h
+// \brief Header file for the log shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_LOG_H_
+#define _BLAZE_MATH_SHIMS_LOG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LOG SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::log() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::log;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Log10.h b/src/cpu/blaze/math/shims/Log10.h
new file mode 100644
index 00000000..92113c0f
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Log10.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Log10.h
+// \brief Header file for the log10 shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_LOG10_H_
+#define _BLAZE_MATH_SHIMS_LOG10_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// LOG10 SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::log10() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::log10;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Pow.h b/src/cpu/blaze/math/shims/Pow.h
new file mode 100644
index 00000000..2561825f
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Pow.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Pow.h
+// \brief Header file for the pow shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_POW_H_
+#define _BLAZE_MATH_SHIMS_POW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// POW SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::pow() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::pow;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Real.h b/src/cpu/blaze/math/shims/Real.h
new file mode 100644
index 00000000..c9710ffe
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Real.h
@@ -0,0 +1,91 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Real.h
+// \brief Header file for the real shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_REAL_H_
+#define _BLAZE_MATH_SHIMS_REAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// REAL SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Computing the real part of the given value/object.
+// \ingroup math_shims
+//
+// \param a The given value/object.
+// \return The real part of the given value.
+//
+// The \a real shim represents an abstract interface for the computation of the real part of
+// any given data type. In case the given value is of complex type the function returns the
+// real part:
+
+ \code
+ const blaze::complex<double> a( 3.0, -2.0 );
+ const double b( real( a ) ); // Results in 3.0
+ \endcode
+
+// Values of built-in data type are considered complex numbers with an imaginary part of 0. Thus
+// the returned value corresponds to the given value:
+
+ \code
+ const double a( -3.0 );
+ const double b( real( a ) ); // Results in -3.0
+ \endcode
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE constexpr EnableIf_< IsBuiltin<T>, T > real( T a ) noexcept
+{
+ return a;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Reset.h b/src/cpu/blaze/math/shims/Reset.h
new file mode 100644
index 00000000..99fc5fee
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Reset.h
@@ -0,0 +1,73 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Reset.h
+// \brief Header file for the reset shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_RESET_H_
+#define _BLAZE_MATH_SHIMS_RESET_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RESET SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Resetting the given value/object to the default value.
+// \ingroup math_shims
+//
+// \param resettable The value/object to be resetted.
+// \return void
+//
+// The \a reset shim represents an abstract interface for the resetting of a value/object of
+// any given data type to its default value. Values of built-in data type are reset to zero.
+*/
+template< typename Type >
+BLAZE_ALWAYS_INLINE void reset( Type& resettable )
+{
+ resettable = Type(0);
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Serial.h b/src/cpu/blaze/math/shims/Serial.h
new file mode 100644
index 00000000..cce9a1b5
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Serial.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Serial.h
+// \brief Header file for the serial shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_SERIAL_H_
+#define _BLAZE_MATH_SHIMS_SERIAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SERIAL SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Formal serialization of the evaluation of the given argument.
+// \ingroup math_shims
+//
+// \param a The value/object to be evaluated serially.
+// \return The serialized operation.
+//
+// The \a serial shim represents an abstract interface for the serialization of the evaluation of
+// a value/object of any given data type. For data types that are per default evaluated serially,
+// as for instance built-in data types, the default behavior is not changed.
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE constexpr EnableIf_< Or< IsBuiltin<T>, IsComplex<T> >, const T& >
+ serial( const T& a ) noexcept
+{
+ return a;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Shims.h b/src/cpu/blaze/math/shims/Shims.h
new file mode 100644
index 00000000..2ad60fb7
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Shims.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Shims.h
+// \brief Mathematical shims module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_SHIMS_H_
+#define _BLAZE_MATH_SHIMS_SHIMS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup math_shims Shims
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Sin.h b/src/cpu/blaze/math/shims/Sin.h
new file mode 100644
index 00000000..6333dad6
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Sin.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Sin.h
+// \brief Header file for the sin shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_SIN_H_
+#define _BLAZE_MATH_SHIMS_SIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SIN SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::sin() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::sin;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Sinh.h b/src/cpu/blaze/math/shims/Sinh.h
new file mode 100644
index 00000000..6d98afdd
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Sinh.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Sinh.h
+// \brief Header file for the sinh shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_SINH_H_
+#define _BLAZE_MATH_SHIMS_SINH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SINH SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::sinh() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::sinh;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Sqrt.h b/src/cpu/blaze/math/shims/Sqrt.h
new file mode 100644
index 00000000..a76627e0
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Sqrt.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Sqrt.h
+// \brief Header file for the sqrt shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_SQRT_H_
+#define _BLAZE_MATH_SHIMS_SQRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SQRT SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::sqrt() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::sqrt;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Square.h b/src/cpu/blaze/math/shims/Square.h
new file mode 100644
index 00000000..0f7180d0
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Square.h
@@ -0,0 +1,75 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Square.h
+// \brief Header file for the square shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_SQUARE_H_
+#define _BLAZE_MATH_SHIMS_SQUARE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/MultExprTrait.h>
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SQUARE SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Squaring the given value/object.
+// \ingroup math_shims
+//
+// \param a The value/object to be squared.
+// \return The result of the square operation.
+//
+// The \a sq shim represents an abstract interface for squaring a value/object of any given
+// data type. For values of built-in data type this results in a plain multiplication.
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE constexpr MultExprTrait_<T,T> sq( const T& a )
+ noexcept( noexcept( a * a ) )
+{
+ return a * a;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Tan.h b/src/cpu/blaze/math/shims/Tan.h
new file mode 100644
index 00000000..a7f6c666
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Tan.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Tan.h
+// \brief Header file for the tan shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_TAN_H_
+#define _BLAZE_MATH_SHIMS_TAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// TAN SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::tan() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::tan;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/shims/Tanh.h b/src/cpu/blaze/math/shims/Tanh.h
new file mode 100644
index 00000000..6924474e
--- /dev/null
+++ b/src/cpu/blaze/math/shims/Tanh.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/shims/Tanh.h
+// \brief Header file for the tanh shim
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SHIMS_TANH_H_
+#define _BLAZE_MATH_SHIMS_TANH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// TANH SHIM
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Import of the std::tanh() function into the Blaze namespace.
+// \ingroup math_shims
+*/
+using std::tanh;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Abs.h b/src/cpu/blaze/math/simd/Abs.h
new file mode 100644
index 00000000..85706012
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Abs.h
@@ -0,0 +1,177 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Abs.h
+// \brief Header file for the SIMD abs functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ABS_H_
+#define _BLAZE_MATH_SIMD_ABS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Absolute value of a vector of 8-bit signed integral values.
+// \ingroup simd
+//
+// \param a The vector of 8-bit unsigned integral values.
+// \return The absolute values.
+//
+// This operation is only available for SSSE3, AVX2, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDuint8 abs( const SIMDint8& a ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_abs_epi8( a.value );
+}
+#elif BLAZE_SSSE3_MODE
+{
+ return _mm_abs_epi8( a.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Absolute value of a vector of 16-bit signed integral values.
+// \ingroup simd
+//
+// \param a The vector of 16-bit unsigned integral values.
+// \return The absolute values.
+//
+// This operation is only available for SSSE3, AVX2, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDuint16 abs( const SIMDint16& a ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_abs_epi16( a.value );
+}
+#elif BLAZE_SSSE3_MODE
+{
+ return _mm_abs_epi16( a.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Absolute value of a vector of 32-bit signed integral values.
+// \ingroup simd
+//
+// \param a The vector of 32-bit unsigned integral values.
+// \return The absolute values.
+//
+// This operation is only available for SSSE3, AVX2, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDuint32 abs( const SIMDint32& a ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_abs_epi32( a.value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_abs_epi32( a.value );
+}
+#elif BLAZE_SSSE3_MODE
+{
+ return _mm_abs_epi32( a.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Absolute value of a vector of 64-bit signed integral values.
+// \ingroup simd
+//
+// \param a The vector of 64-bit unsigned integral values.
+// \return The absolute values.
+//
+// This operation is only available for AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDuint64 abs( const SIMDint64& a ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_abs_epi64( a.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Acos.h b/src/cpu/blaze/math/simd/Acos.h
new file mode 100644
index 00000000..473e3851
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Acos.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Acos.h
+// \brief Header file for the SIMD inverse cosine functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ACOS_H_
+#define _BLAZE_MATH_SIMD_ACOS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse cosine of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values \f$[-1..1]\f$.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat acos( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_acos_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_acos_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_acos_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse cosine of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values \f$[-1..1]\f$.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble acos( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_acos_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_acos_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_acos_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Acosh.h b/src/cpu/blaze/math/simd/Acosh.h
new file mode 100644
index 00000000..8f7f65a7
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Acosh.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Acosh.h
+// \brief Header file for the SIMD inverse hyperbolic cosine functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ACOSH_H_
+#define _BLAZE_MATH_SIMD_ACOSH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse hyperbolic cosine of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values \f$[1..\infty)\f$.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat acosh( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_acosh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_acosh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_acosh_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse hyperbolic cosine of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values \f$[1..\infty)\f$.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble acosh( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_acosh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_acosh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_acosh_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Addition.h b/src/cpu/blaze/math/simd/Addition.h
new file mode 100644
index 00000000..898ed74b
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Addition.h
@@ -0,0 +1,573 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Addition.h
+// \brief Header file for the SIMD addition functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ADDITION_H_
+#define _BLAZE_MATH_SIMD_ADDITION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 8-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator+( const SIMDi8<T>& a, const SIMDi8<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi8( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi8( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 8-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint8
+ operator+( const SIMDi8<T1>& a, const SIMDi8<T2>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi8( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi8( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 8-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator+( const SIMDci8<T>& a, const SIMDci8<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi8( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi8( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 16-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator+( const SIMDi16<T>& a, const SIMDi16<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 16-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint16
+ operator+( const SIMDi16<T1>& a, const SIMDi16<T2>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 16-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator+( const SIMDci16<T>& a, const SIMDci16<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 32-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator+( const SIMDi32<T>& a, const SIMDi32<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 32-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint32
+ operator+( const SIMDi32<T1>& a, const SIMDi32<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 32-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator+( const SIMDci32<T>& a, const SIMDci32<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64 SIMD TYPES INTEGRAL
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 64-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T > // Type of the left-hand side operand
+BLAZE_ALWAYS_INLINE const T
+ operator+( const SIMDi64<T>& a, const SIMDi64<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi64( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 64-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint64
+ operator+( const SIMDi64<T1>& a, const SIMDi64<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi64( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of 64-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator+( const SIMDci64<T>& a, const SIMDci64<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_add_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_epi64( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of single precision floating point SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDfloat
+ operator+( const SIMDf32<T1>& a, const SIMDf32<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_ps( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_add_ps( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_add_ps( (~a).eval().value, (~b).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of single precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat
+ operator+( const SIMDcfloat& a, const SIMDcfloat& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_ps( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_add_ps( a.value, b.value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_add_ps( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of double precision floating point SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDdouble
+ operator+( const SIMDf64<T1>& a, const SIMDf64<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_pd( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_add_pd( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_pd( (~a).eval().value, (~b).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition of two vectors of double precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the addition.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble
+ operator+( const SIMDcdouble& a, const SIMDcdouble& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_add_pd( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_add_pd( a.value, b.value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_add_pd( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Asin.h b/src/cpu/blaze/math/simd/Asin.h
new file mode 100644
index 00000000..91cf5925
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Asin.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Asin.h
+// \brief Header file for the SIMD inverse sine functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ASIN_H_
+#define _BLAZE_MATH_SIMD_ASIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse sine of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values \f$[-1..1]\f$.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat asin( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_asin_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_asin_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_asin_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse sine of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values \f$[-1..1]\f$.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble asin( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_asin_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_asin_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_asin_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Asinh.h b/src/cpu/blaze/math/simd/Asinh.h
new file mode 100644
index 00000000..232eec46
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Asinh.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Asinh.h
+// \brief Header file for the SIMD inverse hyperbolic sine functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ASINH_H_
+#define _BLAZE_MATH_SIMD_ASINH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse hyperbolic sine of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat asinh( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_asinh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_asinh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_asinh_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse hyperbolic sine of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble asinh( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_asinh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_asinh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_asinh_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Atan.h b/src/cpu/blaze/math/simd/Atan.h
new file mode 100644
index 00000000..74c5a671
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Atan.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Atan.h
+// \brief Header file for the SIMD inverse tangent functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ATAN_H_
+#define _BLAZE_MATH_SIMD_ATAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse tangent of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat atan( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_atan_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_atan_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_atan_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse tangent of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble atan( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_atan_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_atan_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_atan_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Atanh.h b/src/cpu/blaze/math/simd/Atanh.h
new file mode 100644
index 00000000..632879c6
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Atanh.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Atanh.h
+// \brief Header file for the SIMD inverse hyperbolic tangent functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ATANH_H_
+#define _BLAZE_MATH_SIMD_ATANH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse hyperbolic tangent of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values \f$[-1..1]\f$.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat atanh( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_atanh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_atanh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_atanh_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inverse hyperbolic tangent of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values \f$[-1..1]\f$.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble atanh( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_atanh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_atanh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_atanh_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/BasicTypes.h b/src/cpu/blaze/math/simd/BasicTypes.h
new file mode 100644
index 00000000..4a5f7f98
--- /dev/null
+++ b/src/cpu/blaze/math/simd/BasicTypes.h
@@ -0,0 +1,1348 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/BasicTypes.h
+// \brief Header file for the basic SIMD types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_BASICTYPES_H_
+#define _BLAZE_MATH_SIMD_BASICTYPES_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/SIMDPack.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDi8
+// \brief Base class for all 8-bit integral SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDi8 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDint8
+// \brief SIMD type for 8-bit signed integral data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDint8 : public SIMDi8< SIMDint8 >
+{
+ using This = SIMDint8;
+ using BaseType = SIMDi8<This>;
+ using ValueType = int8_t;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDint8() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDint8() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 32UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDint8() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDint8() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDint8( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDint8( const SIMDi8<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDint8& operator=( const SIMDi8<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDuint8
+// \brief SIMD type for 8-bit unsigned integral data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDuint8 : public SIMDi8< SIMDuint8 >
+{
+ using This = SIMDuint8;
+ using BaseType = SIMDi8<This>;
+ using ValueType = uint8_t;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDuint8() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDuint8() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 32UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDuint8() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDuint8() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDuint8( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDuint8( const SIMDi8<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDuint8& operator=( const SIMDi8<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL COMPLEX SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDci8
+// \brief Base class for all 8-bit integral complex SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDci8 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcint8
+// \brief SIMD type for 8-bit signed integral complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcint8 : public SIMDci8< SIMDcint8 >
+{
+ using This = SIMDcint8;
+ using BaseType = SIMDci8<This>;
+ using ValueType = complex<int8_t>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcint8() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDcint8() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDcint8() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcint8() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcint8( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcint8( const SIMDci8<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcint8& operator=( const SIMDci8<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcuint8
+// \brief SIMD type for 8-bit unsigned integral complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcuint8 : public SIMDci8< SIMDcuint8 >
+{
+ using This = SIMDcuint8;
+ using BaseType = SIMDci8<This>;
+ using ValueType = complex<uint8_t>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcuint8() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDcuint8() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDcuint8() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcuint8() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcuint8( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcuint8( const SIMDci8<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcuint8& operator=( const SIMDci8<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDi16
+// \brief Base class for all 16-bit integral SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDi16 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDint16
+// \brief SIMD type for 16-bit signed integral data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDint16 : public SIMDi16< SIMDint16 >
+{
+ using This = SIMDint16;
+ using BaseType = SIMDi16<This>;
+ using ValueType = int16_t;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDint16() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDint16() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDint16() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDint16() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDint16( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDint16( const SIMDi16<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDint16& operator=( const SIMDi16<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDuint16
+// \brief SIMD type for 16-bit unsigned integral data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDuint16 : public SIMDi16< SIMDuint16 >
+{
+ using This = SIMDuint16;
+ using BaseType = SIMDi16<This>;
+ using ValueType = uint16_t;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDuint16() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDuint16() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDuint16() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDuint16() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDuint16( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDuint16( const SIMDi16<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDuint16& operator=( const SIMDi16<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL COMPLEX SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDci16
+// \brief Base class for all 16-bit integral complex SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDci16 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcint16
+// \brief SIMD type for 16-bit signed integral complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcint16 : public SIMDci16< SIMDcint16 >
+{
+ using This = SIMDcint16;
+ using BaseType = SIMDci16<This>;
+ using ValueType = complex<int16_t>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcint16() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDcint16() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDcint16() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcint16() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcint16( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcint16( const SIMDci16<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcint16& operator=( const SIMDci16<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcuint16
+// \brief SIMD type for 16-bit unsigned integral complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcuint16 : public SIMDci16< SIMDcuint16 >
+{
+ using This = SIMDcuint16;
+ using BaseType = SIMDci16<This>;
+ using ValueType = complex<uint16_t>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcuint16() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDcuint16() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDcuint16() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcuint16() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcuint16( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcuint16( const SIMDci16<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcuint16& operator=( const SIMDci16<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDi32
+// \brief Base class for all 32-bit integral SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDi32 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDint32
+// \brief SIMD type for 32-bit signed integral data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDint32 : public SIMDi32< SIMDint32 >
+{
+ using This = SIMDint32;
+ using BaseType = SIMDi32<This>;
+ using ValueType = int32_t;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512i;
+ BLAZE_ALWAYS_INLINE SIMDint32() noexcept : value( _mm512_setzero_epi32() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDint32() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDint32() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDint32() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDint32( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDint32( const SIMDi32<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDint32& operator=( const SIMDi32<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDuint32
+// \brief SIMD type for 32-bit unsigned integral data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDuint32 : public SIMDi32< SIMDuint32 >
+{
+ using This = SIMDuint32;
+ using BaseType = SIMDi32<This>;
+ using ValueType = uint32_t;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512i;
+ BLAZE_ALWAYS_INLINE SIMDuint32() noexcept : value( _mm512_setzero_epi32() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDuint32() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDuint32() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDuint32() noexcept : value( 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDuint32( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDuint32( const SIMDi32<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDuint32& operator=( const SIMDi32<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL COMPLEX SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDci32
+// \brief Base class for all 32-bit integral complex SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDci32 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcint32
+// \brief SIMD type for 32-bit signed integral complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcint32 : public SIMDci32< SIMDcint32 >
+{
+ using This = SIMDcint32;
+ using BaseType = SIMDci32<This>;
+ using ValueType = complex<int32_t>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512i;
+ BLAZE_ALWAYS_INLINE SIMDcint32() noexcept : value( _mm512_setzero_epi32() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDcint32() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDcint32() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcint32() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcint32( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcint32( const SIMDci32<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcint32& operator=( const SIMDci32<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcuint32
+// \brief SIMD type for 32-bit unsigned integral complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcuint32 : public SIMDci32< SIMDcuint32 >
+{
+ using This = SIMDcuint32;
+ using BaseType = SIMDci32<This>;
+ using ValueType = complex<uint32_t>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512i;
+ BLAZE_ALWAYS_INLINE SIMDcuint32() noexcept : value( _mm512_setzero_epi32() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDcuint32() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDcuint32() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcuint32() noexcept : value( 0, 0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcuint32( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcuint32( const SIMDci32<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcuint32& operator=( const SIMDci32<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDi64
+// \brief Base class for all 64-bit integral SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDi64 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDint64
+// \brief SIMD type for 64-bit integral data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDint64 : public SIMDi64< SIMDint64 >
+{
+ using This = SIMDint64;
+ using BaseType = SIMDi64<This>;
+ using ValueType = int64_t;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512i;
+ BLAZE_ALWAYS_INLINE SIMDint64() noexcept : value( _mm512_setzero_epi32() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDint64() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDint64() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDint64() noexcept : value( 0L ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDint64( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDint64( const SIMDi64<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDint64& operator=( const SIMDi64<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDuint64
+// \brief SIMD type for 64-bit unsigned integral data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDuint64 : public SIMDi64< SIMDuint64 >
+{
+ using This = SIMDuint64;
+ using BaseType = SIMDi64<This>;
+ using ValueType = uint64_t;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512i;
+ BLAZE_ALWAYS_INLINE SIMDuint64() noexcept : value( _mm512_setzero_epi32() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDuint64() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDuint64() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDuint64() noexcept : value( 0L ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDuint64( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDuint64( const SIMDi64<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDuint64& operator=( const SIMDi64<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL COMPLEX SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDci64
+// \brief Base class for all 64-bit integral complex SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDci64 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcint64
+// \brief SIMD type for 64-bit signed integral complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcint64 : public SIMDci64< SIMDcint64 >
+{
+ using This = SIMDcint64;
+ using BaseType = SIMDci64<This>;
+ using ValueType = complex<int64_t>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512i;
+ BLAZE_ALWAYS_INLINE SIMDcint64() noexcept : value( _mm512_setzero_epi32() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDcint64() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDcint64() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 1UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcint64() noexcept : value( 0L, 0L ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcint64( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcint64( const SIMDci64<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcint64& operator=( const SIMDci64<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcuint64
+// \brief SIMD type for 64-bit unsigned integral complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcuint64 : public SIMDci64< SIMDcuint64 >
+{
+ using This = SIMDcuint64;
+ using BaseType = SIMDci64<This>;
+ using ValueType = complex<uint64_t>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512i;
+ BLAZE_ALWAYS_INLINE SIMDcuint64() noexcept : value( _mm512_setzero_epi32() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_AVX2_MODE
+ using IntrinsicType = __m256i;
+ BLAZE_ALWAYS_INLINE SIMDcuint64() noexcept : value( _mm256_setzero_si256() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128i;
+ BLAZE_ALWAYS_INLINE SIMDcuint64() noexcept : value( _mm_setzero_si128() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 1UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcuint64() noexcept : value( 0L, 0L ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcuint64( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcuint64( const SIMDci64<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcuint64& operator=( const SIMDci64<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLE PRECISION FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDf32
+// \brief Base class for all single precision floating point SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDf32 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDfloat
+// \brief SIMD type for 32-bit single precision floating point data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDfloat : public SIMDf32< SIMDfloat >
+{
+ using This = SIMDfloat;
+ using BaseType = SIMDf32<This>;
+ using ValueType = float;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512;
+ BLAZE_ALWAYS_INLINE SIMDfloat() noexcept : value( _mm512_setzero_ps() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 16UL };
+#elif BLAZE_AVX_MODE
+ using IntrinsicType = __m256;
+ BLAZE_ALWAYS_INLINE SIMDfloat() noexcept : value( _mm256_setzero_ps() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_SSE_MODE
+ using IntrinsicType = __m128;
+ BLAZE_ALWAYS_INLINE SIMDfloat() noexcept : value( _mm_setzero_ps() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDfloat() noexcept : value( 0.0F ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDfloat( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDfloat( const SIMDf32<T>& v ) noexcept : value( (~v).eval().value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDfloat& operator=( const SIMDf32<T>& v ) noexcept { value = (~v).eval().value; return *this; }
+
+ BLAZE_ALWAYS_INLINE const This& eval() const { return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLE PRECISION FLOATING POINT COMPLEX SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDcf32
+// \brief Base class for all single precision floating point complex SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDcf32 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcfloat
+// \brief SIMD type for 32-bit single precision complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcfloat : public SIMDcf32< SIMDcfloat >
+{
+ using This = SIMDcfloat;
+ using BaseType = SIMDcf32<This>;
+ using ValueType = complex<float>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512;
+ BLAZE_ALWAYS_INLINE SIMDcfloat() noexcept : value( _mm512_setzero_ps() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_AVX_MODE
+ using IntrinsicType = __m256;
+ BLAZE_ALWAYS_INLINE SIMDcfloat() noexcept : value( _mm256_setzero_ps() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_SSE_MODE
+ using IntrinsicType = __m128;
+ BLAZE_ALWAYS_INLINE SIMDcfloat() noexcept : value( _mm_setzero_ps() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcfloat() noexcept : value( 0.0F, 0.0F ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcfloat( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcfloat( const SIMDcf32<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcfloat& operator=( const SIMDcf32<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DOUBLE PRECISION FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDf64
+// \brief Base class for all double precision floating point SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDf64 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDdouble
+// \brief SIMD type for 64-bit double precision floating point data values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDdouble : public SIMDf64< SIMDdouble >
+{
+ using This = SIMDdouble;
+ using BaseType = SIMDf64<This>;
+ using ValueType = double;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512d;
+ BLAZE_ALWAYS_INLINE SIMDdouble() noexcept : value( _mm512_setzero_pd() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 8UL };
+#elif BLAZE_AVX_MODE
+ using IntrinsicType = __m256d;
+ BLAZE_ALWAYS_INLINE SIMDdouble() noexcept : value( _mm256_setzero_pd() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128d;
+ BLAZE_ALWAYS_INLINE SIMDdouble() noexcept : value( _mm_setzero_pd() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDdouble() noexcept : value( 0.0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDdouble( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDdouble( const SIMDf64<T>& v ) noexcept : value( (~v).eval().value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDdouble& operator=( const SIMDf64<T>& v ) noexcept { value = (~v).eval().value; return *this; }
+
+ BLAZE_ALWAYS_INLINE const This& eval() const { return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DOUBLE PRECISION FLOATING POINT COMPLEX SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*\class blaze::SIMDcf64
+// \brief Base class for all double precision floating point complex SIMD data types.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+template< typename T > // Type of the SIMD element
+struct SIMDcf64 : public SIMDPack< T >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::SIMDcdouble
+// \brief SIMD type for 64-bit double precision complex values.
+// \ingroup simd
+*/
+/*! \cond BLAZE_INTERNAL */
+struct SIMDcdouble : public SIMDcf64< SIMDcdouble >
+{
+ using This = SIMDcdouble;
+ using BaseType = SIMDcf64<This>;
+ using ValueType = complex<double>;
+
+#if BLAZE_MIC_MODE
+ using IntrinsicType = __m512d;
+ BLAZE_ALWAYS_INLINE SIMDcdouble() noexcept : value( _mm512_setzero_pd() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 4UL };
+#elif BLAZE_AVX_MODE
+ using IntrinsicType = __m256d;
+ BLAZE_ALWAYS_INLINE SIMDcdouble() noexcept : value( _mm256_setzero_pd() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 2UL };
+#elif BLAZE_SSE2_MODE
+ using IntrinsicType = __m128d;
+ BLAZE_ALWAYS_INLINE SIMDcdouble() noexcept : value( _mm_setzero_pd() ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t i ) const noexcept { return reinterpret_cast<const ValueType*>( &value )[i]; }
+ enum : size_t { size = 1UL };
+#else
+ using IntrinsicType = ValueType;
+ BLAZE_ALWAYS_INLINE SIMDcdouble() noexcept : value( 0.0, 0.0 ) {}
+ BLAZE_ALWAYS_INLINE ValueType operator[]( size_t /*i*/ ) const noexcept { return value; }
+ enum : size_t { size = 1UL };
+#endif
+
+ BLAZE_ALWAYS_INLINE SIMDcdouble( IntrinsicType v ) noexcept : value( v ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcdouble( const SIMDcf64<T>& v ) noexcept : value( (~v).value ) {}
+
+ template< typename T >
+ BLAZE_ALWAYS_INLINE SIMDcdouble& operator=( const SIMDcf64<T>& v ) noexcept { value = (~v).value; return *this; }
+
+ IntrinsicType value;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIMD OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of two SIMD packs.
+// \ingroup simd
+//
+// \param lhs The left-hand side SIMD operand for the addition.
+// \param rhs The right-hand side SIMD operand for the addition.
+// \return Reference to the left-hand side SIMD operand.
+*/
+template< typename T1 // Type of the left-hand side SIMD operand
+ , typename T2 > // Type of the right-hand side SIMD operand
+BLAZE_ALWAYS_INLINE T1& operator+=( SIMDPack<T1>& lhs, const SIMDPack<T2>& rhs )
+{
+ (~lhs) = (~lhs) + (~rhs);
+ return ~lhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of two SIMD packs.
+// \ingroup simd
+//
+// \param lhs The left-hand side SIMD operand for the subtraction.
+// \param rhs The right-hand side SIMD operand for the subtraction.
+// \return Reference to the left-hand side SIMD operand.
+*/
+template< typename T1 // Type of the left-hand side SIMD operand
+ , typename T2 > // Type of the right-hand side SIMD operand
+BLAZE_ALWAYS_INLINE T1& operator-=( SIMDPack<T1>& lhs, const SIMDPack<T2>& rhs )
+{
+ (~lhs) = (~lhs) - (~rhs);
+ return ~lhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of two SIMD packs.
+// \ingroup simd
+//
+// \param lhs The left-hand side SIMD operand for the multiplication.
+// \param rhs The right-hand side SIMD operand for the multiplication.
+// \return Reference to the left-hand side SIMD operand.
+*/
+template< typename T1 // Type of the left-hand side SIMD operand
+ , typename T2 > // Type of the right-hand side SIMD operand
+BLAZE_ALWAYS_INLINE T1& operator*=( SIMDPack<T1>& lhs, const SIMDPack<T2>& rhs )
+{
+ (~lhs) = (~lhs) * (~rhs);
+ return ~lhs;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of two SIMD packs.
+// \ingroup simd
+//
+// \param lhs The left-hand side SIMD operand for the division.
+// \param rhs The right-hand side SIMD operand for the division.
+// \return Reference to the left-hand side SIMD operand.
+*/
+template< typename T1 // Type of the left-hand side SIMD operand
+ , typename T2 > // Type of the right-hand side SIMD operand
+BLAZE_ALWAYS_INLINE T1& operator/=( SIMDPack<T1>& lhs, const SIMDPack<T2>& rhs )
+{
+ (~lhs) = (~lhs) / (~rhs);
+ return ~lhs;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Cbrt.h b/src/cpu/blaze/math/simd/Cbrt.h
new file mode 100644
index 00000000..306f4810
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Cbrt.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Cbrt.h
+// \brief Header file for the SIMD cubit root functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_CBRT_H_
+#define _BLAZE_MATH_SIMD_CBRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the cubic root for a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat cbrt( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_cbrt_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_cbrt_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_cbrt_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the cubic root for a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble cbrt( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_cbrt_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_cbrt_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_cbrt_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Ceil.h b/src/cpu/blaze/math/simd/Ceil.h
new file mode 100644
index 00000000..1237703c
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Ceil.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Ceil.h
+// \brief Header file for the SIMD ceil functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_CEIL_H_
+#define _BLAZE_MATH_SIMD_CEIL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the largest integer value not less than the given value for a vector of single
+// precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat ceil( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_ceil_ps( (~a).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_ceil_ps( (~a).eval().value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_ceil_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the largest integer value not less than the given value for a vector of double
+// precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble ceil( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_ceil_pd( (~a).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_ceil_pd( (~a).eval().value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_ceil_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Conj.h b/src/cpu/blaze/math/simd/Conj.h
new file mode 100644
index 00000000..da93b3c6
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Conj.h
@@ -0,0 +1,298 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Conj.h
+// \brief Header file for the SIMD conj functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_CONJ_H_
+#define _BLAZE_MATH_SIMD_CONJ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of 8-bit integral values.
+// \ingroup simd
+//
+// \param a The vector of 8-bit integral values.
+// \return The complex conjugate values.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const T conj( const SIMDi8<T>& a ) noexcept
+{
+ return a;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of 16-bit integral values.
+// \ingroup simd
+//
+// \param a The vector of 16-bit integral values.
+// \return The complex conjugate values.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const T conj( const SIMDi16<T>& a ) noexcept
+{
+ return a;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of 16-bit integral complex values.
+// \ingroup simd
+//
+// \param a The vector of 16-bit integral complex values.
+// \return The complex conjugate values.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcint16 conj( const SIMDcint16& a ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi16( a.value, _mm256_set_epi16( -1, 1, -1, 1, -1, 1, -1, 1,
+ -1, 1, -1, 1, -1, 1, -1, 1 ) );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mullo_epi16( a.value, _mm_set_epi16( -1, 1, -1, 1, -1, 1, -1, 1 ) );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of 32-bit integral values.
+// \ingroup simd
+//
+// \param a The vector of 32-bit integral values.
+// \return The complex conjugate values.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const T conj( const SIMDi32<T>& a ) noexcept
+{
+ return a;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of 32-bit integral complex values.
+// \ingroup simd
+//
+// \param a The vector of 32-bit integral complex values.
+// \return The complex conjugate values.
+//
+// This operation is only available for SSE4, AVX2, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcint32 conj( const SIMDcint32& a ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mullo_epi32( a.value, _mm512_set_epi32( -1, 1, -1, 1, -1, 1, -1, 1,
+ -1, 1, -1, 1, -1, 1, -1, 1 ) );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi32( a.value, _mm256_set_epi32( -1, 1, -1, 1, -1, 1, -1, 1 ) );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_mullo_epi32( a.value, _mm_set_epi32( -1, 1, -1, 1 ) );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of 64-bit integral values.
+// \ingroup simd
+//
+// \param a The vector of 64-bit integral values.
+// \return The complex conjugate values.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const T conj( const SIMDi64<T>& a ) noexcept
+{
+ return a;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The complex conjugate values.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const T conj( const SIMDf32<T>& a ) noexcept
+{
+ return (~a);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of single precision complex values.
+// \ingroup simd
+//
+// \param a The vector of single precision complex values.
+// \return The complex conjugate values.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat conj( const SIMDcfloat& a ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mul_ps( a.value, _mm512_set_ps( -1.0F, 1.0F, -1.0F, 1.0F, -1.0F, 1.0F, -1.0F, 1.0F,
+ -1.0F, 1.0F, -1.0F, 1.0F, -1.0F, 1.0F, -1.0F, 1.0F ) );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_mul_ps( a.value, _mm256_set_ps( -1.0F, 1.0F, -1.0F, 1.0F, -1.0F, 1.0F, -1.0F, 1.0F ) );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mul_ps( a.value, _mm_set_ps( -1.0F, 1.0F, -1.0F, 1.0F ) );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The complex conjugate values.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const T conj( const SIMDf64<T>& a ) noexcept
+{
+ return (~a);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Complex conjugate of a vector of double precision complex values.
+// \ingroup simd
+//
+// \param a The vector of double precision complex values.
+// \return The complex conjugate values.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble conj( const SIMDcdouble& a ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mul_pd( a.value, _mm512_set_pd( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ) );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_mul_pd( a.value, _mm256_set_pd( -1.0, 1.0, -1.0, 1.0 ) );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mul_pd( a.value, _mm_set_pd( -1.0, 1.0 ) );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Cos.h b/src/cpu/blaze/math/simd/Cos.h
new file mode 100644
index 00000000..bfe7d8aa
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Cos.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Cos.h
+// \brief Header file for the SIMD cosine functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_COS_H_
+#define _BLAZE_MATH_SIMD_COS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Cosine of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat cos( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_cos_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_cos_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_cos_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Cosine of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble cos( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_cos_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_cos_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_cos_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Cosh.h b/src/cpu/blaze/math/simd/Cosh.h
new file mode 100644
index 00000000..d8b241d7
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Cosh.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Cosh.h
+// \brief Header file for the SIMD hyperbolic cosine functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_COSH_H_
+#define _BLAZE_MATH_SIMD_COSH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Hyperbolic cosine of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat cosh( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_cosh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_cosh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_cosh_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Hyperbolic cosine of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble cosh( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_cosh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_cosh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_cosh_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/DerivedTypes.h b/src/cpu/blaze/math/simd/DerivedTypes.h
new file mode 100644
index 00000000..c4342e76
--- /dev/null
+++ b/src/cpu/blaze/math/simd/DerivedTypes.h
@@ -0,0 +1,216 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/DerivedTypes.h
+// \brief Header file for the derived SIMD types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_DERIVEDTYPES_H_
+#define _BLAZE_MATH_SIMD_DERIVEDTYPES_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/SIMDTrait.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DERIVED SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'char'.
+// \ingroup simd
+*/
+typedef SIMDTrait<char>::Type SIMDchar;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'signed char'.
+// \ingroup simd
+*/
+typedef SIMDTrait<signed char>::Type SIMDschar;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'unsigned char'.
+// \ingroup simd
+*/
+typedef SIMDTrait<unsigned char>::Type SIMDuchar;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'wchar_t'.
+// \ingroup simd
+*/
+typedef SIMDTrait<wchar_t>::Type SIMDwchar;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<char>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<char> >::Type SIMDcchar;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<signed char>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<signed char> >::Type SIMDcschar;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<unsigned char>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<unsigned char> >::Type SIMDcuchar;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<wchar_t>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<wchar_t> >::Type SIMDcwchar;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'short'.
+// \ingroup simd
+*/
+typedef SIMDTrait<short>::Type SIMDshort;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'unsigned short'.
+// \ingroup simd
+*/
+typedef SIMDTrait<unsigned short>::Type SIMDushort;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<short>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<short> >::Type SIMDcshort;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<unsigned short>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<unsigned short> >::Type SIMDcushort;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'int'.
+// \ingroup simd
+*/
+typedef SIMDTrait<int>::Type SIMDint;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'unsigned int'.
+// \ingroup simd
+*/
+typedef SIMDTrait<unsigned int>::Type SIMDuint;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<int>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<int> >::Type SIMDcint;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<unsigned int>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<unsigned int> >::Type SIMDcuint;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'long int'.
+// \ingroup simd
+*/
+typedef SIMDTrait<long>::Type SIMDlong;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'unsigned long int'.
+// \ingroup simd
+*/
+typedef SIMDTrait<unsigned long>::Type SIMDulong;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<long int>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<long> >::Type SIMDclong;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The SIMD data type for 'complex<unsigned long int>'.
+// \ingroup simd
+*/
+typedef SIMDTrait< complex<unsigned long> >::Type SIMDculong;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Division.h b/src/cpu/blaze/math/simd/Division.h
new file mode 100644
index 00000000..bfcbf7d9
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Division.h
@@ -0,0 +1,293 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Division.h
+// \brief Header file for the SIMD division functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_DIVISION_H_
+#define _BLAZE_MATH_SIMD_DIVISION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division of two vectors of 32-bit signed integral SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the division.
+//
+// This operation is only available for AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDint32
+ operator/( const SIMDint32& a, const SIMDint32& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_div_epi32( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 32-bit signed integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the division.
+//
+// This operation is only available for AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcint32
+ operator/( const SIMDcint32& a, const SIMDint32& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_div_epi32( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division of two vectors of 64-bit signed integral SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the division.
+//
+// This operation is only available for AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDint64
+ operator/( const SIMDint64& a, const SIMDint64& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_div_epi64( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 64-bit signed integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the division.
+//
+// This operation is only available for AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcint64
+ operator/( const SIMDcint64& a, const SIMDint64& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_div_epi64( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division of two vectors of single precision floating point SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the division.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDfloat
+ operator/( const SIMDf32<T1>& a, const SIMDf32<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_div_ps( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_div_ps( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_div_ps( (~a).eval().value, (~b).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of single precision floating point values complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the division.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat
+ operator/( const SIMDcfloat& a, const SIMDfloat& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_div_ps( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_div_ps( a.value, b.value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_div_ps( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Division of two vectors of double precision floating point SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the division.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDdouble
+ operator/( const SIMDf64<T1>& a, const SIMDf64<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_div_pd( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_div_pd( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_div_pd( (~a).eval().value, (~b).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of double precision floating point values complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the division.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble
+ operator/( const SIMDcdouble& a, const SIMDdouble& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_div_pd( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_div_pd( a.value, b.value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_div_pd( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Erf.h b/src/cpu/blaze/math/simd/Erf.h
new file mode 100644
index 00000000..0fb5c531
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Erf.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Erf.h
+// \brief Header file for the SIMD error function (erf) functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ERF_H_
+#define _BLAZE_MATH_SIMD_ERF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the error function for a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat erf( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_erf_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_erf_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_erf_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the error function for a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble erf( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_erf_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_erf_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_erf_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Erfc.h b/src/cpu/blaze/math/simd/Erfc.h
new file mode 100644
index 00000000..6ab898b2
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Erfc.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Erfc.h
+// \brief Header file for the SIMD complementary error function (erfc) functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_ERFC_H_
+#define _BLAZE_MATH_SIMD_ERFC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the complementary error function for a vector of single precision floating
+// point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat erfc( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_erfc_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_erfc_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_erfc_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the complementary error function for a vector of double precision floating
+// point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble erfc( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_erfc_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_erfc_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_erfc_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Exp.h b/src/cpu/blaze/math/simd/Exp.h
new file mode 100644
index 00000000..45fc04f0
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Exp.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Exp.h
+// \brief Header file for the SIMD exponent functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_EXP_H_
+#define _BLAZE_MATH_SIMD_EXP_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes \f$ e^x \f$ for a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat exp( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_exp_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_exp_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_exp_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes \f$ e^x \f$ for a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble exp( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_exp_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_exp_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_exp_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/FMA.h b/src/cpu/blaze/math/simd/FMA.h
new file mode 100644
index 00000000..e81838f8
--- /dev/null
+++ b/src/cpu/blaze/math/simd/FMA.h
@@ -0,0 +1,1476 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/FMA.h
+// \brief Header file for the SIMD fused multiply-add (FMA) functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_FMA_H_
+#define _BLAZE_MATH_SIMD_FMA_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/Addition.h>
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/math/simd/Multiplication.h>
+#include <blaze/math/simd/Subtraction.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for 32-bit floating point fused multiply-add operations.
+// \ingroup simd
+//
+// The SIMDf32FmaddExpr class represents the compile time expression for 32-bit floating point
+// fused multiply-add operations.
+*/
+template< typename T1 // Type of the left-hand side multiplication operand
+ , typename T2 // Type of the right-hand side multiplication operand
+ , typename T3 > // Type of the right-hand side addition operand
+struct SIMDf32FmaddExpr : public SIMDf32< SIMDf32FmaddExpr<T1,T2,T3> >
+{
+ //**Type definitions****************************************************************************
+ using This = SIMDf32FmaddExpr<T1,T2,T3>; //!< Type of this SIMDf32FMaddExpr instance.
+ using BaseType = SIMDf32<This>; //!< Base type of this SIMDf32FMaddExpr instance.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SIMDf32FmaddExpr class.
+ //
+ // \param a The left-hand side operand for the multiplication.
+ // \param b The right-hand side operand for the multiplication.
+ // \param c The right-hand side operand for the addition.
+ */
+ explicit BLAZE_ALWAYS_INLINE SIMDf32FmaddExpr( const T1& a, const T2& b, const T3& c )
+ : a_( a ) // The left-hand side operand for the multiplication
+ , b_( b ) // The right-hand side operand for the multiplication
+ , c_( c ) // The right-hand side operand for the addition
+ {}
+ //**********************************************************************************************
+
+ //**Evaluation function*************************************************************************
+ /*!\brief Evaluation of the expression object.
+ //
+ // \return The resulting packed 32-bit floating point value.
+ */
+ BLAZE_ALWAYS_INLINE const SIMDfloat eval() const noexcept
+#if BLAZE_FMA_MODE && BLAZE_MIC_MODE
+ {
+ return _mm512_fmadd_ps( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#elif BLAZE_FMA_MODE && BLAZE_AVX_MODE
+ {
+ return _mm256_fmadd_ps( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#elif BLAZE_FMA_MODE && BLAZE_SSE2_MODE
+ {
+ return _mm_fmadd_ps( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#else
+ = delete;
+#endif
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ const T1 a_; //!< The left-hand side operand for the multiplication.
+ const T2 b_; //!< The right-hand side operand for the multiplication.
+ const T3 c_; //!< The right-hand side operand for the addition.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Expression object for 32-bit floating point fused multiply-subtract operations.
+// \ingroup simd
+//
+// The SIMDf32FmsubExpr class represents the compile time expression for 32-bit floating point
+// fused multiply-subtract operations.
+*/
+template< typename T1 // Type of the left-hand side multiplication operand
+ , typename T2 // Type of the right-hand side multiplication operand
+ , typename T3 > // Type of the right-hand side subtraction operand
+struct SIMDf32FmsubExpr : public SIMDf32< SIMDf32FmsubExpr<T1,T2,T3> >
+{
+ //**Type definitions****************************************************************************
+ using This = SIMDf32MultExpr<T1,T2>; //!< Type of this SIMDf32FMsubExpr instance.
+ using BaseType = SIMDf32<This>; //!< Base type of this SIMDf32FMsubExpr instance.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SIMDf32FmsubExpr class.
+ //
+ // \param a The left-hand side operand for the multiplication.
+ // \param b The right-hand side operand for the multiplication.
+ // \param c The right-hand side operand for the subtraction.
+ */
+ explicit BLAZE_ALWAYS_INLINE SIMDf32FmsubExpr( const T1& a, const T2& b, const T3& c )
+ : a_( a ) // The left-hand side operand for the multiplication
+ , b_( b ) // The right-hand side operand for the multiplication
+ , c_( c ) // The right-hand side operand for the subtraction
+ {}
+ //**********************************************************************************************
+
+ //**Evaluation function*************************************************************************
+ /*!\brief Evaluation of the expression object.
+ //
+ // \return The resulting packed 32-bit floating point value.
+ */
+ BLAZE_ALWAYS_INLINE const SIMDfloat eval() const noexcept
+#if BLAZE_FMA_MODE && BLAZE_MIC_MODE
+ {
+ return _mm512_fmsub_ps( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#elif BLAZE_FMA_MODE && BLAZE_AVX_MODE
+ {
+ return _mm256_fmsub_ps( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#elif BLAZE_FMA_MODE && BLAZE_SSE2_MODE
+ {
+ return _mm_fmsub_ps( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#else
+ = delete;
+#endif
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ const T1 a_; //!< The left-hand side operand for the multiplication.
+ const T2 b_; //!< The right-hand side operand for the multiplication.
+ const T3 c_; //!< The right-hand side operand for the subtraction.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for fusing a 32-bit floating point multiplication and addition.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD addition operand.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 32-bit floating point multiplication with the addition of a 32-bit
+// floating point operand. It returns an expression representing the fused multiply-add (FMA)
+// operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand
+ , typename T2 // Type of the second multiplication operand
+ , typename T3 > // Type of the second addition operand
+BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr<T1,T2,T3>
+ operator+( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32<T3>& b )
+{
+ return SIMDf32FmaddExpr<T1,T2,T3>( a.a_, a.b_, ~b );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for fusing a 32-bit floating point multiplication and addition.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD addition operand.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 32-bit floating point multiplication with the addition of a 32-bit
+// floating point operand. It returns an expression representing the fused multiply-add (FMA)
+// operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first addition operand
+ , typename T2 // Type of the first multiplication operand
+ , typename T3 > // Type of the second multiplication operand
+BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr<T2,T3,T1>
+ operator+( const SIMDf32<T1>& a, const SIMDf32MultExpr<T2,T3>& b )
+{
+ return SIMDf32FmaddExpr<T2,T3,T1>( b.a_, b.b_, ~a );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for fusing a 32-bit floating point multiplication and addition.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 32-bit floating point multiplication with the addition of a 32-bit
+// floating point operand. It returns an expression representing the fused multiply-add (FMA)
+// operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first operand of the left-hand side multiplication
+ , typename T2 // Type of the second operand of the left-hand side multiplication
+ , typename T3 // Type of the first operand of the right-hand side multiplication
+ , typename T4 > // Type of the second operand of the right-hand side multiplication
+BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr< T1, T2, SIMDf32MultExpr<T3,T4> >
+ operator+( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32MultExpr<T3,T4>& b )
+{
+ return SIMDf32FmaddExpr< T1, T2, SIMDf32MultExpr<T3,T4> >( a.a_, a.b_, b );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of a 32-bit floating point FMA expression with
+// a 32-bit floating point operand.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD addition operand.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of a 32-bit floating
+// point FMA expression and a 32-bit floating point operand. It restructures the expression
+// \f$ (a*b+c) + d \f$ to the expression \f$ (a*b) + (c+d) \f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first FMA multiplication operand
+ , typename T2 // Type of the second FMA multiplication operand
+ , typename T3 // Type of the FMA addition operand
+ , typename T4 > // Type of the second addition operand
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32<T4>& b )
+{
+ return ( a.a_ * a.b_ ) + ( a.c_ + (~b) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of a 32-bit floating point operand with a
+// 32-bit floating point FMA expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD addition operand.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of a 32-bit floating
+// point operand and a 32-bit floating point FMA expression. It restructures the expression
+// \f$ a + (b*c+d) \f$ to the expression \f$ (b*c) + (d+a) \f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first addition operand
+ , typename T2 // Type of the first FMA multiplication operand
+ , typename T3 // Type of the second FMA multiplication operand
+ , typename T4 > // Type of the FMA addition operand
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf32<T1>& a, const SIMDf32FmaddExpr<T2,T3,T4>& b )
+{
+ return ( b.a_ * b.b_ ) + ( b.c_ + (~a) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of a 32-bit floating point FMA expression with
+// a 32-bit floating point multiplication expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of a 32-bit floating
+// point FMA expression and a 32-bit floating point multiplication expression. It restructures the
+// expression \f$ (a*b+c) + (d*e) \f$ to the expression \f$ (a*b) + (d*e+c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first FMA multiplication operand
+ , typename T2 // Type of the second FMA multiplication operand
+ , typename T3 // Type of the FMA addition operand
+ , typename T4 // Type of the first multiplication operand
+ , typename T5 > // Type of the second multiplication operand
+BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr< T4, T5, SIMDf32FmaddExpr<T1,T2,T3> >
+ operator+( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32MultExpr<T4,T5>& b )
+{
+ return SIMDf32FmaddExpr< T4, T5, SIMDf32FmaddExpr<T1,T2,T3> >( b.a_, b.b_, a );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of a 32-bit floating point multiplication
+// expression with a 32-bit floating point FMA expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of a 32-bit floating
+// point multiplication expression and a 32-bit floating point FMA expression. It restructures the
+// expression \f$ (a*b) + (c*d+e) \f$ to the expression \f$ (a*b) + (c*d+e)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand
+ , typename T2 // Type of the second multiplication operand
+ , typename T3 // Type of the first FMA multiplication operand
+ , typename T4 // Type of the second FMA multiplication operand
+ , typename T5 > // Type of the FMA addition operand
+BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr< T1, T2, SIMDf32FmaddExpr<T3,T4,T5> >
+ operator+( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32FmaddExpr<T3,T4,T5>& b )
+{
+ return SIMDf32FmaddExpr< T1, T2, SIMDf32FmaddExpr<T3,T4,T5> >( a.a_, a.b_, b );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of two 32-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of two 32-bit floating
+// point FMA expressions. It restructures the expression \f$ (a*b+c) + (d*e+f) \f$ to the expression
+// \f$ (a*b) + (d*e+c+f)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the addition operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the addition operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32FmaddExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( a.c_ + b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of two 32-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of two 32-bit floating
+// point FMA expressions. It restructures the expression \f$ (a*b+c) + (d*e-f) \f$ to the expression
+// \f$ (a*b) + (d*e+c-f)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the addition operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the subtraction operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32FmsubExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( a.c_ - b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of two 32-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of two 32-bit floating
+// point FMA expressions. It restructures the expression \f$ (a*b-c) + (d*e+f) \f$ to the expression
+// \f$ (a*b) + (d*e+f-c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the subtraction operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the addition operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32FmaddExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( b.c_ - a.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of two 32-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of two 32-bit floating
+// point FMA expressions. It restructures the expression \f$ (a*b-c) + (d*e-f) \f$ to the expression
+// \f$ (a*b) + (d*e-f-c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the subtraction operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the subtraction operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32FmsubExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) - ( b.c_ + a.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for fusing a 32-bit floating point multiplication and subtraction.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD subtraction operand.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 32-bit floating point multiplication with the subtraction of a 32-bit
+// floating point operand. It returns an expression representing the fused multiply-subtract
+// operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand
+ , typename T2 // Type of the second multiplication operand
+ , typename T3 > // Type of the second subtraction operand
+BLAZE_ALWAYS_INLINE const SIMDf32FmsubExpr<T1,T2,T3>
+ operator-( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32<T3>& b )
+{
+ return SIMDf32FmsubExpr<T1,T2,T3>( a.a_, a.b_, ~b );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for fusing a 32-bit floating point multiplication and subtraction.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 32-bit floating point multiplication with the subtraction of a 32-bit
+// floating point operand. It returns an expression representing the fused multiply-subtract
+// (FMA) operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first operand of the left-hand side multiplication
+ , typename T2 // Type of the second operand of the left-hand side multiplication
+ , typename T3 // Type of the first operand of the right-hand side multiplication
+ , typename T4 > // Type of the second operand of the right-hand side multiplication
+BLAZE_ALWAYS_INLINE const SIMDf32FmsubExpr< T1, T2, SIMDf32MultExpr<T3,T4> >
+ operator-( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32MultExpr<T3,T4>& b )
+{
+ return SIMDf32FmsubExpr< T1, T2, SIMDf32MultExpr<T3,T4> >( a.a_, a.b_, b );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of a 32-bit floating point FMA expression
+// with a 32-bit floating point operand.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD subtraction operand.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of a 32-bit
+// floating point FMA expression and a 32-bit floating point operand. It restructures the
+// expression \f$ (a*b+c) + d \f$ to the expression \f$ (a*b) + (c+d) \f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first FMA multiplication operand
+ , typename T2 // Type of the second FMA multiplication operand
+ , typename T3 // Type of the FMA subtraction operand
+ , typename T4 > // Type of the second subtraction operand
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32<T4>& b )
+{
+ return ( a.a_ * a.b_ ) - ( a.c_ + (~b) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of a 32-bit floating point FMA expression
+// with a 32-bit floating point multiplication expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of a 32-bit
+// floating point FMA expression and a 32-bit floating point multiplication expression. It
+// restructures the expression \f$ (a*b-c) - (d*e) \f$ to the expression \f$ (a*b) - (d*e+c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first FMA multiplication operand
+ , typename T2 // Type of the second FMA multiplication operand
+ , typename T3 // Type of the FMA subtraction operand
+ , typename T4 // Type of the first multiplication operand
+ , typename T5 > // Type of the second multiplication operand
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32MultExpr<T4,T5>& b )
+{
+ return ( a.a_ * a.b_ ) - ( b.a_ * b.b_ + a.c_ );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of a 32-bit floating point multiplication
+// expression with a 32-bit floating point FMA expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of a 32-bit
+// floating point multiplication expression and a 32-bit floating point FMA expression. It
+// restructures the expression \f$ (a*b) - (c*d+e) \f$ to the expression \f$ (a*b) - (c*d+e)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand
+ , typename T2 // Type of the second multiplication operand
+ , typename T3 // Type of the first FMA multiplication operand
+ , typename T4 // Type of the second FMA multiplication operand
+ , typename T5 > // Type of the FMA subtraction operand
+BLAZE_ALWAYS_INLINE const SIMDf32FmsubExpr< T1, T2, SIMDf32FmsubExpr<T3,T4,T5> >
+ operator-( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32FmsubExpr<T3,T4,T5>& b )
+{
+ return SIMDf32FmsubExpr< T1, T2, SIMDf32FmsubExpr<T3,T4,T5> >( a.a_, a.b_, b );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of two 32-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of two 32-bit
+// floating point FMA expressions. It restructures the expression \f$ (a*b+c) - (d*e+f) \f$ to
+// the expression \f$ (a*b) - (d*e+f-c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the addition operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the addition operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32FmaddExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( b.c_ - a.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of two 32-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of two 32-bit
+// floating point FMA expressions. It restructures the expression \f$ (a*b+c) - (d*e-f) \f$ to
+// the expression \f$ (a*b) - (d*e+f-c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the addition operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the subtraction operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32FmsubExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) - ( a.c_ + b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of two 32-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of two 32-bit
+// floating point FMA expressions. It restructures the expression \f$ (a*b-c) - (d*e+f) \f$ to
+// the expression \f$ (a*b) - (d*e+c-f)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the subtraction operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the addition operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32FmaddExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( a.c_ + b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of two 32-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of two 32-bit
+// floating point FMA expressions. It restructures the expression \f$ (a*b-c) - (d*e-f) \f$ to
+// the expression \f$ (a*b) - (d*e+c-f)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the subtraction operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the subtraction operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32FmsubExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( a.c_ - b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for 64-bit floating point fused multiply-add operations.
+// \ingroup simd
+//
+// The SIMDf64FmaddExpr class represents the compile time expression for 64-bit floating point
+// fused multiply-add operations.
+*/
+template< typename T1 // Type of the left-hand side multiplication operand
+ , typename T2 // Type of the right-hand side multiplication operand
+ , typename T3 > // Type of the right-hand side addition operand
+struct SIMDf64FmaddExpr : public SIMDf64< SIMDf64FmaddExpr<T1,T2,T3> >
+{
+ //**Type definitions****************************************************************************
+ using This = SIMDf64FmaddExpr<T1,T2,T3>; //!< Type of this SIMDf64FMaddExpr instance.
+ using BaseType = SIMDf64<This>; //!< Base type of this SIMDf64FMaddExpr instance.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SIMDf64FmaddExpr class.
+ //
+ // \param a The left-hand side operand for the multiplication.
+ // \param b The right-hand side operand for the multiplication.
+ // \param c The right-hand side operand for the addition.
+ */
+ explicit BLAZE_ALWAYS_INLINE SIMDf64FmaddExpr( const T1& a, const T2& b, const T3& c )
+ : a_( a ) // The left-hand side operand for the multiplication
+ , b_( b ) // The right-hand side operand for the multiplication
+ , c_( c ) // The right-hand side operand for the addition
+ {}
+ //**********************************************************************************************
+
+ //**Evaluation function*************************************************************************
+ /*!\brief Evaluation of the expression object.
+ //
+ // \return The resulting packed 64-bit floating point value.
+ */
+ BLAZE_ALWAYS_INLINE const SIMDdouble eval() const noexcept
+#if BLAZE_FMA_MODE && BLAZE_MIC_MODE
+ {
+ return _mm512_fmadd_pd( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#elif BLAZE_FMA_MODE && BLAZE_AVX_MODE
+ {
+ return _mm256_fmadd_pd( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#elif BLAZE_FMA_MODE && BLAZE_SSE2_MODE
+ {
+ return _mm_fmadd_pd( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#else
+ = delete;
+#endif
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ const T1 a_; //!< The left-hand side operand for the multiplication.
+ const T2 b_; //!< The right-hand side operand for the multiplication.
+ const T3 c_; //!< The right-hand side operand for the addition.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Expression object for 64-bit floating point fused multiply-subtract operations.
+// \ingroup simd
+//
+// The SIMDf64FmsubExpr class represents the compile time expression for 64-bit floating point
+// fused multiply-subtract operations.
+*/
+template< typename T1 // Type of the left-hand side multiplication operand
+ , typename T2 // Type of the right-hand side multiplication operand
+ , typename T3 > // Type of the right-hand side subtraction operand
+struct SIMDf64FmsubExpr : public SIMDf64< SIMDf64FmsubExpr<T1,T2,T3> >
+{
+ //**Type definitions****************************************************************************
+ using This = SIMDf64MultExpr<T1,T2>; //!< Type of this SIMDf64FMsubExpr instance.
+ using BaseType = SIMDf64<This>; //!< Base type of this SIMDf64FMsubExpr instance.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SIMDf64FmsubExpr class.
+ //
+ // \param a The left-hand side operand for the multiplication.
+ // \param b The right-hand side operand for the multiplication.
+ // \param c The right-hand side operand for the subtraction.
+ */
+ explicit BLAZE_ALWAYS_INLINE SIMDf64FmsubExpr( const T1& a, const T2& b, const T3& c )
+ : a_( a ) // The left-hand side operand for the multiplication
+ , b_( b ) // The right-hand side operand for the multiplication
+ , c_( c ) // The right-hand side operand for the subtraction
+ {}
+ //**********************************************************************************************
+
+ //**Evaluation function*************************************************************************
+ /*!\brief Evaluation of the expression object.
+ //
+ // \return The resulting packed 64-bit floating point value.
+ */
+ BLAZE_ALWAYS_INLINE const SIMDdouble eval() const noexcept
+#if BLAZE_FMA_MODE && BLAZE_MIC_MODE
+ {
+ return _mm512_fmsub_pd( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#elif BLAZE_FMA_MODE && BLAZE_AVX_MODE
+ {
+ return _mm256_fmsub_pd( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#elif BLAZE_FMA_MODE && BLAZE_SSE2_MODE
+ {
+ return _mm_fmsub_pd( a_.eval().value, b_.eval().value, c_.eval().value );
+ }
+#else
+ = delete;
+#endif
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ const T1 a_; //!< The left-hand side operand for the multiplication.
+ const T2 b_; //!< The right-hand side operand for the multiplication.
+ const T3 c_; //!< The right-hand side operand for the subtraction.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for fusing a 64-bit floating point multiplication and addition.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD addition operand.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 64-bit floating point multiplication with the addition of a 64-bit
+// floating point operand. It returns an expression representing the fused multiply-add (FMA)
+// operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand
+ , typename T2 // Type of the second multiplication operand
+ , typename T3 > // Type of the second addition operand
+BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr<T1,T2,T3>
+ operator+( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64<T3>& b )
+{
+ return SIMDf64FmaddExpr<T1,T2,T3>( a.a_, a.b_, ~b );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition operator for fusing a 64-bit floating point multiplication and addition.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD addition operand.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 64-bit floating point multiplication with the addition of a 64-bit
+// floating point operand. It returns an expression representing the fused multiply-add (FMA)
+// operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first addition operand
+ , typename T2 // Type of the first multiplication operand
+ , typename T3 > // Type of the second multiplication operand
+BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr<T2,T3,T1>
+ operator+( const SIMDf64<T1>& a, const SIMDf64MultExpr<T2,T3>& b )
+{
+ return SIMDf64FmaddExpr<T2,T3,T1>( b.a_, b.b_, ~a );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition operator for fusing a 64-bit floating point multiplication and addition.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 64-bit floating point multiplication with the addition of a 64-bit
+// floating point operand. It returns an expression representing the fused multiply-add (FMA)
+// operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first operand of the left-hand side multiplication
+ , typename T2 // Type of the second operand of the left-hand side multiplication
+ , typename T3 // Type of the first operand of the right-hand side multiplication
+ , typename T4 > // Type of the second operand of the right-hand side multiplication
+BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr< T1, T2, SIMDf64MultExpr<T3,T4> >
+ operator+( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64MultExpr<T3,T4>& b )
+{
+ return SIMDf64FmaddExpr< T1, T2, SIMDf64MultExpr<T3,T4> >( a.a_, a.b_, b );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of a 64-bit floating point FMA expression with
+// a 64-bit floating point operand.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD addition operand.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of a 64-bit floating
+// point FMA expression and a 64-bit floating point operand. It restructures the expression
+// \f$ (a*b+c) + d \f$ to the expression \f$ (a*b) + (c+d) \f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first FMA multiplication operand
+ , typename T2 // Type of the second FMA multiplication operand
+ , typename T3 // Type of the FMA addition operand
+ , typename T4 > // Type of the second addition operand
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64<T4>& b )
+{
+ return ( a.a_ * a.b_ ) + ( a.c_ + (~b) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of a 64-bit floating point operand with a
+// 64-bit floating point FMA expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD addition operand.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of a 64-bit floating
+// point operand and a 64-bit floating point FMA expression. It restructures the expression
+// \f$ a + (b*c+d) \f$ to the expression \f$ (b*c) + (d+a) \f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first addition operand
+ , typename T2 // Type of the first FMA multiplication operand
+ , typename T3 // Type of the second FMA multiplication operand
+ , typename T4 > // Type of the FMA addition operand
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf64<T1>& a, const SIMDf64FmaddExpr<T2,T3,T4>& b )
+{
+ return ( b.a_ * b.b_ ) + ( b.c_ + (~a) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of a 64-bit floating point FMA expression with
+// a 64-bit floating point multiplication expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of a 64-bit floating
+// point FMA expression and a 64-bit floating point multiplication expression. It restructures the
+// expression \f$ (a*b+c) + (d*e) \f$ to the expression \f$ (a*b) + (d*e+c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first FMA multiplication operand
+ , typename T2 // Type of the second FMA multiplication operand
+ , typename T3 // Type of the FMA addition operand
+ , typename T4 // Type of the first multiplication operand
+ , typename T5 > // Type of the second multiplication operand
+BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr< T4, T5, SIMDf64FmaddExpr<T1,T2,T3> >
+ operator+( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64MultExpr<T4,T5>& b )
+{
+ return SIMDf64FmaddExpr< T4, T5, SIMDf64FmaddExpr<T1,T2,T3> >( b.a_, b.b_, a );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of a 64-bit floating point multiplication
+// expression with a 64-bit floating point FMA expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of a 64-bit floating
+// point multiplication expression and a 64-bit floating point FMA expression. It restructures the
+// expression \f$ (a*b) + (c*d+e) \f$ to the expression \f$ (a*b) + (c*d+e)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand
+ , typename T2 // Type of the second multiplication operand
+ , typename T3 // Type of the first FMA multiplication operand
+ , typename T4 // Type of the second FMA multiplication operand
+ , typename T5 > // Type of the FMA addition operand
+BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr< T1, T2, SIMDf64FmaddExpr<T3,T4,T5> >
+ operator+( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64FmaddExpr<T3,T4,T5>& b )
+{
+ return SIMDf64FmaddExpr< T1, T2, SIMDf64FmaddExpr<T3,T4,T5> >( a.a_, a.b_, b );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of two 64-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of two 64-bit floating
+// point FMA expressions. It restructures the expression \f$ (a*b+c) + (d*e+f) \f$ to the expression
+// \f$ (a*b) + (d*e+c+f)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the addition operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the addition operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64FmaddExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( a.c_ + b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of two 64-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of two 64-bit floating
+// point FMA expressions. It restructures the expression \f$ (a*b+c) + (d*e-f) \f$ to the expression
+// \f$ (a*b) + (d*e+c-f)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the addition operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the subtraction operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64FmsubExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( a.c_ - b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of two 64-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of two 64-bit floating
+// point FMA expressions. It restructures the expression \f$ (a*b-c) + (d*e+f) \f$ to the expression
+// \f$ (a*b) + (d*e+f-c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the subtraction operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the addition operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64FmaddExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( b.c_ - a.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the addition of two 64-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the addition of two 64-bit floating
+// point FMA expressions. It restructures the expression \f$ (a*b-c) + (d*e-f) \f$ to the expression
+// \f$ (a*b) + (d*e-f-c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the subtraction operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the subtraction operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator+( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64FmsubExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) - ( b.c_ + a.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction operator for fusing a 64-bit floating point multiplication and subtraction.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD subtraction operand.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 64-bit floating point multiplication with the subtraction of a 64-bit
+// floating point operand. It returns an expression representing the fused multiply-subtract
+// operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand
+ , typename T2 // Type of the second multiplication operand
+ , typename T3 > // Type of the second subtraction operand
+BLAZE_ALWAYS_INLINE const SIMDf64FmsubExpr<T1,T2,T3>
+ operator-( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64<T3>& b )
+{
+ return SIMDf64FmsubExpr<T1,T2,T3>( a.a_, a.b_, ~b );
+}
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction operator for fusing a 64-bit floating point multiplication and subtraction.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The result of the FMA operation.
+//
+// This operator fuses a 64-bit floating point multiplication with the subtraction of a 64-bit
+// floating point operand. It returns an expression representing the fused multiply-subtract
+// (FMA) operation.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first operand of the left-hand side multiplication
+ , typename T2 // Type of the second operand of the left-hand side multiplication
+ , typename T3 // Type of the first operand of the right-hand side multiplication
+ , typename T4 > // Type of the second operand of the right-hand side multiplication
+BLAZE_ALWAYS_INLINE const SIMDf64FmsubExpr< T1, T2, SIMDf64MultExpr<T3,T4> >
+ operator-( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64MultExpr<T3,T4>& b )
+{
+ return SIMDf64FmsubExpr< T1, T2, SIMDf64MultExpr<T3,T4> >( a.a_, a.b_, b );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of a 64-bit floating point FMA expression
+// with a 64-bit floating point operand.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD subtraction operand.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of a 64-bit
+// floating point FMA expression and a 64-bit floating point operand. It restructures the
+// expression \f$ (a*b+c) + d \f$ to the expression \f$ (a*b) + (c+d) \f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first FMA multiplication operand
+ , typename T2 // Type of the second FMA multiplication operand
+ , typename T3 // Type of the FMA subtraction operand
+ , typename T4 > // Type of the second subtraction operand
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64<T4>& b )
+{
+ return ( a.a_ * a.b_ ) - ( a.c_ + (~b) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of a 64-bit floating point FMA expression
+// with a 64-bit floating point multiplication expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD multiplication expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of a 64-bit
+// floating point FMA expression and a 64-bit floating point multiplication expression. It
+// restructures the expression \f$ (a*b-c) - (d*e) \f$ to the expression \f$ (a*b) - (d*e+c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first FMA multiplication operand
+ , typename T2 // Type of the second FMA multiplication operand
+ , typename T3 // Type of the FMA subtraction operand
+ , typename T4 // Type of the first multiplication operand
+ , typename T5 > // Type of the second multiplication operand
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64MultExpr<T4,T5>& b )
+{
+ return ( a.a_ * a.b_ ) - ( b.a_ * b.b_ + a.c_ );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of a 64-bit floating point multiplication
+// expression with a 64-bit floating point FMA expression.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD multiplication expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of a 64-bit
+// floating point multiplication expression and a 64-bit floating point FMA expression. It
+// restructures the expression \f$ (a*b) - (c*d+e) \f$ to the expression \f$ (a*b) - (c*d+e)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand
+ , typename T2 // Type of the second multiplication operand
+ , typename T3 // Type of the first FMA multiplication operand
+ , typename T4 // Type of the second FMA multiplication operand
+ , typename T5 > // Type of the FMA subtraction operand
+BLAZE_ALWAYS_INLINE const SIMDf64FmsubExpr< T1, T2, SIMDf64FmsubExpr<T3,T4,T5> >
+ operator-( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64FmsubExpr<T3,T4,T5>& b )
+{
+ return SIMDf64FmsubExpr< T1, T2, SIMDf64FmsubExpr<T3,T4,T5> >( a.a_, a.b_, b );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of two 64-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of two 64-bit
+// floating point FMA expressions. It restructures the expression \f$ (a*b+c) - (d*e+f) \f$ to
+// the expression \f$ (a*b) - (d*e+f-c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the addition operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the addition operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64FmaddExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( b.c_ - a.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of two 64-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of two 64-bit
+// floating point FMA expressions. It restructures the expression \f$ (a*b+c) - (d*e-f) \f$ to
+// the expression \f$ (a*b) - (d*e+f-c)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the addition operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the subtraction operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64FmsubExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) - ( a.c_ + b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of two 64-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of two 64-bit
+// floating point FMA expressions. It restructures the expression \f$ (a*b-c) - (d*e+f) \f$ to
+// the expression \f$ (a*b) - (d*e+c-f)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the subtraction operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the addition operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64FmaddExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( a.c_ + b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Restructuring operator for the subtraction of two 64-bit floating point FMA expressions.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD FMA expression.
+// \param b The right-hand side SIMD FMA expression.
+// \return The restructured expression.
+//
+// This operator implements a performance optimized treatment of the subtraction of two 64-bit
+// floating point FMA expressions. It restructures the expression \f$ (a*b-c) - (d*e-f) \f$ to
+// the expression \f$ (a*b) - (d*e+c-f)\f$.
+*/
+#if BLAZE_FMA_MODE
+template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
+ , typename T2 // Type of the second multiplication operand of the left-hand side FMA
+ , typename T3 // Type of the subtraction operand of the left-hand side FMA
+ , typename T4 // Type of the first multiplication operand of the right-hand side FMA
+ , typename T5 // Type of the second multiplication operand of the right-hand side FMA
+ , typename T6 > // Type of the subtraction operand of the right-hand side FMA
+BLAZE_ALWAYS_INLINE const auto
+ operator-( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64FmsubExpr<T4,T5,T6>& b )
+{
+ return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( a.c_ - b.c_ ) );
+}
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Floor.h b/src/cpu/blaze/math/simd/Floor.h
new file mode 100644
index 00000000..471067b3
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Floor.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Floor.h
+// \brief Header file for the SIMD floor functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_FLOOR_H_
+#define _BLAZE_MATH_SIMD_FLOOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the largest integer value not greater than the given value for a vector of
+// single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat floor( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_floor_ps( (~a).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_floor_ps( (~a).eval().value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_floor_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the largest integer value not greater than the given value for a vector of
+// double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble floor( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_floor_pd( (~a).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_floor_pd( (~a).eval().value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_floor_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Functions.h b/src/cpu/blaze/math/simd/Functions.h
new file mode 100644
index 00000000..a025c32f
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Functions.h
@@ -0,0 +1,83 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Functions.h
+// \brief Header file for all SIMD functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_FUNCTIONS_H_
+#define _BLAZE_MATH_SIMD_FUNCTIONS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/Abs.h>
+#include <blaze/math/simd/Acos.h>
+#include <blaze/math/simd/Acosh.h>
+#include <blaze/math/simd/Addition.h>
+#include <blaze/math/simd/Asin.h>
+#include <blaze/math/simd/Asinh.h>
+#include <blaze/math/simd/Atan.h>
+#include <blaze/math/simd/Atanh.h>
+#include <blaze/math/simd/Cbrt.h>
+#include <blaze/math/simd/Ceil.h>
+#include <blaze/math/simd/Conj.h>
+#include <blaze/math/simd/Cos.h>
+#include <blaze/math/simd/Cosh.h>
+#include <blaze/math/simd/Division.h>
+#include <blaze/math/simd/Erf.h>
+#include <blaze/math/simd/Erfc.h>
+#include <blaze/math/simd/Exp.h>
+#include <blaze/math/simd/Floor.h>
+#include <blaze/math/simd/FMA.h>
+#include <blaze/math/simd/InvCbrt.h>
+#include <blaze/math/simd/InvSqrt.h>
+#include <blaze/math/simd/Loada.h>
+#include <blaze/math/simd/Loadu.h>
+#include <blaze/math/simd/Log.h>
+#include <blaze/math/simd/Log10.h>
+#include <blaze/math/simd/Multiplication.h>
+#include <blaze/math/simd/Pow.h>
+#include <blaze/math/simd/Reduction.h>
+#include <blaze/math/simd/Set.h>
+#include <blaze/math/simd/Setzero.h>
+#include <blaze/math/simd/Sin.h>
+#include <blaze/math/simd/Sinh.h>
+#include <blaze/math/simd/Sqrt.h>
+#include <blaze/math/simd/Storea.h>
+#include <blaze/math/simd/Storeu.h>
+#include <blaze/math/simd/Stream.h>
+#include <blaze/math/simd/Subtraction.h>
+#include <blaze/math/simd/Tan.h>
+#include <blaze/math/simd/Tanh.h>
+
+#endif
diff --git a/src/cpu/blaze/math/simd/InvCbrt.h b/src/cpu/blaze/math/simd/InvCbrt.h
new file mode 100644
index 00000000..9954cef0
--- /dev/null
+++ b/src/cpu/blaze/math/simd/InvCbrt.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/InvCbrt.h
+// \brief Header file for the SIMD inverse cubit root functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_INVCBRT_H_
+#define _BLAZE_MATH_SIMD_INVCBRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cubic root for a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat invcbrt( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_invcbrt_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_invcbrt_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the inverse cubic root for a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble invcbrt( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_invcbrt_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_invcbrt_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/InvSqrt.h b/src/cpu/blaze/math/simd/InvSqrt.h
new file mode 100644
index 00000000..12fc3ac5
--- /dev/null
+++ b/src/cpu/blaze/math/simd/InvSqrt.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/InvSqrt.h
+// \brief Header file for the SIMD inverse square root functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_INVSQRT_H_
+#define _BLAZE_MATH_SIMD_INVSQRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the inverse square root for a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat invsqrt( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_invsqrt_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_invsqrt_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_invsqrt_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the inverse square root for a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble invsqrt( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_invsqrt_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_invsqrt_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_invsqrt_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Loada.h b/src/cpu/blaze/math/simd/Loada.h
new file mode 100644
index 00000000..4de63ab4
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Loada.h
@@ -0,0 +1,465 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Loada.h
+// \brief Header file for the SIMD aligned load functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_LOADA_H_
+#define _BLAZE_MATH_SIMD_LOADA_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/HasSize.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsSigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 1-byte integral values.
+// \ingroup simd
+//
+// \param address The first integral value to be loaded.
+// \return The loaded vector of integral values.
+//
+// This function loads a vector of 1-byte integral values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,1UL> >
+ , If_< IsSigned<T>, SIMDint8, SIMDuint8 > >
+ loada( const T* address ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ return _mm256_load_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 1-byte integral complex values.
+// \ingroup simd
+//
+// \param address The first integral complex value to be loaded.
+// \return The loaded vector of integral complex values.
+//
+// This function loads a vector of 1-byte integral complex values. The given address must be
+// aligned according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte
+// alignment in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,1UL> >
+ , If_< IsSigned<T>, SIMDcint8, SIMDcuint8 > >
+ loada( const complex<T>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ return _mm256_load_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 2-byte integral values.
+// \ingroup simd
+//
+// \param address The first integral value to be loaded.
+// \return The loaded vector of integral values.
+//
+// This function loads a vector of 2-byte integral values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,2UL> >
+ , If_< IsSigned<T>, SIMDint16, SIMDuint16 > >
+ loada( const T* address ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ return _mm256_load_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 2-byte integral complex values.
+// \ingroup simd
+//
+// \param address The first integral complex value to be loaded.
+// \return The loaded vector of integral complex values.
+//
+// This function loads a vector of 2-byte integral complex values. The given address must be
+// aligned according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte
+// alignment in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,2UL> >
+ , If_< IsSigned<T>, SIMDcint16, SIMDcuint16 > >
+ loada( const complex<T>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ return _mm256_load_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 4-byte integral values.
+// \ingroup simd
+//
+// \param address The first integral value to be loaded.
+// \return The loaded vector of integral values.
+//
+// This function loads a vector of 4-byte integral values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,4UL> >
+ , If_< IsSigned<T>, SIMDint32, SIMDuint32 > >
+ loada( const T* address ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ return _mm512_load_epi32( address );
+#elif BLAZE_AVX2_MODE
+ return _mm256_load_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 4-byte integral complex values.
+// \ingroup simd
+//
+// \param address The first integral complex value to be loaded.
+// \return The loaded vector of integral complex values.
+//
+// This function loads a vector of 4-byte integral complex values. The given address must be
+// aligned according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte
+// alignment in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,4UL> >
+ , If_< IsSigned<T>, SIMDcint32, SIMDcuint32 > >
+ loada( const complex<T>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ return _mm512_load_epi32( address );
+#elif BLAZE_AVX2_MODE
+ return _mm256_load_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 8-byte integral values.
+// \ingroup simd
+//
+// \param address The first integral value to be loaded.
+// \return The loaded vector of integral values.
+//
+// This function loads a vector of 8-byte integral values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,8UL> >
+ , If_< IsSigned<T>, SIMDint64, SIMDuint64 > >
+ loada( const T* address ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ return _mm512_load_epi64( address );
+#elif BLAZE_AVX2_MODE
+ return _mm256_load_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 8-byte integral complex values.
+// \ingroup simd
+//
+// \param address The first integral complex value to be loaded.
+// \return The loaded vector of integral complex values.
+//
+// This function loads a vector of 8-byte integral complex values. The given address must be
+// aligned according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte
+// alignment in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,8UL> >
+ , If_< IsSigned<T>, SIMDcint64, SIMDcuint64 > >
+ loada( const complex<T>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ return _mm512_load_epi64( address );
+#elif BLAZE_AVX2_MODE
+ return _mm256_load_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return If_< IsSigned<T>, SIMDcint64, SIMDcuint64 >( *address );
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 'float' values.
+// \ingroup simd
+//
+// \param address The first 'float' value to be loaded.
+// \return The loaded vector of 'float' values.
+//
+// This function loads a vector of 'float' values. The given address must be aligned according
+// to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment in case
+// of AVX, and 64-byte alignment in case of MIC).
+*/
+BLAZE_ALWAYS_INLINE const SIMDfloat loada( const float* address ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ return _mm512_load_ps( address );
+#elif BLAZE_AVX_MODE
+ return _mm256_load_ps( address );
+#elif BLAZE_SSE_MODE
+ return _mm_load_ps( address );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 'complex<float>' values.
+// \ingroup simd
+//
+// \param address The first 'complex<float>' value to be loaded.
+// \return The loaded vector of 'complex<float>' values.
+//
+// This function loads a vector of 'complex<float>' values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat loada( const complex<float>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT ( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ return _mm512_load_ps( reinterpret_cast<const float*>( address ) );
+#elif BLAZE_AVX_MODE
+ return _mm256_load_ps( reinterpret_cast<const float*>( address ) );
+#elif BLAZE_SSE_MODE
+ return _mm_load_ps( reinterpret_cast<const float*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 'double' values.
+// \ingroup simd
+//
+// \param address The first 'double' value to be loaded.
+// \return The loaded vector of 'double' values.
+//
+// This function loads a vector of 'double' values. The given address must be aligned according
+// to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment in case
+// of AVX, and 64-byte alignment in case of MIC).
+*/
+BLAZE_ALWAYS_INLINE const SIMDdouble loada( const double* address ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ return _mm512_load_pd( address );
+#elif BLAZE_AVX_MODE
+ return _mm256_load_pd( address );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_pd( address );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 'complex<double>' values.
+// \ingroup simd
+//
+// \param address The first 'complex<double>' value to be loaded.
+// \return The loaded vector of 'complex<double>' values.
+//
+// This function loads a vector of 'complex<double>' values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble loada( const complex<double>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT ( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ return _mm512_load_pd( reinterpret_cast<const double*>( address ) );
+#elif BLAZE_AVX_MODE
+ return _mm256_load_pd( reinterpret_cast<const double*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_load_pd( reinterpret_cast<const double*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Loadu.h b/src/cpu/blaze/math/simd/Loadu.h
new file mode 100644
index 00000000..29c00718
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Loadu.h
@@ -0,0 +1,457 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Loadu.h
+// \brief Header file for the SIMD unaligned load functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_LOADU_H_
+#define _BLAZE_MATH_SIMD_LOADU_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/HasSize.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsSigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 1-byte integral values.
+// \ingroup simd
+//
+// \param address The first integral value to be loaded.
+// \return The loaded vector of integral values.
+//
+// This function loads a vector of 1-byte integral values. In contrast to the according \c loada()
+// function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,1UL> >
+ , If_< IsSigned<T>, SIMDint8, SIMDuint8 > >
+ loadu( const T* address ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ return _mm256_loadu_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 1-byte integral complex values.
+// \ingroup simd
+//
+// \param address The first integral complex value to be loaded.
+// \return The loaded vector of integral complex values.
+//
+// This function loads a vector of 1-byte integral complex values. In contrast to the according
+// \c loada() function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,1UL> >
+ , If_< IsSigned<T>, SIMDcint8, SIMDcuint8 > >
+ loadu( const complex<T>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+
+#if BLAZE_AVX2_MODE
+ return _mm256_loadu_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 2-byte integral values.
+// \ingroup simd
+//
+// \param address The first integral value to be loaded.
+// \return The loaded vector of integral values.
+//
+// This function loads a vector of 2-byte integral values. In contrast to the according \c loada()
+// function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,2UL> >
+ , If_< IsSigned<T>, SIMDint16, SIMDuint16 > >
+ loadu( const T* address ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ return _mm256_loadu_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 2-byte integral complex values.
+// \ingroup simd
+//
+// \param address The first integral complex value to be loaded.
+// \return The loaded vector of integral complex values.
+//
+// This function loads a vector of 2-byte integral complex values. In contrast to the according
+// \c loada() function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,2UL> >
+ , If_< IsSigned<T>, SIMDcint16, SIMDcuint16 > >
+ loadu( const complex<T>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+
+#if BLAZE_AVX2_MODE
+ return _mm256_loadu_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 4-byte integral values.
+// \ingroup simd
+//
+// \param address The first integral value to be loaded.
+// \return The loaded vector of integral values.
+//
+// This function loads a vector of 4-byte integral values. In contrast to the according \c loada()
+// function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,4UL> >
+ , If_< IsSigned<T>, SIMDint32, SIMDuint32 > >
+ loadu( const T* address ) noexcept
+{
+#if BLAZE_MIC_MODE
+ __m512i v1 = _mm512_setzero_epi32();
+ v1 = _mm512_loadunpacklo_epi32( v1, address );
+ v1 = _mm512_loadunpackhi_epi32( v1, address+16UL );
+ return v1;
+#elif BLAZE_AVX2_MODE
+ return _mm256_loadu_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 4-byte integral complex values.
+// \ingroup simd
+//
+// \param address The first integral complex value to be loaded.
+// \return The loaded vector of integral complex values.
+//
+// This function loads a vector of 4-byte integral complex values. In contrast to the according
+// \c loada() function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,4UL> >
+ , If_< IsSigned<T>, SIMDcint32, SIMDcuint32 > >
+ loadu( const complex<T>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+
+#if BLAZE_MIC_MODE
+ __m512i v1 = _mm512_setzero_epi32();
+ v1 = _mm512_loadunpacklo_epi32( v1, address );
+ v1 = _mm512_loadunpackhi_epi32( v1, address+8UL );
+ return v1;
+#elif BLAZE_AVX2_MODE
+ return _mm256_loadu_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 8-byte integral values.
+// \ingroup simd
+//
+// \param address The first integral value to be loaded.
+// \return The loaded vector of integral values.
+//
+// This function loads a vector of 8-byte integral values. In contrast to the according \c loada()
+// function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,8UL> >
+ , If_< IsSigned<T>, SIMDint64, SIMDuint64 > >
+ loadu( const T* address ) noexcept
+{
+#if BLAZE_MIC_MODE
+ __m512i v1 = _mm512_setzero_epi32();
+ v1 = _mm512_loadunpacklo_epi64( v1, address );
+ v1 = _mm512_loadunpackhi_epi64( v1, address+8UL );
+ return v1;
+#elif BLAZE_AVX2_MODE
+ return _mm256_loadu_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 8-byte integral complex values.
+// \ingroup simd
+//
+// \param address The first integral complex value to be loaded.
+// \return The loaded vector of integral complex values.
+//
+// This function loads a vector of 8-byte integral complex values. In contrast to the according
+// \c loada() function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,8UL> >
+ , If_< IsSigned<T>, SIMDcint64, SIMDcuint64 > >
+ loadu( const complex<T>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+
+#if BLAZE_MIC_MODE
+ __m512i v1 = _mm512_setzero_epi32();
+ v1 = _mm512_loadunpacklo_epi64( v1, address );
+ v1 = _mm512_loadunpackhi_epi64( v1, address+4UL );
+ return v1;
+#elif BLAZE_AVX2_MODE
+ return _mm256_loadu_si256( reinterpret_cast<const __m256i*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_si128( reinterpret_cast<const __m128i*>( address ) );
+#else
+ return If_< IsSigned<T>, SIMDcint64, SIMDcuint64 >( *address );
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 'float' values.
+// \ingroup simd
+//
+// \param address The first 'float' value to be loaded.
+// \return The loaded vector of 'float' values.
+//
+// This function loads a vector of 'float' values. In contrast to the according \c loada()
+// function, the given address is not required to be properly aligned.
+*/
+BLAZE_ALWAYS_INLINE const SIMDfloat loadu( const float* address ) noexcept
+{
+#if BLAZE_MIC_MODE
+ __m512 v1 = _mm512_setzero_ps();
+ v1 = _mm512_loadunpacklo_ps( v1, address );
+ v1 = _mm512_loadunpackhi_ps( v1, address+16UL );
+ return v1;
+#elif BLAZE_AVX_MODE
+ return _mm256_loadu_ps( address );
+#elif BLAZE_SSE_MODE
+ return _mm_loadu_ps( address );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 'complex<float>' values.
+// \ingroup simd
+//
+// \param address The first 'complex<float>' value to be loaded.
+// \return The loaded vector of 'complex<float>' values.
+//
+// This function loads a vector of 'complex<float>' values. In contrast to the according \c loada()
+// function, the given address is not required to be properly aligned.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat loadu( const complex<float>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+#if BLAZE_MIC_MODE
+ __m512 v1 = _mm512_setzero_ps();
+ v1 = _mm512_loadunpacklo_ps( v1, reinterpret_cast<const float*>( address ) );
+ v1 = _mm512_loadunpackhi_ps( v1, reinterpret_cast<const float*>( address+8UL ) );
+ return v1;
+#elif BLAZE_AVX_MODE
+ return _mm256_loadu_ps( reinterpret_cast<const float*>( address ) );
+#elif BLAZE_SSE_MODE
+ return _mm_loadu_ps( reinterpret_cast<const float*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 'double' values.
+// \ingroup simd
+//
+// \param address The first 'double' value to be loaded.
+// \return The loaded vector of 'double' values.
+//
+// This function loads a vector of 'double' values. In contrast to the according \c loada()
+// function, the given address is not required to be properly aligned.
+*/
+BLAZE_ALWAYS_INLINE const SIMDdouble loadu( const double* address ) noexcept
+{
+#if BLAZE_MIC_MODE
+ __m512d v1 = _mm512_setzero_pd();
+ v1 = _mm512_loadunpacklo_pd( v1, address );
+ v1 = _mm512_loadunpackhi_pd( v1, address+8UL );
+ return v1;
+#elif BLAZE_AVX_MODE
+ return _mm256_loadu_pd( address );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_pd( address );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Loads a vector of 'complex<double>' values.
+// \ingroup simd
+//
+// \param address The first 'complex<double>' value to be loaded.
+// \return The loaded vector of 'complex<double>' values.
+//
+// This function loads a vector of 'complex<double>' values. In contrast to the according
+// \c loada() function, the given address is not required to be properly aligned.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble loadu( const complex<double>* address ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+#if BLAZE_MIC_MODE
+ __m512d v1 = _mm512_setzero_pd();
+ v1 = _mm512_loadunpacklo_pd( v1, reinterpret_cast<const double*>( address ) );
+ v1 = _mm512_loadunpackhi_pd( v1, reinterpret_cast<const double*>( address+4UL ) );
+ return v1;
+#elif BLAZE_AVX_MODE
+ return _mm256_loadu_pd( reinterpret_cast<const double*>( address ) );
+#elif BLAZE_SSE2_MODE
+ return _mm_loadu_pd( reinterpret_cast<const double*>( address ) );
+#else
+ return *address;
+#endif
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Log.h b/src/cpu/blaze/math/simd/Log.h
new file mode 100644
index 00000000..e9f936dc
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Log.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Log.h
+// \brief Header file for the SIMD natural logarithm functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_LOG_H_
+#define _BLAZE_MATH_SIMD_LOG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the natural logarithm for a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat log( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_log_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_log_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_log_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the natural logarithm for a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble log( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_log_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_log_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_log_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Log10.h b/src/cpu/blaze/math/simd/Log10.h
new file mode 100644
index 00000000..bfbb6496
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Log10.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Log10.h
+// \brief Header file for the SIMD common (base-10) logarithm functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_LOG10_H_
+#define _BLAZE_MATH_SIMD_LOG10_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the common logarithm for a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat log10( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_log10_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_log10_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_log10_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the common logarithm for a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble log10( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_log10_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_log10_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_log10_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Multiplication.h b/src/cpu/blaze/math/simd/Multiplication.h
new file mode 100644
index 00000000..ab5a404e
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Multiplication.h
@@ -0,0 +1,881 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Multiplication.h
+// \brief Header file for the SIMD multiplication functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_MULTIPLICATION_H_
+#define _BLAZE_MATH_SIMD_MULTIPLICATION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of 16-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator*( const SIMDi16<T>& a, const SIMDi16<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mullo_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of 16-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint16
+ operator*( const SIMDi16<T1>& a, const SIMDi16<T2>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mullo_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 16-bit signed integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcint16
+ operator*( const SIMDcint16& a, const SIMDint16& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mullo_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 16-bit unsigned integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcuint16
+ operator*( const SIMDcuint16& a, const SIMDuint16& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mullo_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 16-bit signed integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side scalars.
+// \param b The right-hand side complex values to be scaled.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcint16
+ operator*( const SIMDint16& a, const SIMDcint16& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mullo_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 16-bit unsigned integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side scalars.
+// \param b The right-hand side complex values to be scaled.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcuint16
+ operator*( const SIMDuint16& a, const SIMDcuint16& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mullo_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of 16-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator*( const SIMDci16<T>& a, const SIMDci16<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ __m256i x, y, z;
+ const __m256i neg( _mm256_set_epi16( 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1 ) );
+
+ x = _mm256_shufflelo_epi16( (~a).value, 0xA0 );
+ x = _mm256_shufflehi_epi16( x, 0xA0 );
+ z = _mm256_mullo_epi16( x, (~b).value );
+ x = _mm256_shufflelo_epi16( (~a).value, 0xF5 );
+ x = _mm256_shufflehi_epi16( x, 0xF5 );
+ y = _mm256_shufflelo_epi16( (~b).value, 0xB1 );
+ y = _mm256_shufflehi_epi16( y, 0xB1 );
+ y = _mm256_mullo_epi16( x, y );
+ y = _mm256_mullo_epi16( y, neg );
+ return _mm256_add_epi16( z, y );
+}
+#elif BLAZE_SSE2_MODE
+{
+ __m128i x, y, z;
+ const __m128i neg( _mm_set_epi16( 1, -1, 1, -1, 1, -1, 1, -1 ) );
+
+ x = _mm_shufflelo_epi16( (~a).value, 0xA0 );
+ x = _mm_shufflehi_epi16( x, 0xA0 );
+ z = _mm_mullo_epi16( x, (~b).value );
+ x = _mm_shufflelo_epi16( (~a).value, 0xF5 );
+ x = _mm_shufflehi_epi16( x, 0xF5 );
+ y = _mm_shufflelo_epi16( (~b).value, 0xB1 );
+ y = _mm_shufflehi_epi16( y, 0xB1 );
+ y = _mm_mullo_epi16( x, y );
+ y = _mm_mullo_epi16( y, neg );
+ return _mm_add_epi16( z, y );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of 32-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE4, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator*( const SIMDi32<T>& a, const SIMDi32<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_mullo_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of 32-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE4, AVX2, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint32
+ operator*( const SIMDi32<T1>& a, const SIMDi32<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_mullo_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 32-bit signed integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE4, AVX2, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcint32
+ operator*( const SIMDcint32& a, const SIMDint32& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_mullo_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 32-bit unsigned integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE4, AVX2, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcuint32
+ operator*( const SIMDcuint32& a, const SIMDuint32& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_mullo_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 32-bit signed integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side scalars.
+// \param b The right-hand side complex values to be scaled.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE4, AVX2, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDcint32
+ operator*( const SIMDint32& a, const SIMDcint32& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_mullo_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of 32-bit unsigned integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side scalars.
+// \param b The right-hand side complex values to be scaled.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE4, AVX2, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDcuint32
+ operator*( const SIMDuint32& a, const SIMDcuint32& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_mullo_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE4_MODE
+{
+ return _mm_mullo_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of 32-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE4, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator*( const SIMDci32<T>& a, const SIMDci32<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ __m256i x, y, z;
+ const __m256i neg( _mm256_set_epi32( 1, -1, 1, -1, 1, -1, 1, -1 ) );
+
+ x = _mm256_shuffle_epi32( (~a).value, 0xA0 );
+ z = _mm256_mullo_epi32( x, (~b).value );
+ x = _mm256_shuffle_epi32( (~a).value, 0xF5 );
+ y = _mm256_shuffle_epi32( (~b).value, 0xB1 );
+ y = _mm256_mullo_epi32( x, y );
+ y = _mm256_mullo_epi32( y, neg );
+ return _mm256_add_epi32( z, y );
+}
+#elif BLAZE_SSE4_MODE
+{
+ __m128i x, y, z;
+ const __m128i neg( _mm_set_epi32( 1, -1, 1, -1 ) );
+
+ x = _mm_shuffle_epi32( (~a).value, 0xA0 );
+ z = _mm_mullo_epi32( x, (~b).value );
+ x = _mm_shuffle_epi32( (~a).value, 0xF5 );
+ y = _mm_shuffle_epi32( (~b).value, 0xB1 );
+ y = _mm_mullo_epi32( x, y );
+ y = _mm_mullo_epi32( y, neg );
+ return _mm_add_epi32( z, y );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for 32-bit floating point multiplication operations.
+// \ingroup simd
+//
+// The SIMDf32MultExpr class represents the compile time expression for 32-bit floating point
+// multiplication operations.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+struct SIMDf32MultExpr : public SIMDf32< SIMDf32MultExpr<T1,T2> >
+{
+ //**Type definitions****************************************************************************
+ using This = SIMDf32MultExpr<T1,T2>; //!< Type of this SIMDf32MultExpr instance.
+ using BaseType = SIMDf32<This>; //!< Base type of this SIMDf32MultExpr instance.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SIMDf32MultExpr class.
+ //
+ // \param a The left-hand side operand for the multiplication.
+ // \param b The right-hand side operand for the multiplication.
+ */
+ explicit BLAZE_ALWAYS_INLINE SIMDf32MultExpr( const T1& a, const T2& b )
+ : a_( a ) // The left-hand side operand for the multiplication
+ , b_( b ) // The right-hand side operand for the multiplication
+ {}
+ //**********************************************************************************************
+
+ //**Evaluation function*************************************************************************
+ /*!\brief Evaluation of the expression object.
+ //
+ // \return The resulting packed 32-bit floating point value.
+ */
+ BLAZE_ALWAYS_INLINE const SIMDfloat eval() const noexcept
+#if BLAZE_MIC_MODE
+ {
+ return _mm512_mul_ps( a_.eval().value, b_.eval().value );
+ }
+#elif BLAZE_AVX_MODE
+ {
+ return _mm256_mul_ps( a_.eval().value, b_.eval().value );
+ }
+#elif BLAZE_SSE_MODE
+ {
+ return _mm_mul_ps( a_.eval().value, b_.eval().value );
+ }
+#else
+ = delete;
+#endif
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ const T1 a_; //!< The left-hand side operand for the multiplication.
+ const T2 b_; //!< The right-hand side operand for the multiplication.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of single precision floating point SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDf32MultExpr<T1,T2>
+ operator*( const SIMDf32<T1>& a, const SIMDf32<T2>& b ) noexcept
+{
+ return SIMDf32MultExpr<T1,T2>( ~a, ~b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of single precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat
+ operator*( const SIMDcfloat& a, const SIMDfloat& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mul_ps( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_mul_ps( a.value, b.value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_mul_ps( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of single precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side scalars.
+// \param b The right-hand side complex values to be scaled.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat
+ operator*( const SIMDfloat& a, const SIMDcfloat& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mul_ps( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_mul_ps( a.value, b.value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_mul_ps( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of single precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE3 and AVX.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat
+ operator*( const SIMDcfloat& a, const SIMDcfloat& b ) noexcept
+#if BLAZE_AVX_MODE
+{
+ __m256 x, y, z;
+
+ x = _mm256_shuffle_ps( a.value, a.value, 0xA0 );
+ z = _mm256_mul_ps( x, b.value );
+ x = _mm256_shuffle_ps( a.value, a.value, 0xF5 );
+ y = _mm256_shuffle_ps( b.value, b.value, 0xB1 );
+ y = _mm256_mul_ps( x, y );
+ return _mm256_addsub_ps( z, y );
+}
+#elif BLAZE_SSE3_MODE
+{
+ __m128 x, y, z;
+
+ x = _mm_shuffle_ps( a.value, a.value, 0xA0 );
+ z = _mm_mul_ps( x, b.value );
+ x = _mm_shuffle_ps( a.value, a.value, 0xF5 );
+ y = _mm_shuffle_ps( b.value, b.value, 0xB1 );
+ y = _mm_mul_ps( x, y );
+ return _mm_addsub_ps( z, y );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Expression object for 64-bit floating point multiplication operations.
+// \ingroup simd
+//
+// The SIMDf64MultExpr class represents the compile time expression for 64-bit floating point
+// multiplication operations.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+struct SIMDf64MultExpr : public SIMDf64< SIMDf64MultExpr<T1,T2> >
+{
+ //**Type definitions****************************************************************************
+ using This = SIMDf64MultExpr<T1,T2>; //!< Type of this SIMDf64MultExpr instance.
+ using BaseType = SIMDf64<This>; //!< Base type of this SIMDf64MultExpr instance.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the SIMDf64MultExpr class.
+ //
+ // \param a The left-hand side operand for the multiplication.
+ // \param b The right-hand side operand for the multiplication.
+ */
+ explicit BLAZE_ALWAYS_INLINE SIMDf64MultExpr( const T1& a, const T2& b )
+ : a_( a ) // The left-hand side operand for the multiplication
+ , b_( b ) // The right-hand side operand for the multiplication
+ {}
+ //**********************************************************************************************
+
+ //**Evaluation function*************************************************************************
+ /*!\brief Evaluation of the expression object.
+ //
+ // \return The resulting packed 64-bit floating point value.
+ */
+ BLAZE_ALWAYS_INLINE const SIMDdouble eval() const noexcept
+#if BLAZE_MIC_MODE
+ {
+ return _mm512_mul_pd( a_.eval().value, b_.eval().value );
+ }
+#elif BLAZE_AVX_MODE
+ {
+ return _mm256_mul_pd( a_.eval().value, b_.eval().value );
+ }
+#elif BLAZE_SSE2_MODE
+ {
+ return _mm_mul_pd( a_.eval().value, b_.eval().value );
+ }
+#else
+ = delete;
+#endif
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ const T1 a_; //!< The left-hand side operand for the multiplication.
+ const T2 b_; //!< The right-hand side operand for the multiplication.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of double precision floating point SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDf64MultExpr<T1,T2>
+ operator*( const SIMDf64<T1>& a, const SIMDf64<T2>& b ) noexcept
+{
+ return SIMDf64MultExpr<T1,T2>( ~a, ~b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of double precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side complex values to be scaled.
+// \param b The right-hand side scalars.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble
+ operator*( const SIMDcdouble& a, const SIMDdouble& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mul_pd( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_mul_pd( a.value, b.value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mul_pd( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of a vector of double precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side scalars.
+// \param b The right-hand side complex values to be scaled.
+// \return The result of the scaling operation.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble
+ operator*( const SIMDdouble& a, const SIMDcdouble& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_mul_pd( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_mul_pd( a.value, b.value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_mul_pd( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication of two vectors of double precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the multiplication.
+//
+// This operation is only available for SSE3 and AVX.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble
+ operator*( const SIMDcdouble& a, const SIMDcdouble& b ) noexcept
+#if BLAZE_AVX_MODE
+{
+ __m256d x, y, z;
+
+ x = _mm256_shuffle_pd( a.value, a.value, 0 );
+ z = _mm256_mul_pd( x, b.value );
+ x = _mm256_shuffle_pd( a.value, a.value, 15 );
+ y = _mm256_shuffle_pd( b.value, b.value, 5 );
+ y = _mm256_mul_pd( x, y );
+ return _mm256_addsub_pd( z, y );
+}
+#elif BLAZE_SSE3_MODE
+{
+ __m128d x, y, z;
+
+ x = _mm_shuffle_pd( a.value, a.value, 0 );
+ z = _mm_mul_pd( x, b.value );
+ x = _mm_shuffle_pd( a.value, a.value, 3 );
+ y = _mm_shuffle_pd( b.value, b.value, 1 );
+ y = _mm_mul_pd( x, y );
+ return _mm_addsub_pd( z, y );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Pow.h b/src/cpu/blaze/math/simd/Pow.h
new file mode 100644
index 00000000..4cb32e11
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Pow.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Pow.h
+// \brief Header file for the SIMD power functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_POW_H_
+#define _BLAZE_MATH_SIMD_POW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the exponential value of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point base values.
+// \param b The vector of single precision floating point exponents.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operands
+BLAZE_ALWAYS_INLINE const SIMDfloat pow( const SIMDf32<T>& a, const SIMDf32<T>& b ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_pow_ps( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_pow_ps( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_pow_ps( (~a).eval().value, (~b).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the exponential value of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point base values.
+// \param b The vector of double precision floating point exponents.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operands
+BLAZE_ALWAYS_INLINE const SIMDdouble pow( const SIMDf64<T>& a, const SIMDf64<T>& b ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_pow_pd( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_pow_pd( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_pow_pd( (~a).eval().value, (~b).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Reduction.h b/src/cpu/blaze/math/simd/Reduction.h
new file mode 100644
index 00000000..0ff0e95d
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Reduction.h
@@ -0,0 +1,364 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Reduction.h
+// \brief Header file for the SIMD reduction functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_REDUCTION_H_
+#define _BLAZE_MATH_SIMD_REDUCTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the 8-bit integral complex SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE const complex<int8_t> sum( const SIMDcint8& a ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ return complex<int8_t>( a[0] + a[1] + a[ 2] + a[ 3] + a[ 4] + a[ 5] + a[ 6] + a[ 7] +
+ a[8] + a[9] + a[10] + a[11] + a[12] + a[13] + a[14] + a[15] );
+#elif BLAZE_SSE2_MODE
+ return complex<int8_t>( a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] );
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the 16-bit integral SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE int16_t sum( const SIMDint16& a ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ const __m256i b( _mm256_hadd_epi16( a.value, a.value ) );
+ const __m256i c( _mm256_hadd_epi16( b, b ) );
+ const __m256i d( _mm256_hadd_epi16( c, c ) );
+ const __m128i e = _mm_add_epi16( _mm256_extracti128_si256( d, 1 )
+ , _mm256_castsi256_si128( d ) );
+ return _mm_extract_epi16( e, 0 );
+#elif BLAZE_SSSE3_MODE
+ const __m128i b( _mm_hadd_epi16( a.value, a.value ) );
+ const __m128i c( _mm_hadd_epi16( b, b ) );
+ const __m128i d( _mm_hadd_epi16( c, c ) );
+ return _mm_extract_epi16( d, 0 );
+#elif BLAZE_SSE2_MODE
+ return a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7];
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the 16-bit integral complex SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE const complex<int16_t> sum( const SIMDcint16& a ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ return complex<int16_t>( a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] );
+#elif BLAZE_SSE2_MODE
+ return complex<int16_t>( a[0] + a[1] + a[2] + a[3] );
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the 32-bit integral SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE int32_t sum( const SIMDint32& a ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_reduce_add_epi32( a.value );
+#elif BLAZE_AVX2_MODE
+ const __m256i b( _mm256_hadd_epi32( a.value, a.value ) );
+ const __m256i c( _mm256_hadd_epi32( b, b ) );
+ const __m128i d = _mm_add_epi32( _mm256_extracti128_si256( c, 1 )
+ , _mm256_castsi256_si128( c ) );
+ return _mm_extract_epi32( d, 0 );
+#elif BLAZE_SSSE3_MODE
+ const __m128i b( _mm_hadd_epi32( a.value, a.value ) );
+ const __m128i c( _mm_hadd_epi32( b, b ) );
+ return _mm_cvtsi128_si32( c );
+#elif BLAZE_SSE2_MODE
+ return a[0] + a[1] + a[2] + a[3];
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the 32-bit integral complex SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE const complex<int32_t> sum( const SIMDcint32& a ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return complex<int32_t>( a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] );
+#elif BLAZE_AVX2_MODE
+ return complex<int32_t>( a[0] + a[1] + a[2] + a[3] );
+#elif BLAZE_SSE2_MODE
+ return complex<int32_t>( a[0] + a[1] );
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the 64-bit integral SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE int64_t sum( const SIMDint64& a ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_reduce_add_epi64( a.value );
+#elif BLAZE_AVX2_MODE
+ return a[0] + a[1] + a[2] + a[3];
+#elif BLAZE_SSE2_MODE
+ return a[0] + a[1];
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the 64-bit integral complex SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE const complex<int64_t> sum( const SIMDcint64& a ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return complex<int64_t>( a[0] + a[1] + a[2] + a[3] );
+#elif BLAZE_AVX2_MODE
+ return complex<int64_t>( a[0] + a[1] );
+#elif BLAZE_SSE2_MODE
+ return a[0];
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the single precision floating point SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE float sum( const SIMDfloat& a ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_reduce_add_ps( a.value );
+#elif BLAZE_AVX_MODE
+ const __m256 b( _mm256_hadd_ps( a.value, a.value ) );
+ const __m256 c( _mm256_hadd_ps( b, b ) );
+ const __m128 d = _mm_add_ps( _mm256_extractf128_ps( c, 1 ), _mm256_castps256_ps128( c ) );
+ return _mm_cvtss_f32( d );
+#elif BLAZE_SSE3_MODE
+ const __m128 b( _mm_hadd_ps( a.value, a.value ) );
+ const __m128 c( _mm_hadd_ps( b, b ) );
+ return _mm_cvtss_f32( c );
+#elif BLAZE_SSE_MODE
+ return a[0] + a[1] + a[2] + a[3];
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the single precision complex SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE const complex<float> sum( const SIMDcfloat& a ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return complex<float>( a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] );
+#elif BLAZE_AVX_MODE
+ return complex<float>( a[0] + a[1] + a[2] + a[3] );
+#elif BLAZE_SSE_MODE
+ return complex<float>( a[0] + a[1] );
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the double precision floating point SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE double sum( const SIMDdouble& a ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_reduce_add_pd( a.value );
+#elif BLAZE_AVX_MODE
+ const __m256d b( _mm256_hadd_pd( a.value, a.value ) );
+ const __m128d c = _mm_add_pd( _mm256_extractf128_pd( b, 1 ), _mm256_castpd256_pd128( b ) );
+ return _mm_cvtsd_f64( c );
+#elif BLAZE_SSE3_MODE
+ const __m128d b( _mm_hadd_pd( a.value, a.value ) );
+ return _mm_cvtsd_f64( b );
+#elif BLAZE_SSE2_MODE
+ return a[0] + a[1];
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the sum of all elements in the double precision complex SIMD vector.
+// \ingroup simd
+//
+// \param a The vector to be sumed up.
+// \return The sum of all vector elements.
+*/
+BLAZE_ALWAYS_INLINE const complex<double> sum( const SIMDcdouble& a ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return complex<double>( a[0] + a[1] + a[2] + a[3] );
+#elif BLAZE_AVX_MODE
+ return complex<double>( a[0] + a[1] );
+#elif BLAZE_SSE2_MODE
+ return a[0];
+#else
+ return a.value;
+#endif
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/SIMD.h b/src/cpu/blaze/math/simd/SIMD.h
new file mode 100644
index 00000000..5b1d4b18
--- /dev/null
+++ b/src/cpu/blaze/math/simd/SIMD.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/SIMD.h
+// \brief Mathematical SIMD module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SIMD_H_
+#define _BLAZE_MATH_SIMD_SIMD_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup simd SIMD
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/simd/SIMDPack.h b/src/cpu/blaze/math/simd/SIMDPack.h
new file mode 100644
index 00000000..b1afcd4f
--- /dev/null
+++ b/src/cpu/blaze/math/simd/SIMDPack.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/SIMDPack.h
+// \brief Header file for the SIMDPack base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SIMDPACK_H_
+#define _BLAZE_MATH_SIMD_SIMDPACK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all SIMD data types.
+// \ingroup simd
+//
+// The SIMDPack class template is a base class for all SIMD data types within the Blaze library.
+// It provides an abstraction from the actual type of the SIMD pack, but enables a conversion
+// back to this type via the 'Curiously Recurring Template Pattern' (CRTP).
+*/
+template< typename T > // Type of the SIMD pack
+struct SIMDPack
+{
+ //**Non-const conversion operator***************************************************************
+ /*!\brief Conversion operator for non-constant vectors.
+ //
+ // \return Reference of the actual type of the vector.
+ */
+ BLAZE_ALWAYS_INLINE T& operator~() noexcept {
+ return *static_cast<T*>( this );
+ }
+ //**********************************************************************************************
+
+ //**Const conversion operators******************************************************************
+ /*!\brief Conversion operator for constant vectors.
+ //
+ // \return Const reference of the actual type of the vector.
+ */
+ BLAZE_ALWAYS_INLINE const T& operator~() const noexcept {
+ return *static_cast<const T*>( this );
+ }
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/SIMDTrait.h b/src/cpu/blaze/math/simd/SIMDTrait.h
new file mode 100644
index 00000000..e6e34bc3
--- /dev/null
+++ b/src/cpu/blaze/math/simd/SIMDTrait.h
@@ -0,0 +1,320 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/SIMDTrait.h
+// \brief Header file for the SIMD trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SIMDTRAIT_H_
+#define _BLAZE_MATH_SIMD_SIMDTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/HasSize.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSigned.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS SIMDTRAITBASE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Base template for the SIMDTraitBase class.
+// \ingroup simd
+*/
+template< typename T
+ , typename = void >
+struct SIMDTraitBase
+{
+ using Type = T;
+ enum : size_t { size = 1UL };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 1-byte integral data types.
+// \ingroup simd
+*/
+template< typename T >
+struct SIMDTraitBase< T, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, Has1Byte<T> > > >
+{
+ using Type = If_< IsSigned<T>, SIMDint8, SIMDuint8 >;
+ enum : size_t { size = Type::size };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 1-byte integral complex data types.
+// \ingroup simd
+*/
+template< typename T >
+struct SIMDTraitBase< complex<T>, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, Has1Byte<T> > > >
+{
+ using Type = If_< IsSigned<T>, SIMDcint8, SIMDcuint8 >;
+ enum : size_t { size = Type::size };
+
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 2-byte integral data types.
+// \ingroup simd
+*/
+template< typename T >
+struct SIMDTraitBase< T, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, Has2Bytes<T> > > >
+{
+ using Type = If_< IsSigned<T>, SIMDint16, SIMDuint16 >;
+ enum : size_t { size = Type::size };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 2-byte integral complex data types.
+// \ingroup simd
+*/
+template< typename T >
+struct SIMDTraitBase< complex<T>, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, Has2Bytes<T> > > >
+{
+ using Type = If_< IsSigned<T>, SIMDcint16, SIMDcuint16 >;
+ enum : size_t { size = Type::size };
+
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 4-byte integral data types.
+// \ingroup simd
+*/
+template< typename T >
+struct SIMDTraitBase< T, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, Has4Bytes<T> > > >
+{
+ using Type = If_< IsSigned<T>, SIMDint32, SIMDuint32 >;
+ enum : size_t { size = Type::size };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 4-byte integral complex data types.
+// \ingroup simd
+*/
+template< typename T >
+struct SIMDTraitBase< complex<T>, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, Has4Bytes<T> > > >
+{
+ using Type = If_< IsSigned<T>, SIMDcint32, SIMDcuint32 >;
+ enum : size_t { size = Type::size };
+
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 8-byte integral data types.
+// \ingroup simd
+*/
+template< typename T >
+struct SIMDTraitBase< T, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, Has8Bytes<T> > > >
+{
+ using Type = If_< IsSigned<T>, SIMDint64, SIMDuint64 >;
+ enum : size_t { size = Type::size };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 8-byte integral complex data types.
+// \ingroup simd
+*/
+template< typename T >
+struct SIMDTraitBase< complex<T>, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, Has8Bytes<T> > > >
+{
+ using Type = If_< IsSigned<T>, SIMDcint64, SIMDcuint64 >;
+ enum : size_t { size = Type::size };
+
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 'float'.
+// \ingroup simd
+*/
+template<>
+struct SIMDTraitBase<float>
+{
+ using Type = SIMDfloat;
+ enum : size_t { size = Type::size };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 'complex<float>'.
+// \ingroup simd
+*/
+template<>
+struct SIMDTraitBase< complex<float> >
+{
+ using Type = SIMDcfloat;
+ enum : size_t { size = Type::size };
+
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 'double'.
+// \ingroup simd
+*/
+template<>
+struct SIMDTraitBase<double>
+{
+ using Type = SIMDdouble;
+ enum : size_t { size = Type::size };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SIMDTraitBase class template for 'complex<double>'.
+// \ingroup simd
+*/
+template<>
+struct SIMDTraitBase< complex<double> >
+{
+ using Type = SIMDcdouble;
+ enum : size_t { size = Type::size };
+
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS SIMDTRAIT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief SIMD characteristics of data types.
+// \ingroup simd
+//
+// The SIMDTrait class template provides the SIMD characteristics of a specific data type:
+//
+// - The nested data type \a Type corresponds to the according packed, SIMD data type. In case
+// the data type doesn't have a SIMD representation, \a Type corresonds to the given data
+// type itself.
+// - The \a size member constant corresponds to the number of values of the given data type that
+// are packed together in one SIMD vector type. In case the data type cannot be vectorized,
+// \a size is set to 1.
+*/
+template< typename T >
+class SIMDTrait : public SIMDTraitBase< RemoveCV_<T> >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SIMDTrait class template.
+// \ingroup simd
+//
+// The SIMDTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the SIMDTrait class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SIMDTrait<T>::Type;
+ using Type2 = SIMDTrait_<T>;
+ \endcode
+*/
+template< typename T >
+using SIMDTrait_ = typename SIMDTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Set.h b/src/cpu/blaze/math/simd/Set.h
new file mode 100644
index 00000000..004353fd
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Set.h
@@ -0,0 +1,417 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Set.h
+// \brief Header file for the SIMD set functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SET_H_
+#define _BLAZE_MATH_SIMD_SET_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Integral.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/HasSize.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsSigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 1-byte integral value.
+// \ingroup simd
+//
+// \param value The given 1-byte integral value.
+// \return The set vector of 1-byte integral values.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,1UL> >
+ , If_< IsSigned<T>, SIMDint8, SIMDuint8 > >
+ set( T value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ return _mm256_set1_epi8( value );
+#elif BLAZE_SSE2_MODE
+ return _mm_set1_epi8( value );
+#else
+ return value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 1-byte integral complex value.
+// \ingroup simd
+//
+// \param value The given 1-byte integral complex value.
+// \return The set vector of 1-byte integral complex values.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,1UL> >
+ , If_< IsSigned<T>, SIMDcint8, SIMDcuint8 > >
+ set( complex<T> value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ return _mm256_set_epi8( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_SSE2_MODE
+ return _mm_set_epi8( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#else
+ return value;
+#endif
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 2-byte integral value.
+// \ingroup simd
+//
+// \param value The given 2-byte integral value.
+// \return The set vector of 2-byte integral values.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,2UL> >
+ , If_< IsSigned<T>, SIMDint16, SIMDuint16 > >
+ set( T value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ return _mm256_set1_epi16( value );
+#elif BLAZE_SSE2_MODE
+ return _mm_set1_epi16( value );
+#else
+ return value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 2-byte integral complex value.
+// \ingroup simd
+//
+// \param value The given 2-byte integral complex value.
+// \return The set vector of 2-byte integral complex values.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,2UL> >
+ , If_< IsSigned<T>, SIMDcint16, SIMDcuint16 > >
+ set( complex<T> value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ return _mm256_set_epi16( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_SSE2_MODE
+ return _mm_set_epi16( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#else
+ return value;
+#endif
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 4-byte integral value.
+// \ingroup simd
+//
+// \param value The given 4-byte integral value.
+// \return The set vector of 4-byte integral values.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,4UL> >
+ , If_< IsSigned<T>, SIMDint32, SIMDuint32 > >
+ set( T value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_set1_epi32( value );
+#elif BLAZE_AVX2_MODE
+ return _mm256_set1_epi32( value );
+#elif BLAZE_SSE2_MODE
+ return _mm_set1_epi32( value );
+#else
+ return value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 4-byte integral complex value.
+// \ingroup simd
+//
+// \param value The given 4-byte integral complex value.
+// \return The set vector of 4-byte integral complex values.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,4UL> >
+ , If_< IsSigned<T>, SIMDcint32, SIMDcuint32 > >
+ set( complex<T> value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_set_epi32( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_AVX2_MODE
+ return _mm256_set_epi32( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_SSE2_MODE
+ return _mm_set_epi32( value.imag(), value.real(), value.imag(), value.real() );
+#else
+ return value;
+#endif
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 8-byte integral value.
+// \ingroup simd
+//
+// \param value The given 8-byte integral value.
+// \return The set vector of 8-byte integral values.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,8UL> >
+ , If_< IsSigned<T>, SIMDint64, SIMDuint64 > >
+ set( T value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_set1_epi64( value );
+#elif BLAZE_AVX2_MODE
+ return _mm256_set1_epi64x( value );
+#elif BLAZE_SSE2_MODE
+ return _mm_set1_epi64( value );
+#else
+ return value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 8-byte integral complex value.
+// \ingroup simd
+//
+// \param value The given 8-byte integral complex value.
+// \return The set vector of 8-byte integral complex values.
+*/
+template< typename T > // Type of the integral value
+BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral<T>, HasSize<T,8UL> >
+ , If_< IsSigned<T>, SIMDcint64, SIMDcuint64 > >
+ set( complex<T> value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_set_epi64( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_AVX2_MODE
+ return _mm256_set_epi64( value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_SSE2_MODE
+ return _mm_set_epi64( value.imag(), value.real() );
+#else
+ return value;
+#endif
+ BLAZE_STATIC_ASSERT( sizeof( complex<T> ) == 2UL*sizeof( T ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 'float' value.
+// \ingroup simd
+//
+// \param value The given 'float' value.
+// \return The set vector of 'float' values.
+*/
+BLAZE_ALWAYS_INLINE const SIMDfloat set( float value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_set1_ps( value );
+#elif BLAZE_AVX_MODE
+ return _mm256_set1_ps( value );
+#elif BLAZE_SSE_MODE
+ return _mm_set1_ps( value );
+#else
+ return value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 'complex<float>' value.
+// \ingroup simd
+//
+// \param value The given 'complex<float>' value.
+// \return The set vector of 'complex<float>' values.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat set( const complex<float>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_set_ps( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_AVX_MODE
+ return _mm256_set_ps( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_SSE_MODE
+ return _mm_set_ps( value.imag(), value.real(), value.imag(), value.real() );
+#else
+ return value;
+#endif
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 'double' value.
+// \ingroup simd
+//
+// \param value The given 'double' value.
+// \return The set vector of 'double' values.
+*/
+BLAZE_ALWAYS_INLINE const SIMDdouble set( double value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_set1_pd( value );
+#elif BLAZE_AVX_MODE
+ return _mm256_set1_pd( value );
+#elif BLAZE_SSE2_MODE
+ return _mm_set1_pd( value );
+#else
+ return value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sets all values in the vector to the given 'complex<double>' value.
+// \ingroup simd
+//
+// \param value The given 'complex<double>' value.
+// \return The set vector of 'complex<double>' values.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble set( const complex<double>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ return _mm512_set_pd( value.imag(), value.real(), value.imag(), value.real(),
+ value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_AVX_MODE
+ return _mm256_set_pd( value.imag(), value.real(), value.imag(), value.real() );
+#elif BLAZE_SSE2_MODE
+ return _mm_set_pd( value.imag(), value.real() );
+#else
+ return value;
+#endif
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Setzero.h b/src/cpu/blaze/math/simd/Setzero.h
new file mode 100644
index 00000000..c5747dd0
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Setzero.h
@@ -0,0 +1,361 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Setzero.h
+// \brief Header file for the SIMD setzero functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SETZERO_H_
+#define _BLAZE_MATH_SIMD_SETZERO_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Setting an integral SIMD type with 8-bit data values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+template< typename T > // Type of the SIMD element
+BLAZE_ALWAYS_INLINE void setzero( SIMDi8<T>& value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ (~value).value = _mm256_setzero_si256();
+#elif BLAZE_SSE2_MODE
+ (~value).value = _mm_setzero_si128();
+#else
+ (~value).value = 0;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting an integral SIMD type with 8-bit complex values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+template< typename T > // Type of the SIMD element
+BLAZE_ALWAYS_INLINE void setzero( SIMDci8<T>& value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ (~value).value = _mm256_setzero_si256();
+#elif BLAZE_SSE2_MODE
+ (~value).value = _mm_setzero_si128();
+#else
+ (~value).value = 0;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Setting an integral SIMD type with 16-bit data values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+template< typename T > // Type of the SIMD element
+BLAZE_ALWAYS_INLINE void setzero( SIMDi16<T>& value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ (~value).value = _mm256_setzero_si256();
+#elif BLAZE_SSE2_MODE
+ (~value).value = _mm_setzero_si128();
+#else
+ (~value).value = 0;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting an integral SIMD type with 16-bit complex values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+template< typename T > // Type of the SIMD element
+BLAZE_ALWAYS_INLINE void setzero( SIMDci16<T>& value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ (~value).value = _mm256_setzero_si256();
+#elif BLAZE_SSE2_MODE
+ (~value).value = _mm_setzero_si128();
+#else
+ (~value).value = 0;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Setting an integral SIMD type with 32-bit data values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+template< typename T > // Type of the SIMD element
+BLAZE_ALWAYS_INLINE void setzero( SIMDi32<T>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ (~value).value = _mm512_setzero_epi32();
+#elif BLAZE_AVX2_MODE
+ (~value).value = _mm256_setzero_si256();
+#elif BLAZE_SSE2_MODE
+ (~value).value = _mm_setzero_si128();
+#else
+ (~value).value = 0;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting an integral SIMD type with 32-bit complex values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+template< typename T > // Type of the SIMD element
+BLAZE_ALWAYS_INLINE void setzero( SIMDci32<T>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ (~value).value = _mm512_setzero_epi32();
+#elif BLAZE_AVX2_MODE
+ (~value).value = _mm256_setzero_si256();
+#elif BLAZE_SSE2_MODE
+ (~value).value = _mm_setzero_si128();
+#else
+ (~value).value = 0;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Setting an integral SIMD type with 64-bit data values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+template< typename T > // Type of the SIMD element
+BLAZE_ALWAYS_INLINE void setzero( SIMDi64<T>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ (~value).value = _mm512_setzero_epi32();
+#elif BLAZE_AVX2_MODE
+ (~value).value = _mm256_setzero_si256();
+#elif BLAZE_SSE2_MODE
+ (~value).value = _mm_setzero_si128();
+#else
+ (~value).value = 0;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting an integral SIMD type with 64-bit complex values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+template< typename T > // Type of the SIMD element
+BLAZE_ALWAYS_INLINE void setzero( SIMDci64<T>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ (~value).value = _mm512_setzero_epi32();
+#elif BLAZE_AVX2_MODE
+ (~value).value = _mm256_setzero_si256();
+#elif BLAZE_SSE2_MODE
+ (~value).value = _mm_setzero_si128();
+#else
+ (~value).value = 0;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Setting a floating point SIMD type with 32-bit single precision data values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+BLAZE_ALWAYS_INLINE void setzero( SIMDfloat& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ value.value = _mm512_setzero_ps();
+#elif BLAZE_AVX_MODE
+ value.value = _mm256_setzero_ps();
+#elif BLAZE_SSE_MODE
+ value.value = _mm_setzero_ps();
+#else
+ value.value = 0.0F;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting a floating point SIMD type with 32-bit single precision complex values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+BLAZE_ALWAYS_INLINE void setzero( SIMDcfloat& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ value.value = _mm512_setzero_ps();
+#elif BLAZE_AVX_MODE
+ value.value = _mm256_setzero_ps();
+#elif BLAZE_SSE_MODE
+ value.value = _mm_setzero_ps();
+#else
+ value.value = 0.0F;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Setting a floating point SIMD type with 64-bit double precision data values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+BLAZE_ALWAYS_INLINE void setzero( SIMDdouble& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ value.value = _mm512_setzero_pd();
+#elif BLAZE_AVX_MODE
+ value.value = _mm256_setzero_pd();
+#elif BLAZE_SSE2_MODE
+ value.value = _mm_setzero_pd();
+#else
+ value.value = 0.0;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting a floating point SIMD type with 32-bit double precision complex values to zero.
+// \ingroup simd
+//
+// \param value The value to be set to zero.
+// \return void
+*/
+BLAZE_ALWAYS_INLINE void setzero( SIMDcdouble& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ value.value = _mm512_setzero_pd();
+#elif BLAZE_AVX_MODE
+ value.value = _mm256_setzero_pd();
+#elif BLAZE_SSE2_MODE
+ value.value = _mm_setzero_pd();
+#else
+ value.value = 0.0;
+#endif
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Sin.h b/src/cpu/blaze/math/simd/Sin.h
new file mode 100644
index 00000000..df9f1138
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Sin.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Sin.h
+// \brief Header file for the SIMD sine functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SIN_H_
+#define _BLAZE_MATH_SIMD_SIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Sine of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat sin( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_sin_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_sin_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_sin_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Sine of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble sin( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_sin_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_sin_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_sin_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Sinh.h b/src/cpu/blaze/math/simd/Sinh.h
new file mode 100644
index 00000000..aa5d5aa8
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Sinh.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Sinh.h
+// \brief Header file for the SIMD hyperbolic sine functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SINH_H_
+#define _BLAZE_MATH_SIMD_SINH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Hyperbolic sine of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat sinh( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_sinh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_sinh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_sinh_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Hyperbolic sine of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble sinh( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_sinh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_sinh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_sinh_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Sqrt.h b/src/cpu/blaze/math/simd/Sqrt.h
new file mode 100644
index 00000000..9d278ff0
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Sqrt.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Sqrt.h
+// \brief Header file for the SIMD square root functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SQRT_H_
+#define _BLAZE_MATH_SIMD_SQRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the square root for a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat sqrt( const SIMDf32<T>& a ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sqrt_ps( (~a).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_sqrt_ps( (~a).eval().value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_sqrt_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the square root for a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble sqrt( const SIMDf64<T>& a ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sqrt_pd( (~a).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_sqrt_pd( (~a).eval().value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sqrt_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Storea.h b/src/cpu/blaze/math/simd/Storea.h
new file mode 100644
index 00000000..8009c0f4
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Storea.h
@@ -0,0 +1,477 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Storea.h
+// \brief Header file for the SIMD aligned store functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_STOREA_H_
+#define _BLAZE_MATH_SIMD_STOREA_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/HasSize.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 1-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 1-byte integral vector to be stored.
+// \return void
+//
+// This function stores a vector of 1-byte integral values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,1UL> > >
+ storea( T1* address, const SIMDi8<T2>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ _mm256_store_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 1-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 1-byte integral complex vector to be stored.
+// \return void
+//
+// This function stores a vector of 1-byte integral complex values. The given address must be
+// aligned according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte
+// alignment in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,1UL> > >
+ storea( complex<T1>* address, const SIMDci8<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ _mm256_store_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 2-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 2-byte integral vector to be stored.
+// \return void
+//
+// This function stores a vector of 2-byte integral values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,2UL> > >
+ storea( T1* address, const SIMDi16<T2>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ _mm256_store_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 2-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 2-byte integral complex vector to be stored.
+// \return void
+//
+// This function stores a vector of 2-byte integral complex values. The given address must be
+// aligned according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte
+// alignment in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,2UL> > >
+ storea( complex<T1>* address, const SIMDci16<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ _mm256_store_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 4-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 4-byte integral vector to be stored.
+// \return void
+//
+// This function stores a vector of 4-byte integral values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,4UL> > >
+ storea( T1* address, const SIMDi32<T2>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_epi32( address, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_store_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 4-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 4-byte integral complex vector to be stored.
+// \return void
+//
+// This function stores a vector of 4-byte integral complex values. The given address must be
+// aligned according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte
+// alignment in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,4UL> > >
+ storea( complex<T1>* address, const SIMDci32<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_epi32( address, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_store_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 8-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 8-byte integral vector to be stored.
+// \return void
+//
+// This function stores a vector of 8-byte integral values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,8UL> > >
+ storea( T1* address, const SIMDi64<T2>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_epi64( address, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_store_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 8-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 8-byte integral complex vector to be stored.
+// \return void
+//
+// This function stores a vector of 8-byte integral complex values. The given address must be
+// aligned according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte
+// alignment in case of AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,8UL> > >
+ storea( complex<T1>* address, const SIMDci64<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_epi64( address, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_store_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 'float' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'float' vector to be stored.
+// \return void
+//
+// This function stores a vector of 'float' values. The given address must be aligned according
+// to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment in case of
+// AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE void storea( float* address, const SIMDf32<T>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_ps( address, (~value).eval().value );
+#elif BLAZE_AVX_MODE
+ _mm256_store_ps( address, (~value).eval().value );
+#elif BLAZE_SSE_MODE
+ _mm_store_ps( address, (~value).eval().value );
+#else
+ *address = (~value).eval().value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 'complex<float>' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'complex<float>' vector to be stored.
+// \return void
+//
+// This function stores a vector of 'complex<float>' values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+BLAZE_ALWAYS_INLINE void storea( complex<float>* address, const SIMDcfloat& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT ( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_ps( reinterpret_cast<float*>( address ), value.value );
+#elif BLAZE_AVX_MODE
+ _mm256_store_ps( reinterpret_cast<float*>( address ), value.value );
+#elif BLAZE_SSE_MODE
+ _mm_store_ps( reinterpret_cast<float*>( address ), value.value );
+#else
+ *address = value.value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 'double' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'double' vector to be stored.
+// \return void
+//
+// This function stores a vector of 'double' values. The given address must be aligned according
+// to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment in case of
+// AVX, and 64-byte alignment in case of MIC).
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE void storea( double* address, const SIMDf64<T>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_pd( address, (~value).eval().value );
+#elif BLAZE_AVX_MODE
+ _mm256_store_pd( address, (~value).eval().value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_pd( address, (~value).eval().value );
+#else
+ *address = (~value).eval().value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned store of a vector of 'complex<double>' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'complex<double>' vector to be stored.
+// \return void
+//
+// This function stores a vector of 'complex<double>' values. The given address must be aligned
+// according to the enabled instruction set (16-byte alignment in case of SSE, 32-byte alignment
+// in case of AVX, and 64-byte alignment in case of MIC).
+*/
+BLAZE_ALWAYS_INLINE void storea( complex<double>* address, const SIMDcdouble& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT ( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_pd( reinterpret_cast<double*>( address ), value.value );
+#elif BLAZE_AVX_MODE
+ _mm256_store_pd( reinterpret_cast<double*>( address ), value.value );
+#elif BLAZE_SSE2_MODE
+ _mm_store_pd( reinterpret_cast<double*>( address ), value.value );
+#else
+ *address = value.value;
+#endif
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Storeu.h b/src/cpu/blaze/math/simd/Storeu.h
new file mode 100644
index 00000000..6715a8b0
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Storeu.h
@@ -0,0 +1,455 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Storeu.h
+// \brief Header file for the SIMD unaligned store functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_STOREU_H_
+#define _BLAZE_MATH_SIMD_STOREU_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/HasSize.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 1-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 1-byte integral vector to be stored.
+// \return void
+//
+// This function stores a vector of 1-byte integral values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,1UL> > >
+ storeu( T1* address, const SIMDi8<T2>& value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ _mm256_storeu_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 1-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 1-byte integral complex vector to be stored.
+// \return void
+//
+// This function stores a vector of 1-byte integral complex values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,1UL> > >
+ storeu( complex<T1>* address, const SIMDci8<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+
+#if BLAZE_AVX2_MODE
+ _mm256_storeu_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 2-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 2-byte integral vector to be stored.
+// \return void
+//
+// This function stores a vector of 2-byte integral values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,2UL> > >
+ storeu( T1* address, const SIMDi16<T2>& value ) noexcept
+{
+#if BLAZE_AVX2_MODE
+ _mm256_storeu_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 2-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 2-byte integral complex vector to be stored.
+// \return void
+//
+// This function stores a vector of 2-byte integral complex values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,2UL> > >
+ storeu( complex<T1>* address, const SIMDci16<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+
+#if BLAZE_AVX2_MODE
+ _mm256_storeu_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 4-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 4-byte integral vector to be stored.
+// \return void
+//
+// This function stores a vector of 4-byte integral values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,4UL> > >
+ storeu( T1* address, const SIMDi32<T2>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ _mm512_packstorelo_epi32( address , (~value).value );
+ _mm512_packstorehi_epi32( address+16UL, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_storeu_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 4-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 4-byte integral complex vector to be stored.
+// \return void
+//
+// This function stores a vector of 4-byte integral complex values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,4UL> > >
+ storeu( complex<T1>* address, const SIMDci32<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+
+#if BLAZE_MIC_MODE
+ _mm512_packstorelo_epi32( address , (~value).value );
+ _mm512_packstorehi_epi32( address+8UL, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_storeu_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 8-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 8-byte integral vector to be stored.
+// \return void
+//
+// This function stores a vector of 8-byte integral values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,8UL> > >
+ storeu( T1* address, const SIMDi64<T2>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ _mm512_packstorelo_epi64( address , (~value).value );
+ _mm512_packstorehi_epi64( address+8UL, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_storeu_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 8-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 8-byte integral complex vector to be stored.
+// \return void
+//
+// This function stores a vector of 8-byte integral complex values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,8UL> > >
+ storeu( complex<T1>* address, const SIMDci64<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+
+#if BLAZE_MIC_MODE
+ _mm512_packstorelo_epi64( address , (~value).value );
+ _mm512_packstorehi_epi64( address+4UL, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_storeu_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 'float' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'float' vector to be stored.
+// \return void
+//
+// This function stores a vector of 'float' values. In contrast to the according \c storea()
+// function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE void storeu( float* address, const SIMDf32<T>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ const SIMDfloat( (~value).eval().value );
+ _mm512_packstorelo_ps( address , tmp );
+ _mm512_packstorehi_ps( address+16UL, tmp );
+#elif BLAZE_AVX_MODE
+ _mm256_storeu_ps( address, (~value).eval().value );
+#elif BLAZE_SSE_MODE
+ _mm_storeu_ps( address, (~value).eval().value );
+#else
+ *address = (~value).eval().value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 'complex<float>' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'complex<float>' vector to be stored.
+// \return void
+//
+// This function stores a vector of 'complex<float>' values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+BLAZE_ALWAYS_INLINE void storeu( complex<float>* address, const SIMDcfloat& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+
+#if BLAZE_MIC_MODE
+ _mm512_packstorelo_ps( reinterpret_cast<float*>( address ), value.value );
+ _mm512_packstorehi_ps( reinterpret_cast<float*>( address+8UL ), value.value );
+#elif BLAZE_AVX_MODE
+ _mm256_storeu_ps( reinterpret_cast<float*>( address ), value.value );
+#elif BLAZE_SSE_MODE
+ _mm_storeu_ps( reinterpret_cast<float*>( address ), value.value );
+#else
+ *address = value.value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 'double' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'double' vector to be stored.
+// \return void
+//
+// This function stores a vector of 'double' values. In contrast to the according \c storea()
+// function, the given address is not required to be properly aligned.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE void storeu( double* address, const SIMDf64<T>& value ) noexcept
+{
+#if BLAZE_MIC_MODE
+ const SIMDdouble tmp( (~value).eval().value );
+ _mm512_packstorelo_pd( address , tmp );
+ _mm512_packstorehi_pd( address+8UL, tmp );
+#elif BLAZE_AVX_MODE
+ _mm256_storeu_pd( address, (~value).eval().value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_pd( address, (~value).eval().value );
+#else
+ *address = (~value).eval().value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unaligned store of a vector of 'complex<double>' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'complex<double>' vector to be stored.
+// \return void
+//
+// This function stores a vector of 'complex<double>' values. In contrast to the according
+// \c storea() function, the given address is not required to be properly aligned.
+*/
+BLAZE_ALWAYS_INLINE void storeu( complex<double>* address, const SIMDcdouble& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+
+#if BLAZE_MIC_MODE
+ _mm512_packstorelo_pd( reinterpret_cast<double*>( address ), value.value );
+ _mm512_packstorehi_pd( reinterpret_cast<double*>( address+4UL ), value.value );
+#elif BLAZE_AVX_MODE
+ _mm256_storeu_pd( reinterpret_cast<double*>( address ), value.value );
+#elif BLAZE_SSE2_MODE
+ _mm_storeu_pd( reinterpret_cast<double*>( address ), value.value );
+#else
+ *address = value.value;
+#endif
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Stream.h b/src/cpu/blaze/math/simd/Stream.h
new file mode 100644
index 00000000..91a73f9b
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Stream.h
@@ -0,0 +1,429 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Stream.h
+// \brief Header file for the SIMD stream functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_STREAM_H_
+#define _BLAZE_MATH_SIMD_STREAM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/HasSize.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 1-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 1-byte integral vector to be streamed.
+// \return void
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,1UL> > >
+ stream( T1* address, const SIMDi8<T2>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ _mm256_stream_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 1-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 1-byte integral complex vector to be streamed.
+// \return void
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,1UL> > >
+ stream( complex<T1>* address, const SIMDci8<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ _mm256_stream_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 2-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 2-byte integral vector to be streamed.
+// \return void
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,2UL> > >
+ stream( T1* address, const SIMDi16<T2>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ _mm256_stream_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 2-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 2-byte integral complex vector to be streamed.
+// \return void
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,2UL> > >
+ stream( complex<T1>* address, const SIMDci16<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_AVX2_MODE
+ _mm256_stream_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 4-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 4-byte integral vector to be streamed.
+// \return void
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,4UL> > >
+ stream( T1* address, const SIMDi32<T2>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_epi32( address, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_stream_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 4-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 4-byte integral complex vector to be streamed.
+// \return void
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,4UL> > >
+ stream( complex<T1>* address, const SIMDci32<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_epi32( address, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_stream_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 8-byte integral values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 8-byte integral vector to be streamed.
+// \return void
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,8UL> > >
+ stream( T1* address, const SIMDi64<T2>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_epi64( address, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_stream_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 8-byte integral complex values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 8-byte integral complex vector to be streamed.
+// \return void
+*/
+template< typename T1 // Type of the integral value
+ , typename T2 > // Type of the SIMD data type
+BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral<T1>, HasSize<T1,8UL> > >
+ stream( complex<T1>* address, const SIMDci64<T2>& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT( sizeof( complex<T1> ) == 2UL*sizeof( T1 ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_store_epi64( address, (~value).value );
+#elif BLAZE_AVX2_MODE
+ _mm256_stream_si256( reinterpret_cast<__m256i*>( address ), (~value).value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_si128( reinterpret_cast<__m128i*>( address ), (~value).value );
+#else
+ *address = (~value).value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 'float' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'float' vector to be streamed.
+// \return void
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE void stream( float* address, const SIMDf32<T>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_storenr_ps( address, (~value).eval().value );
+#elif BLAZE_AVX_MODE
+ _mm256_stream_ps( address, (~value).eval().value );
+#elif BLAZE_SSE_MODE
+ _mm_stream_ps( address, (~value).eval().value );
+#else
+ *address = (~value).eval().value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 'complex<float>' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'complex<float>' vector to be streamed.
+// \return void
+*/
+BLAZE_ALWAYS_INLINE void stream( complex<float>* address, const SIMDcfloat& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT ( sizeof( complex<float> ) == 2UL*sizeof( float ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_storenr_ps( reinterpret_cast<float*>( address ), value.value );
+#elif BLAZE_AVX_MODE
+ _mm256_stream_ps( reinterpret_cast<float*>( address ), value.value );
+#elif BLAZE_SSE_MODE
+ _mm_stream_ps( reinterpret_cast<float*>( address ), value.value );
+#else
+ *address = value.value;
+#endif
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 'double' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'double' vector to be streamed.
+// \return void
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE void stream( double* address, const SIMDf64<T>& value ) noexcept
+{
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_storenr_pd( address, (~value).eval().value );
+#elif BLAZE_AVX_MODE
+ _mm256_stream_pd( address, (~value).eval().value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_pd( address, (~value).eval().value );
+#else
+ *address = (~value).eval().value;
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned, non-temporal store of a vector of 'complex<double>' values.
+// \ingroup simd
+//
+// \param address The target address.
+// \param value The 'complex<double>' vector to be streamed.
+// \return void
+*/
+BLAZE_ALWAYS_INLINE void stream( complex<double>* address, const SIMDcdouble& value ) noexcept
+{
+ BLAZE_STATIC_ASSERT ( sizeof( complex<double> ) == 2UL*sizeof( double ) );
+ BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" );
+
+#if BLAZE_MIC_MODE
+ _mm512_storenr_pd( reinterpret_cast<double*>( address ), value.value );
+#elif BLAZE_AVX_MODE
+ _mm256_stream_pd( reinterpret_cast<double*>( address ), value.value );
+#elif BLAZE_SSE2_MODE
+ _mm_stream_pd( reinterpret_cast<double*>( address ), value.value );
+#else
+ *address = value.value;
+#endif
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Subtraction.h b/src/cpu/blaze/math/simd/Subtraction.h
new file mode 100644
index 00000000..779aa6a5
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Subtraction.h
@@ -0,0 +1,573 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Subtraction.h
+// \brief Header file for the SIMD subtraction functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_SUBTRACTION_H_
+#define _BLAZE_MATH_SIMD_SUBTRACTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 8-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 8-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator-( const SIMDi8<T>& a, const SIMDi8<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi8( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi8( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 8-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint8
+ operator-( const SIMDi8<T1>& a, const SIMDi8<T2>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi8( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi8( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 8-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator-( const SIMDci8<T>& a, const SIMDci8<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi8( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi8( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 16-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 16-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator-( const SIMDi16<T>& a, const SIMDi16<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 16-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint16
+ operator-( const SIMDi16<T1>& a, const SIMDi16<T2>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 16-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2 and AVX2.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator-( const SIMDci16<T>& a, const SIMDci16<T>& b ) noexcept
+#if BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi16( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi16( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 32-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator-( const SIMDi32<T>& a, const SIMDi32<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 32-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint32
+ operator-( const SIMDi32<T1>& a, const SIMDi32<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 32-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator-( const SIMDci32<T>& a, const SIMDci32<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi32( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi32( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT INTEGRAL SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 64-bit integral SIMD values of the same type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator-( const SIMDi64<T>& a, const SIMDi64<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi64( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 64-bit integral SIMD values of different type.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDuint64
+ operator-( const SIMDi64<T1>& a, const SIMDi64<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi64( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of 64-bit integral complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2, AVX2, and AVX-512.
+*/
+template< typename T > // Type of both operands
+BLAZE_ALWAYS_INLINE const T
+ operator-( const SIMDci64<T>& a, const SIMDci64<T>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_AVX2_MODE
+{
+ return _mm256_sub_epi64( (~a).value, (~b).value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_epi64( (~a).value, (~b).value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of single precision floating point SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDfloat
+ operator-( const SIMDf32<T1>& a, const SIMDf32<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_ps( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_sub_ps( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_sub_ps( (~a).eval().value, (~b).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of single precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcfloat
+ operator-( const SIMDcfloat& a, const SIMDcfloat& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_ps( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_sub_ps( a.value, b.value );
+}
+#elif BLAZE_SSE_MODE
+{
+ return _mm_sub_ps( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of double precision floating point SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+BLAZE_ALWAYS_INLINE const SIMDdouble
+ operator-( const SIMDf64<T1>& a, const SIMDf64<T2>& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_pd( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_sub_pd( (~a).eval().value, (~b).eval().value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_pd( (~a).eval().value, (~b).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction of two vectors of double precision complex SIMD values.
+// \ingroup simd
+//
+// \param a The left-hand side SIMD operand.
+// \param b The right-hand side SIMD operand.
+// \return The result of the subtraction.
+//
+// This operation is only available for SSE2, AVX, and AVX-512.
+*/
+BLAZE_ALWAYS_INLINE const SIMDcdouble
+ operator-( const SIMDcdouble& a, const SIMDcdouble& b ) noexcept
+#if BLAZE_MIC_MODE
+{
+ return _mm512_sub_pd( a.value, b.value );
+}
+#elif BLAZE_AVX_MODE
+{
+ return _mm256_sub_pd( a.value, b.value );
+}
+#elif BLAZE_SSE2_MODE
+{
+ return _mm_sub_pd( a.value, b.value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Tan.h b/src/cpu/blaze/math/simd/Tan.h
new file mode 100644
index 00000000..24805c6e
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Tan.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Tan.h
+// \brief Header file for the SIMD tangent functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_TAN_H_
+#define _BLAZE_MATH_SIMD_TAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Tangent of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat tan( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_tan_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_tan_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_tan_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Tangent of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble tan( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_tan_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_tan_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_tan_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/simd/Tanh.h b/src/cpu/blaze/math/simd/Tanh.h
new file mode 100644
index 00000000..69f3e569
--- /dev/null
+++ b/src/cpu/blaze/math/simd/Tanh.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/simd/Tanh.h
+// \brief Header file for the SIMD hyperbolic tangent functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SIMD_TANH_H_
+#define _BLAZE_MATH_SIMD_TANH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/BasicTypes.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Vectorization.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// 32-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Hyperbolic tangent of a vector of single precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of single precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDfloat tanh( const SIMDf32<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_tanh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_tanh_ps( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_tanh_ps( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// 64-BIT FLOATING POINT SIMD TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Hyperbolic tangent of a vector of double precision floating point values.
+// \ingroup simd
+//
+// \param a The vector of double precision floating point values.
+// \return The resulting vector.
+//
+// This operation is only available via the SVML for SSE, AVX, and AVX-512.
+*/
+template< typename T > // Type of the operand
+BLAZE_ALWAYS_INLINE const SIMDdouble tanh( const SIMDf64<T>& a ) noexcept
+#if BLAZE_SVML_MODE && BLAZE_MIC_MODE
+{
+ return _mm512_tanh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_AVX_MODE
+{
+ return _mm256_tanh_pd( (~a).eval().value );
+}
+#elif BLAZE_SVML_MODE && BLAZE_SSE_MODE
+{
+ return _mm_tanh_pd( (~a).eval().value );
+}
+#else
+= delete;
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/DenseMatrix.h b/src/cpu/blaze/math/smp/DenseMatrix.h
new file mode 100644
index 00000000..ba8018c9
--- /dev/null
+++ b/src/cpu/blaze/math/smp/DenseMatrix.h
@@ -0,0 +1,53 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/DenseMatrix.h
+// \brief Header file for the dense matrix SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_DENSEMATRIX_H_
+#define _BLAZE_MATH_SMP_DENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/SMP.h>
+
+#if BLAZE_OPENMP_PARALLEL_MODE
+#include <blaze/math/smp/openmp/DenseMatrix.h>
+#elif BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE
+#include <blaze/math/smp/threads/DenseMatrix.h>
+#else
+#include <blaze/math/smp/default/DenseMatrix.h>
+#endif
+
+#endif
diff --git a/src/cpu/blaze/math/smp/DenseVector.h b/src/cpu/blaze/math/smp/DenseVector.h
new file mode 100644
index 00000000..a5fa6e75
--- /dev/null
+++ b/src/cpu/blaze/math/smp/DenseVector.h
@@ -0,0 +1,53 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/DenseVector.h
+// \brief Header file for the dense vector SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_DENSEVECTOR_H_
+#define _BLAZE_MATH_SMP_DENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/SMP.h>
+
+#if BLAZE_OPENMP_PARALLEL_MODE
+#include <blaze/math/smp/openmp/DenseVector.h>
+#elif BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE
+#include <blaze/math/smp/threads/DenseVector.h>
+#else
+#include <blaze/math/smp/default/DenseVector.h>
+#endif
+
+#endif
diff --git a/src/cpu/blaze/math/smp/Functions.h b/src/cpu/blaze/math/smp/Functions.h
new file mode 100644
index 00000000..0cd19905
--- /dev/null
+++ b/src/cpu/blaze/math/smp/Functions.h
@@ -0,0 +1,53 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/Functions.h
+// \brief Header file for SMP utility functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_FUNCTIONS_H_
+#define _BLAZE_MATH_SMP_FUNCTIONS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/SMP.h>
+
+#if BLAZE_OPENMP_PARALLEL_MODE
+#include <blaze/math/smp/openmp/Functions.h>
+#elif BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE
+#include <blaze/math/smp/threads/Functions.h>
+#else
+#include <blaze/math/smp/default/Functions.h>
+#endif
+
+#endif
diff --git a/src/cpu/blaze/math/smp/ParallelSection.h b/src/cpu/blaze/math/smp/ParallelSection.h
new file mode 100644
index 00000000..8a0b9909
--- /dev/null
+++ b/src/cpu/blaze/math/smp/ParallelSection.h
@@ -0,0 +1,252 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/ParallelSection.h
+// \brief Header file for the parallel section implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_PARALLELSECTION_H_
+#define _BLAZE_MATH_SMP_PARALLELSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Exception.h>
+#include <blaze/util/Suffix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Section for the debugging of the shared-memory parallelization.
+// \ingroup smp
+//
+// The ParallelSection class is an auxiliary helper class for the \a BLAZE_PARALLEL_SECTION macro.
+// It provides the functionality to detected whether a parallel section has been started and with
+// that serves as a utility for debugging the shared-memory parallelization.
+*/
+template< typename T >
+class ParallelSection
+{
+ public:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ inline ParallelSection( bool activate );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~ParallelSection();
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator bool() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ static bool active_; //!< Activity flag for the parallel section.
+ /*!< In case a parallel section is active (i.e. the currently executed
+ code is inside a parallel section), the flag is set to \a true,
+ otherwise it is \a false. */
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend bool isParallelSectionActive();
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T >
+bool ParallelSection<T>::active_ = false;
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the ParallelSection class.
+//
+// \param activate Activation flag for the parallel section.
+// \exception std::runtime_error Nested parallel sections detected.
+*/
+template< typename T >
+inline ParallelSection<T>::ParallelSection( bool activate )
+{
+ if( active_ ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Nested parallel sections detected" );
+ }
+
+ active_ = activate;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Destructor of the ParallelSection class.
+*/
+template< typename T >
+inline ParallelSection<T>::~ParallelSection()
+{
+ active_ = false; // Resetting the activity flag
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to \a bool.
+//
+// The conversion operator returns \a true in case a parallel section is active and \a false
+// otherwise.
+*/
+template< typename T >
+inline ParallelSection<T>::operator bool() const
+{
+ return active_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name ParallelSection functions */
+//@{
+inline bool isParallelSectionActive();
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether a parallel section is active or not.
+// \ingroup smp
+//
+// \return \a true if a parallel section is active, \a false if not.
+*/
+inline bool isParallelSectionActive()
+{
+ return ParallelSection<int>::active_;
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// PARALLEL SECTION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Section for the debugging of the shared-memory parallelization.
+// \ingroup smp
+//
+// During the shared-memory parallel (SMP) execution of an operation nested calls to the SMP
+// assign functions are conceptually not allowed. In other words, it is not allowed to call a
+// SMP assign function from within a non-SMP assign function. The BLAZE_PARALLEL_SECTION macro
+// can be used to mark the start of a parallel section and with that detect nested SMP assign
+// function calls. In case a nested use of a parallel section is detected, a \a std::runtime_error
+// exception is thrown.\n
+// Note that this macro is reserved for internal debugging purposes only and therefore must \b NOT
+// be used explicitly! Using this macro might result in erroneous results, runtime or compilation
+// errors.
+*/
+#define BLAZE_PARALLEL_SECTION \
+ if( blaze::ParallelSection<int> BLAZE_JOIN( parallelSection, __LINE__ ) = true )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/SMP.h b/src/cpu/blaze/math/smp/SMP.h
new file mode 100644
index 00000000..cc4407c7
--- /dev/null
+++ b/src/cpu/blaze/math/smp/SMP.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/SMP.h
+// \brief Shared memory parallelization (SMP) module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_SMP_H_
+#define _BLAZE_MATH_SMP_SMP_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup smp Shared memory parallelization module
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/smp/SerialSection.h b/src/cpu/blaze/math/smp/SerialSection.h
new file mode 100644
index 00000000..17283826
--- /dev/null
+++ b/src/cpu/blaze/math/smp/SerialSection.h
@@ -0,0 +1,268 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/SerialSection.h
+// \brief Header file for the serial section implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_SERIALSECTION_H_
+#define _BLAZE_MATH_SMP_SERIALSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Exception.h>
+#include <blaze/util/Suffix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Section to enforce the serial execution of operations.
+// \ingroup smp
+//
+// The SerialSection class is an auxiliary helper class for the \a BLAZE_SERIAL_SECTION macro.
+// It provides the functionality to detect whether a serial section is active, i.e. if the
+// currently executed code is inside a serial section.
+*/
+template< typename T >
+class SerialSection
+{
+ public:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ inline SerialSection( bool activate );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~SerialSection();
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator bool() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ static bool active_; //!< Activity flag for the serial section.
+ /*!< In case a serial section is active (i.e. the currently executed
+ code is inside a serial section), the flag is set to \a true,
+ otherwise it is \a false. */
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend bool isSerialSectionActive();
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T >
+bool SerialSection<T>::active_ = false;
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the SerialSection class.
+//
+// \param activate Activation flag for the serial section.
+// \exception std::runtime_error Nested serial sections detected.
+*/
+template< typename T >
+inline SerialSection<T>::SerialSection( bool activate )
+{
+ if( active_ ) {
+ BLAZE_THROW_RUNTIME_ERROR( "Nested serial sections detected" );
+ }
+
+ active_ = activate;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Destructor of the SerialSection class.
+*/
+template< typename T >
+inline SerialSection<T>::~SerialSection()
+{
+ active_ = false; // Resetting the activity flag
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to \a bool.
+//
+// The conversion operator returns \a true in case a serial section is active and \a false
+// otherwise.
+*/
+template< typename T >
+inline SerialSection<T>::operator bool() const
+{
+ return active_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SerialSection functions */
+//@{
+inline bool isSerialSectionActive();
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether a serial section is active or not.
+// \ingroup smp
+//
+// \return \a true if a serial section is active, \a false if not.
+*/
+inline bool isSerialSectionActive()
+{
+ return SerialSection<int>::active_;
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// SERIAL SECTION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Section to enforce the serial execution of operations.
+// \ingroup smp
+//
+// This macro provides the option to start a serial section to enforce the serial execution of
+// operations. The following example demonstrates how a serial section is used:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnVector;
+
+ blaze::DynamicMatrix<double,rowMajor> A;
+ blaze::DynamicVector<double,columnVector> b, c, d, x, y, z;
+
+ // ... Resizing and initialization
+
+ // Start of a serial section
+ // All operations executed within the serial section are guaranteed to be executed in
+ // serial (even if a parallel execution would be possible and/or beneficial).
+ BLAZE_SERIAL_SECTION {
+ x = A * b;
+ y = A * c;
+ z = A * d;
+ }
+ \endcode
+
+// Note that it is not allowed to use nested serial sections (i.e. a serial section within
+// another serial section). In case the nested use of a serial section is detected, a
+// \a std::runtime_error exception is thrown.
+*/
+#define BLAZE_SERIAL_SECTION \
+ if( blaze::SerialSection<int> BLAZE_JOIN( serialSection, __LINE__ ) = true )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/SparseMatrix.h b/src/cpu/blaze/math/smp/SparseMatrix.h
new file mode 100644
index 00000000..de64a3c7
--- /dev/null
+++ b/src/cpu/blaze/math/smp/SparseMatrix.h
@@ -0,0 +1,45 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/SparseMatrix.h
+// \brief Header file for the sparse matrix SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_SPARSEMATRIX_H_
+#define _BLAZE_MATH_SMP_SPARSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/smp/default/SparseMatrix.h>
+
+#endif
diff --git a/src/cpu/blaze/math/smp/SparseVector.h b/src/cpu/blaze/math/smp/SparseVector.h
new file mode 100644
index 00000000..33bed922
--- /dev/null
+++ b/src/cpu/blaze/math/smp/SparseVector.h
@@ -0,0 +1,45 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/SparseVector.h
+// \brief Header file for the sparse vector SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_SPARSEVECTOR_H_
+#define _BLAZE_MATH_SMP_SPARSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/smp/default/SparseVector.h>
+
+#endif
diff --git a/src/cpu/blaze/math/smp/default/DenseMatrix.h b/src/cpu/blaze/math/smp/default/DenseMatrix.h
new file mode 100644
index 00000000..ceced7ed
--- /dev/null
+++ b/src/cpu/blaze/math/smp/default/DenseMatrix.h
@@ -0,0 +1,193 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/default/DenseMatrix.h
+// \brief Header file for the default dense matrix SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_DEFAULT_DENSEMATRIX_H_
+#define _BLAZE_MATH_SMP_DEFAULT_DENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Dense matrix SMP functions */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline EnableIf_< IsDenseMatrix<MT1> >
+ smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline EnableIf_< IsDenseMatrix<MT1> >
+ smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline EnableIf_< IsDenseMatrix<MT1> >
+ smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP assignment of a matrix to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \return void
+//
+// This function implements the default SMP assignment of a matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsDenseMatrix<MT1> >
+ smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ assign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP addition assignment of a matrix to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be added.
+// \return void
+//
+// This function implements the default SMP addition assignment of a matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsDenseMatrix<MT1> >
+ smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+//
+// This function implements the default SMP subtraction assignment of a matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsDenseMatrix<MT1> >
+ smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( !BLAZE_OPENMP_PARALLEL_MODE );
+BLAZE_STATIC_ASSERT( !BLAZE_CPP_THREADS_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/default/DenseVector.h b/src/cpu/blaze/math/smp/default/DenseVector.h
new file mode 100644
index 00000000..5964a23b
--- /dev/null
+++ b/src/cpu/blaze/math/smp/default/DenseVector.h
@@ -0,0 +1,253 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/default/DenseVector.h
+// \brief Header file for the default dense vector SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_DEFAULT_DENSEVECTOR_H_
+#define _BLAZE_MATH_SMP_DEFAULT_DENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Vector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Dense vector SMP functions */
+//@{
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsDenseVector<VT1> >
+ smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsDenseVector<VT1> >
+ smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsDenseVector<VT1> >
+ smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsDenseVector<VT1> >
+ smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsDenseVector<VT1> >
+ smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP assignment of a vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default SMP assignment of a vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsDenseVector<VT1> >
+ smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ assign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP addition assignment of a vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be added.
+// \return void
+//
+// This function implements the default SMP addition assignment of a vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsDenseVector<VT1> >
+ smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ addAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP subtraction assignment of a vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be subtracted.
+// \return void
+//
+// This function implements the default SMP subtraction assignment of a vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsDenseVector<VT1> >
+ smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ subAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP multiplication assignment of a vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be multiplied.
+// \return void
+//
+// This function implements the default SMP multiplication assignment of a vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsDenseVector<VT1> >
+ smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ multAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP division assignment of a vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector divisor.
+// \return void
+//
+// This function implements the default SMP division assignment of a vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsDenseVector<VT1> >
+ smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ divAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( !BLAZE_OPENMP_PARALLEL_MODE );
+BLAZE_STATIC_ASSERT( !BLAZE_CPP_THREADS_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/default/Functions.h b/src/cpu/blaze/math/smp/default/Functions.h
new file mode 100644
index 00000000..e520ee94
--- /dev/null
+++ b/src/cpu/blaze/math/smp/default/Functions.h
@@ -0,0 +1,154 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/default/Functions.h
+// \brief Header file for the default SMP utility functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_DEFAULT_FUNCTIONS_H_
+#define _BLAZE_MATH_SMP_DEFAULT_FUNCTIONS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SMP UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SMP utility functions */
+//@{
+BLAZE_ALWAYS_INLINE size_t getNumThreads ();
+BLAZE_ALWAYS_INLINE void setNumThreads ( size_t number );
+BLAZE_ALWAYS_INLINE void shutDownThreads();
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of threads used for thread parallel operations.
+// \ingroup smp
+//
+// \return The number of threads used for thread parallel operations.
+//
+// Via this function the number of threads used for thread parallel operations can be queried.
+// Note that in case no parallelization is active the function will always return 1.
+*/
+BLAZE_ALWAYS_INLINE size_t getNumThreads()
+{
+ return 1UL;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sets the number of threads to be used for thread parallel operations.
+// \ingroup smp
+//
+// \param number The given number of threads \f$[1..\infty)\f$.
+// \return void
+// \exception std::invalid_argument Invalid number of threads.
+//
+// Via this function the maximum number of threads for thread parallel operations can be specified.
+// Note that the given \a number must be in the range \f$[1..\infty)\f$. In case an invalid
+// number of threads is specified, a \a std::invalid_argument exception is thrown. Also note that
+// in case no parallelization is active, the function has no effect.
+*/
+BLAZE_ALWAYS_INLINE void setNumThreads( size_t number )
+{
+ UNUSED_PARAMETER( number );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Provides a reliable shutdown of C++11 threads for Visual Studio compilers.
+// \ingroup smp
+//
+// \return void
+//
+// There is a known issue in Visual Studio 2012 and 2013 that may cause C++11 threads to hang
+// if their destructor is executed after the \c main() function:
+//
+// http://connect.microsoft.com/VisualStudio/feedback/details/747145
+//
+// This function, which has only an effect for Visual Studio compilers, provides a reliable way
+// to circumvent this problem. If called directly before the end of the \c main() function it
+// blocks until all threads have been destroyed:
+
+ \code
+ int main()
+ {
+ // ... Using the C++11 thread parallelization of Blaze
+
+ shutDownThreads();
+ }
+ \endcode
+*/
+BLAZE_ALWAYS_INLINE void shutDownThreads()
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( !BLAZE_OPENMP_PARALLEL_MODE );
+BLAZE_STATIC_ASSERT( !BLAZE_CPP_THREADS_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/default/SparseMatrix.h b/src/cpu/blaze/math/smp/default/SparseMatrix.h
new file mode 100644
index 00000000..9e289b50
--- /dev/null
+++ b/src/cpu/blaze/math/smp/default/SparseMatrix.h
@@ -0,0 +1,171 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/default/SparseMatrix.h
+// \brief Header file for the default sparse matrix SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_DEFAULT_SPARSEMATRIX_H_
+#define _BLAZE_MATH_SMP_DEFAULT_SPARSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Sparse matrix SMP functions */
+//@{
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline EnableIf_< IsSparseMatrix<MT1> >
+ smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline EnableIf_< IsSparseMatrix<MT1> >
+ smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs );
+
+template< typename MT1, bool SO1, typename MT2, bool SO2 >
+inline EnableIf_< IsSparseMatrix<MT1> >
+ smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP assignment of a matrix to a sparse matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side sparse matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \return void
+//
+// This function implements the default SMP assignment of a matrix to a sparse matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , bool SO1 // Storage order of the left-hand side sparse matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsSparseMatrix<MT1> >
+ smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ assign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP addition assignment of a matrix to a sparse matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side sparse matrix.
+// \param rhs The right-hand side matrix to be added.
+// \return void
+//
+// This function implements the default SMP addition assignment of a matrix to a sparse matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , bool SO1 // Storage order of the left-hand side sparse matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsSparseMatrix<MT1> >
+ smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP subtraction assignment of a matrix to sparse matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side sparse matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+//
+// This function implements the default SMP subtraction assignment of a matrix to a sparse matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side sparse matrix
+ , bool SO1 // Storage order of the left-hand side sparse matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsSparseMatrix<MT1> >
+ smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/default/SparseVector.h b/src/cpu/blaze/math/smp/default/SparseVector.h
new file mode 100644
index 00000000..3c9a41fe
--- /dev/null
+++ b/src/cpu/blaze/math/smp/default/SparseVector.h
@@ -0,0 +1,200 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/default/SparseVector.h
+// \brief Header file for the default sparse vector SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_DEFAULT_SPARSEVECTOR_H_
+#define _BLAZE_MATH_SMP_DEFAULT_SPARSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/Vector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Sparse vector SMP functions */
+//@{
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsSparseVector<VT1> >
+ smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsSparseVector<VT1> >
+ smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsSparseVector<VT1> >
+ smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+
+template< typename VT1, bool TF1, typename VT2, bool TF2 >
+inline EnableIf_< IsSparseVector<VT1> >
+ smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP assignment of a vector to a sparse vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side sparse vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default SMP assignment of a vector to a sparse vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , bool TF1 // Transpose flag of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsSparseVector<VT1> >
+ smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ assign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP addition assignment of a vector to a sparse vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side sparse vector.
+// \param rhs The right-hand side vector to be added.
+// \return void
+//
+// This function implements the default SMP addition assignment of a vector to a sparse vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , bool TF1 // Transpose flag of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsSparseVector<VT1> >
+ smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ addAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP subtraction assignment of a vector to a sparse vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side sparse vector.
+// \param rhs The right-hand side vector to be subtracted.
+// \return void
+//
+// This function implements the default SMP subtraction assignment of a vector to a sparse
+// vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , bool TF1 // Transpose flag of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsSparseVector<VT1> >
+ smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ subAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the SMP multiplication assignment of a vector to a sparse vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side sparse vector.
+// \param rhs The right-hand side vector to be multiplied.
+// \return void
+//
+// This function implements the default SMP multiplication assignment of a vector to a sparse
+// vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , bool TF1 // Transpose flag of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< IsSparseVector<VT1> >
+ smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+ multAssign( ~lhs, ~rhs );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/openmp/DenseMatrix.h b/src/cpu/blaze/math/smp/openmp/DenseMatrix.h
new file mode 100644
index 00000000..d3a9b07f
--- /dev/null
+++ b/src/cpu/blaze/math/smp/openmp/DenseMatrix.h
@@ -0,0 +1,1165 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/openmp/DenseMatrix.h
+// \brief Header file for the OpenMP-based dense matrix SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_OPENMP_DENSEMATRIX_H_
+#define _BLAZE_MATH_SMP_OPENMP_DENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <omp.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SMPAssignable.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/simd/SIMDTrait.h>
+#include <blaze/math/smp/ParallelSection.h>
+#include <blaze/math/smp/SerialSection.h>
+#include <blaze/math/StorageOrder.h>
+#include <blaze/math/Submatrix.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// PLAIN ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP assignment of a row-major dense matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major dense matrix to be assigned.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP assignment of a row-major
+// dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).rows() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t rowsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ assign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ assign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ assign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ assign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP assignment of a column-major dense matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major dense matrix to be assigned.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP assignment of a column-major
+// dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).columns() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t colsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ assign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ assign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ assign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ assign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP assignment of a row-major sparse matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major sparse matrix to be assigned.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP assignment of a row-major
+// sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t rowsPerThread( (~lhs).rows() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ assign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP assignment of a column-major sparse matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major sparse matrix to be assigned.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP assignment of a column-major
+// sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t colsPerThread( (~lhs).columns() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ assign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP assignment to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \return void
+//
+// This function implements the default OpenMP-based SMP assignment to a dense matrix. Due to
+// the explicit application of the SFINAE principle, this function can only be selected by the
+// compiler in case both operands are SMP-assignable and the element types of both operands are
+// not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>
+ , Or< Not< IsSMPAssignable<MT1> >
+ , Not< IsSMPAssignable<MT2> > > > >
+ smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ assign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the OpenMP-based SMP assignment to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major sparse matrix to be assigned.
+// \return void
+//
+// This function implements the OpenMP-based SMP assignment to a dense matrix. Due to the
+// explicit application of the SFINAE principle, this function can only be selected by the
+// compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
+ smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ assign( ~lhs, ~rhs );
+ }
+ else {
+#pragma omp parallel shared( lhs, rhs )
+ smpAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDITION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP addition assignment of a row-major dense matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major dense matrix to be added.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP addition assignment of a
+// row-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpAddAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).rows() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t rowsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ addAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ addAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ addAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ addAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP addition assignment of a column-major dense matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major dense matrix to be added.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP addition assignment of a
+// column-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpAddAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).columns() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t colsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ addAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ addAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ addAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ addAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP addition assignment of a row-major sparse matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major sparse matrix to be added.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP addition assignment of a
+// row-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpAddAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t rowsPerThread( (~lhs).rows() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ addAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP addition assignment of a column-major sparse matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major sparse matrix to be added.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP addition assignment of a
+// column-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpAddAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t colsPerThread( (~lhs).columns() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ addAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP addition assignment to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be added.
+// \return void
+//
+// This function implements the default OpenMP-based SMP addition assignment to a dense matrix.
+// Due to the explicit application of the SFINAE principle, this function can only be selected
+// by the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>
+ , Or< Not< IsSMPAssignable<MT1> >
+ , Not< IsSMPAssignable<MT2> > > > >
+ smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the OpenMP-based SMP addition assignment to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major dense matrix to be added.
+// \return void
+//
+// This function implements the OpenMP-based SMP addition assignment to a dense matrix. Due to
+// the explicit application of the SFINAE principle, this function can only be selected by the
+// compiler in case both operands are SMP-assignable and the element types of both operands are
+// not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
+ smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ addAssign( ~lhs, ~rhs );
+ }
+ else {
+#pragma omp parallel shared( lhs, rhs )
+ smpAddAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRACTION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP subtraction assignment of a row-major dense matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major dense matrix to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP subtraction assignment
+// of a row-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpSubAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).rows() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t rowsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ subAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ subAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ subAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ subAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP subtraction assignment of a column-major dense matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major dense matrix to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP subtraction assignment
+// of a column-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpSubAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).columns() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t colsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ subAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ subAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ subAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ subAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP subtraction assignment of a row-major sparse matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major sparse matrix to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP subtraction assignment
+// of a row-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpSubAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t rowsPerThread( (~lhs).rows() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ subAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP subtraction assignment of a column-major sparse matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major sparse matrix to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP subtraction assignment
+// of a column-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpSubAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t colsPerThread( (~lhs).columns() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ subAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP subtracction assignment to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+//
+// This function implements the default OpenMP-based SMP subtraction assignment to a dense matrix.
+// Due to the explicit application of the SFINAE principle, this function can only be selected by
+// the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>
+ , Or< Not< IsSMPAssignable<MT1> >
+ , Not< IsSMPAssignable<MT2> > > > >
+ smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the OpenMP-based SMP subtracction assignment to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+//
+// This function implements the default OpenMP-based SMP subtraction assignment of a matrix to a
+// dense matrix. Due to the explicit application of the SFINAE principle, this function can only
+// be selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
+ smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ subAssign( ~lhs, ~rhs );
+ }
+ else {
+#pragma omp parallel shared( lhs, rhs )
+ smpSubAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTIPLICATION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP multiplication assignment to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be multiplied.
+// \return void
+//
+// This function implements the default OpenMP-based SMP multiplication assignment to a dense
+// matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsDenseMatrix<MT1> >
+ smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( BLAZE_OPENMP_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/openmp/DenseVector.h b/src/cpu/blaze/math/smp/openmp/DenseVector.h
new file mode 100644
index 00000000..3ce0f91f
--- /dev/null
+++ b/src/cpu/blaze/math/smp/openmp/DenseVector.h
@@ -0,0 +1,1129 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/openmp/DenseVector.h
+// \brief Header file for the OpenMP-based dense vector SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_OPENMP_DENSEVECTOR_H_
+#define _BLAZE_MATH_SMP_OPENMP_DENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <omp.h>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SMPAssignable.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/simd/SIMDTrait.h>
+#include <blaze/math/smp/ParallelSection.h>
+#include <blaze/math/smp/SerialSection.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/math/views/Subvector.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// PLAIN ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP assignment of a dense vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP assignment of a dense
+// vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ assign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ assign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ assign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ assign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP assignment of a sparse vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP assignment of a sparse
+// vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+void smpAssign_backend( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t sizePerThread( (~lhs).size() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ assign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default OpenMP-based SMP assignment to a dense vector. Due to
+// the explicit application of the SFINAE principle, this function can only be selected by the
+// compiler in case both operands are SMP-assignable and the element types of both operands are
+// not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ assign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the OpenMP-based SMP assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function performs the OpenMP-based SMP assignment to a dense vector. Due to the
+// explicit application of the SFINAE principle, this function can only be selected by the
+// compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ assign( ~lhs, ~rhs );
+ }
+ else {
+#pragma omp parallel shared( lhs, rhs )
+ smpAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDITION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP addition assignment of a dense vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function is the backend implementation the OpenMP-based SMP addition assignment of a
+// dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpAddAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ addAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ addAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ addAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ addAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP addition assignment of a sparse vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function is the backend implementation the OpenMP-based SMP addition assignment of a
+// sparse vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+void smpAddAssign_backend( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t sizePerThread( (~lhs).size() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ addAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP addition assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be added.
+// \return void
+//
+// This function implements the default OpenMP-based SMP addition assignment to a dense vector.
+// Due to the explicit application of the SFINAE principle, this function can only be selected
+// by the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the OpenMP-based SMP addition assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function implements the OpenMP-based SMP addition assignment to a dense vector. Due to
+// the explicit application of the SFINAE principle, this function can only be selected by the
+// compiler in case both operands are SMP-assignable and the element types of both operands are
+// not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ addAssign( ~lhs, ~rhs );
+ }
+ else {
+#pragma omp parallel shared( lhs, rhs )
+ smpAddAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRACTION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP subtraction assignment of a dense vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function is the backend implementation the OpenMP-based SMP subtraction assignment of a
+// dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpSubAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ subAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ subAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ subAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ subAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP subtraction assignment of a sparse vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP subtraction assignment of
+// a sparse vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+void smpSubAssign_backend( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t sizePerThread( (~lhs).size() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ subAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP subtraction assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be subtracted.
+// \return void
+//
+// This function implements the default OpenMP-based SMP subtraction assignment of a vector to
+// a dense vector. Due to the explicit application of the SFINAE principle, this function can
+// only be selected by the compiler in case both operands are SMP-assignable and the element
+// types of both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the OpenMP-based SMP subtraction assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function implements the OpenMP-based SMP subtraction assignment to a dense vector. Due
+// to the explicit application of the SFINAE principle, this function can only be selected by
+// the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ subAssign( ~lhs, ~rhs );
+ }
+ else {
+#pragma omp parallel shared( lhs, rhs )
+ smpSubAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTIPLICATION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP multiplication assignment of a dense vector to a
+// dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP multiplication assignment
+// of a dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpMultAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ multAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ multAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ multAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ multAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP multiplication assignment of a sparse vector to a
+// dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP multiplication assignment
+// of a sparse vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+void smpMultAssign_backend( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t sizePerThread( (~lhs).size() / threads + addon );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ multAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP multiplication assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be multiplied.
+// \return void
+//
+// This function implements the default OpenMP-based SMP multiplication assignment to a dense
+// vector. Due to the explicit application of the SFINAE principle, this function can only be
+// selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the OpenMP-based SMP multiplication assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function implements the OpenMP-based SMP multiplication assignment to a dense vector.
+// Due to the explicit application of the SFINAE principle, this function can only be selected
+// by the compiler in case both operands are SMP-assignable and the element types of both
+// operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ multAssign( ~lhs, ~rhs );
+ }
+ else {
+#pragma omp parallel shared( lhs, rhs )
+ smpMultAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVISION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the OpenMP-based SMP division assignment of a dense vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function is the backend implementation of the OpenMP-based SMP division assignment of
+// a dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpDivAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const int threads ( omp_get_num_threads() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+#pragma omp for schedule(dynamic,1) nowait
+ for( int i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ divAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ divAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ divAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ divAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the OpenMP-based SMP division assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector divisor.
+// \return void
+//
+// This function implements the default OpenMP-based SMP division assignment to a dense vector.
+// Due to the explicit application of the SFINAE principle, this function can only be selected
+// by the compiler in case both operands are SMP-assignable and the element types of both
+// operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ divAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the OpenMP-based SMP division assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function implements the OpenMP-based SMP division assignment to a dense vector. Due to
+// the explicit application of the SFINAE principle, this function can only be selected by the
+// compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ divAssign( ~lhs, ~rhs );
+ }
+ else {
+#pragma omp parallel shared( lhs, rhs )
+ smpDivAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( BLAZE_OPENMP_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/openmp/Functions.h b/src/cpu/blaze/math/smp/openmp/Functions.h
new file mode 100644
index 00000000..f0a9fe90
--- /dev/null
+++ b/src/cpu/blaze/math/smp/openmp/Functions.h
@@ -0,0 +1,154 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/openmp/Functions.h
+// \brief Header file for the OpenMP-based SMP utility functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_OPENMP_FUNCTIONS_H_
+#define _BLAZE_MATH_SMP_OPENMP_FUNCTIONS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <omp.h>
+#include <blaze/math/Exception.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SMP UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of threads used for OpenMP parallel operations.
+// \ingroup smp
+//
+// \return The number of threads used for OpenMP parallel operations.
+//
+// Via this function the number of threads used for OpenMP parallel operations can be queried.
+// The function generally reflects the number of threads as set by the OMP_NUM_THREADS environment
+// variable, the \c omp_set_num_threads() library function, or the blaze::setNumThreads() function.
+*/
+BLAZE_ALWAYS_INLINE size_t getNumThreads()
+{
+ return omp_get_max_threads();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Sets the number of threads to be used for OpenMP parallel operations.
+// \ingroup smp
+//
+// \param number The given number of threads \f$[1..\infty)\f$.
+// \return void
+// \exception std::invalid_argument Invalid number of threads.
+//
+// Via this function the maximum number of threads for OpenMP parallel operations can be specified.
+// Note that the given \a number must be in the range \f$[1..infty)\f$. In case an invalid
+// number of threads is specified, a \a std::invalid_argument exception is thrown.
+*/
+BLAZE_ALWAYS_INLINE void setNumThreads( size_t number )
+{
+ if( number == 0UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of threads" );
+ }
+
+ omp_set_num_threads( number );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Provides a reliable shutdown of C++11 threads for Visual Studio compilers.
+// \ingroup smp
+//
+// \return void
+//
+// There is a known issue in Visual Studio 2012 and 2013 that may cause C++11 threads to hang
+// if their destructor is executed after the \c main() function:
+//
+// http://connect.microsoft.com/VisualStudio/feedback/details/747145
+//
+// This function, which has only an effect for Visual Studio compilers, provides a reliable way
+// to circumvent this problem. If called directly before the end of the \c main() function it
+// blocks until all threads have been destroyed:
+
+ \code
+ int main()
+ {
+ // ... Using the C++11 thread parallelization of Blaze
+
+ shutDownThreads();
+ }
+ \endcode
+*/
+BLAZE_ALWAYS_INLINE void shutDownThreads()
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( BLAZE_OPENMP_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/threads/DenseMatrix.h b/src/cpu/blaze/math/smp/threads/DenseMatrix.h
new file mode 100644
index 00000000..a0c07c29
--- /dev/null
+++ b/src/cpu/blaze/math/smp/threads/DenseMatrix.h
@@ -0,0 +1,1182 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/threads/DenseMatrix.h
+// \brief Header file for the C++11/Boost thread-based dense matrix SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_THREADS_DENSEMATRIX_H_
+#define _BLAZE_MATH_SMP_THREADS_DENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SMPAssignable.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/simd/SIMDTrait.h>
+#include <blaze/math/smp/ParallelSection.h>
+#include <blaze/math/smp/SerialSection.h>
+#include <blaze/math/smp/threads/ThreadBackend.h>
+#include <blaze/math/StorageOrder.h>
+#include <blaze/math/Submatrix.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// PLAIN ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP assignment of a row-major dense matrix to a
+// dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major dense matrix to be assigned.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP assignment
+// of a row-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).rows() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t rowsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP assignment of a column-major dense matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major dense matrix to be assigned.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP assignment
+// of a column-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).columns() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t colsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP assignment of a row-major sparse matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major sparse matrix to be assigned.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP assignment
+// of a row-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t rowsPerThread( (~lhs).rows() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP assignment of a column-major sparse matrix
+// to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major sparse matrix to be assigned.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP assignment
+// of a column-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t colsPerThread( (~lhs).columns() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP assignment to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP assignment to a dense matrix.
+// Due to the explicit application of the SFINAE principle, this function can only be selected by
+// the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>
+ , Or< Not< IsSMPAssignable<MT1> >
+ , Not< IsSMPAssignable<MT2> > > > >
+ smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ assign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the C++11/Boost thread-based SMP assignment to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major sparse matrix to be assigned.
+// \return void
+//
+// This function implements the C++11/Boost thread-based SMP assignment to a dense matrix. Due
+// to the explicit application of the SFINAE principle, this function can only be selected by
+// the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
+ smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ assign( ~lhs, ~rhs );
+ }
+ else {
+ smpAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDITION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP addition assignment of a row-major dense
+// matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major dense matrix to be added.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP addition
+// assignment of a row-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpAddAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).rows() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t rowsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP addition assignment of a column-major dense
+// matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major dense matrix to be added.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP addition
+// assignment of a column-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpAddAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).columns() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t colsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP addition assignment of a row-major sparse
+// matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major sparse matrix to be added.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP addition
+// assignment of a row-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpAddAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t rowsPerThread( (~lhs).rows() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP addition assignment of a column-major sparse
+// matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major sparse matrix to be added.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP addition
+// assignment of a column-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpAddAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t colsPerThread( (~lhs).columns() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleAddAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP addition assignment to a
+// dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be added.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP addition assignment to a
+// dense matrix. Due to the explicit application of the SFINAE principle, this function can only
+// be selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>
+ , Or< Not< IsSMPAssignable<MT1> >
+ , Not< IsSMPAssignable<MT2> > > > >
+ smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ addAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the C++11/Boost thread-based SMP addition assignment to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major dense matrix to be added.
+// \return void
+//
+// This function implements the C++11/Boost thread-based SMP addition assignment to a dense matrix.
+// Due to the explicit application of the SFINAE principle, this function can only be selected by
+// the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
+ smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ addAssign( ~lhs, ~rhs );
+ }
+ else {
+ smpAddAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRACTION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP subtraction assignment of a row-major dense
+// matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major dense matrix to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP subtraction
+// assignment of a row-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpSubAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).rows() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t rowsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<aligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP subtraction assignment of a column-major
+// dense matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major dense matrix to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP subtraction
+// assignment of a column-major dense matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side dense matrix
+void smpSubAssign_backend( DenseMatrix<MT1,SO>& lhs, const DenseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<MT1> >::size };
+
+ const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).columns() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t colsPerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( submatrix<aligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<aligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ else {
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP subtraction assignment of a row-major sparse
+// matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side row-major sparse matrix to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP subtraction
+// assignment of a row-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpSubAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,rowMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).rows() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t rowsPerThread( (~lhs).rows() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t row( i*rowsPerThread );
+
+ if( row >= (~lhs).rows() )
+ continue;
+
+ const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, row, 0UL, m, (~lhs).columns() ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<unaligned>( ~rhs, row, 0UL, m, (~lhs).columns() ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP subtraction assignment of a column-major
+// sparse matrix to a dense matrix.
+// \ingroup math
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side column-major sparse matrix to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP subtraction
+// assignment of a column-major sparse matrix to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO // Storage order of the left-hand side dense matrix
+ , typename MT2 > // Type of the right-hand side sparse matrix
+void smpSubAssign_backend( DenseMatrix<MT1,SO>& lhs, const SparseMatrix<MT2,columnMajor>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<MT1> ET1;
+ typedef ElementType_<MT2> ET2;
+ typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).columns() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t colsPerThread( (~lhs).columns() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t column( i*colsPerThread );
+
+ if( column >= (~lhs).columns() )
+ continue;
+
+ const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
+ UnalignedTarget target( submatrix<unaligned>( ~lhs, 0UL, column, (~lhs).rows(), n ) );
+ TheThreadBackend::scheduleSubAssign( target, submatrix<unaligned>( ~rhs, 0UL, column, (~lhs).rows(), n ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP subtracction assignment to a
+// dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP subtraction assignment to a
+// dense matrix. Due to the explicit application of the SFINAE principle, this function can only
+// be selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>
+ , Or< Not< IsSMPAssignable<MT1> >
+ , Not< IsSMPAssignable<MT2> > > > >
+ smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ subAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the C++11/Boost thread-based SMP subtracction assignment to a dense
+// matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP subtraction assignment of a
+// matrix to a dense matrix. Due to the explicit application of the SFINAE principle, this function
+// can only be selected by the compiler in case both operands are SMP-assignable and the element
+// types of both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side dense matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
+ smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ subAssign( ~lhs, ~rhs );
+ }
+ else {
+ smpSubAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTIPLICATION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP multiplication assignment
+// to a dense matrix.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense matrix.
+// \param rhs The right-hand side matrix to be multiplied.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP multiplication assignment
+// to a dense matrix.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the left-hand side dense matrix
+ , bool SO1 // Storage order of the left-hand side matrix
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< IsDenseMatrix<MT1> >
+ smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ multAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/threads/DenseVector.h b/src/cpu/blaze/math/smp/threads/DenseVector.h
new file mode 100644
index 00000000..c1dcafa1
--- /dev/null
+++ b/src/cpu/blaze/math/smp/threads/DenseVector.h
@@ -0,0 +1,1145 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/threads/DenseVector.h
+// \brief Header file for the C++11/Boost thread-based dense vector SMP implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_THREADS_DENSEVECTOR_H_
+#define _BLAZE_MATH_SMP_THREADS_DENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SMPAssignable.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/simd/SIMDTrait.h>
+#include <blaze/math/smp/ParallelSection.h>
+#include <blaze/math/smp/SerialSection.h>
+#include <blaze/math/smp/threads/ThreadBackend.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/math/views/Subvector.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// PLAIN ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP assignment of a dense vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP assignment
+// of a dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP assignment of a sparse vector to a dense
+// vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP assignment
+// of a sparse vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+void smpAssign_backend( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t sizePerThread( (~lhs).size() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP assignment to a dense vector.
+// Due to the explicit application of the SFINAE principle, this function can only be selected by
+// the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ assign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the C++11/Boost thread-based SMP assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function performs the C++11/Boost thread-based SMP assignment to a dense vector. Due to
+// the explicit application of the SFINAE principle, this function can only be selected by the
+// compiler in case both operands are SMP-assignable and the element types of both operands are
+// not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ assign( ~lhs, ~rhs );
+ }
+ else {
+ smpAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDITION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP addition assignment of a dense vector to a
+// dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP addition
+// assignment of a dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpAddAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAddAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAddAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAddAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAddAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP addition assignment of a sparse vector to
+// a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP addition
+// assignment of a sparse vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+void smpAddAssign_backend( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t sizePerThread( (~lhs).size() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleAddAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP addition assignment to a
+// dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP addition assignment to a
+// dense vector. Due to the explicit application of the SFINAE principle, this function can only
+// be selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ addAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the C++11/Boost thread-based SMP addition assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function performs the C++11/Boost thread-based SMP addition assignment to a dense vector.
+// Due to the explicit application of the SFINAE principle, this function can only be selected by
+// the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ addAssign( ~lhs, ~rhs );
+ }
+ else {
+ smpAddAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRACTION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP subtraction assignment of a dense vector
+// to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP subtraction
+// assignment of a dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpSubAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleSubAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleSubAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleSubAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleSubAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP subtraction assignment of a sparse vector
+// to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP subtraction
+// assignment of a sparse vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+void smpSubAssign_backend( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t sizePerThread( (~lhs).size() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleSubAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP subtraction assignment to a
+// dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP subtraction assignment to a
+// dense vector. Due to the explicit application of the SFINAE principle, this function can only
+// be selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ subAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the C++11/Boost thread-based SMP subtraction assignment to a dense
+// vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function performs the C++11/Boost thread-based SMP subtraction assignment to a dense
+// vector. Due to the explicit application of the SFINAE principle, this function can only be
+// selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ subAssign( ~lhs, ~rhs );
+ }
+ else {
+ smpSubAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTIPLICATION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP multiplication assignment of a dense vector
+// to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP multiplication
+// assignment of a dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpMultAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleMultAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleMultAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleMultAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleMultAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP multiplication assignment of a sparse
+// vector to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP multiplication
+// assignment of a sparse vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+void smpMultAssign_backend( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t sizePerThread( (~lhs).size() / threads + addon );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleMultAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP multiplication assignment
+// to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP multiplication assignment to
+// a dense vector. Due to the explicit application of the SFINAE principle, this function can only
+// be selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ multAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the C++11/Boost thread-based SMP multiplication assignment to a dense
+// vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function performs the C++11/Boost thread-based SMP multiplication assignment to a dense
+// vector. Due to the explicit application of the SFINAE principle, this function can only be
+// selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ multAssign( ~lhs, ~rhs );
+ }
+ else {
+ smpMultAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVISION ASSIGNMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend of the C++11/Boost thread-based SMP division assignment of a dense vector to
+// a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side dense vector division.
+// \return void
+//
+// This function is the backend implementation of the C++11/Boost thread-based SMP division
+// assignment of a dense vector to a dense vector.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF2 > // Transpose flag of the right-hand side dense vector
+void smpDivAssign_backend( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
+
+ typedef ElementType_<VT1> ET1;
+ typedef ElementType_<VT2> ET2;
+ typedef SubvectorExprTrait_<VT1,aligned> AlignedTarget;
+ typedef SubvectorExprTrait_<VT1,unaligned> UnalignedTarget;
+
+ enum : size_t { SIMDSIZE = SIMDTrait< ElementType_<VT1> >::size };
+
+ const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame<ET1,ET2>::value );
+ const bool lhsAligned ( (~lhs).isAligned() );
+ const bool rhsAligned ( (~rhs).isAligned() );
+
+ const size_t threads ( TheThreadBackend::size() );
+ const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
+ const size_t equalShare ( (~lhs).size() / threads + addon );
+ const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
+ const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
+
+ for( size_t i=0UL; i<threads; ++i )
+ {
+ const size_t index( i*sizePerThread );
+
+ if( index >= (~lhs).size() )
+ continue;
+
+ const size_t size( min( sizePerThread, (~lhs).size() - index ) );
+
+ if( simdEnabled && lhsAligned && rhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleDivAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && lhsAligned ) {
+ AlignedTarget target( subvector<aligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleDivAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ else if( simdEnabled && rhsAligned ) {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleDivAssign( target, subvector<aligned>( ~rhs, index, size ) );
+ }
+ else {
+ UnalignedTarget target( subvector<unaligned>( ~lhs, index, size ) );
+ TheThreadBackend::scheduleDivAssign( target, subvector<unaligned>( ~rhs, index, size ) );
+ }
+ }
+
+ TheThreadBackend::wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the C++11/Boost thread-based SMP division assignment to a
+// dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side vector to be assigned.
+// \return void
+//
+// This function implements the default C++11/Boost thread-based SMP division assignment to a
+// dense vector. Due to the explicit application of the SFINAE principle, this function can only
+// be selected by the compiler in case both operands are SMP-assignable and the element types of
+// both operands are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>
+ , Or< Not< IsSMPAssignable<VT1> >
+ , Not< IsSMPAssignable<VT2> > > > >
+ smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ divAssign( ~lhs, ~rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the C++11/Boost thread-based SMP division assignment to a dense vector.
+// \ingroup smp
+//
+// \param lhs The target left-hand side dense vector.
+// \param rhs The right-hand side sparse vector divisor.
+// \return void
+//
+// This function performs the C++11/Boost thread-based SMP division assignment to a dense vector.
+// Due to the explicit application of the SFINAE principle, this function can only be selected by
+// the compiler in case both operands are SMP-assignable and the element types of both operands
+// are not SMP-assignable.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , bool TF1 // Transpose flag of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side vector
+ , bool TF2 > // Transpose flag of the right-hand side vector
+inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
+ smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
+
+ BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_PARALLEL_SECTION
+ {
+ if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
+ divAssign( ~lhs, ~rhs );
+ }
+ else {
+ smpDivAssign_backend( ~lhs, ~rhs );
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/threads/Functions.h b/src/cpu/blaze/math/smp/threads/Functions.h
new file mode 100644
index 00000000..0cb09b73
--- /dev/null
+++ b/src/cpu/blaze/math/smp/threads/Functions.h
@@ -0,0 +1,156 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/threads/Functions.h
+// \brief Header file for the C++11 and Boost thread-based SMP utility functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_THREADS_FUNCTIONS_H_
+#define _BLAZE_MATH_SMP_THREADS_FUNCTIONS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Exception.h>
+#include <blaze/math/smp/threads/ThreadBackend.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SMP UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of threads used for thread parallel operations.
+// \ingroup smp
+//
+// \return The number of threads used for thread parallel operations.
+//
+// Via this function the number of threads used for thread parallel operations can be queried.
+*/
+BLAZE_ALWAYS_INLINE size_t getNumThreads()
+{
+ return TheThreadBackend::size();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Sets the number of threads to be used for thread parallel operations.
+// \ingroup smp
+//
+// \param number The given number of threads \f$[1..\infty)\f$.
+// \return void
+// \exception std::invalid_argument Invalid number of threads.
+//
+// Via this function the maximum number of threads for thread parallel operations can be specified.
+// Note that the given \a number must be in the range \f$[1..\infty)\f$. In case an invalid
+// number of threads is specified, a \a std::invalid_argument exception is thrown.
+*/
+BLAZE_ALWAYS_INLINE void setNumThreads( size_t number )
+{
+ if( number == 0UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of threads" );
+ }
+
+ TheThreadBackend::resize( number );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Provides a reliable shutdown of C++11 threads for Visual Studio compilers.
+// \ingroup smp
+//
+// \return void
+//
+// There is a known issue in Visual Studio 2012 and 2013 that may cause C++11 threads to hang
+// if their destructor is executed after the \c main() function:
+//
+// http://connect.microsoft.com/VisualStudio/feedback/details/747145
+//
+// This function, which has only an effect for Visual Studio compilers, provides a reliable way
+// to circumvent this problem. If called directly before the end of the \c main() function it
+// blocks until all threads have been destroyed:
+
+ \code
+ int main()
+ {
+ // ... Using the C++11 thread parallelization of Blaze
+
+ shutDownThreads();
+ }
+ \endcode
+*/
+BLAZE_ALWAYS_INLINE void shutDownThreads()
+{
+#if (defined _MSC_VER)
+ TheThreadBackend::resize( 0UL, true );
+#endif
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/smp/threads/ThreadBackend.h b/src/cpu/blaze/math/smp/threads/ThreadBackend.h
new file mode 100644
index 00000000..62261ccc
--- /dev/null
+++ b/src/cpu/blaze/math/smp/threads/ThreadBackend.h
@@ -0,0 +1,665 @@
+//=================================================================================================
+/*!
+// \file blaze/math/smp/threads/ThreadBackend.h
+// \brief Header file for the C++11 and Boost thread backend
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SMP_THREADS_THREADBACKEND_H_
+#define _BLAZE_MATH_SMP_THREADS_THREADBACKEND_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#if BLAZE_CPP_THREADS_PARALLEL_MODE
+# include <condition_variable>
+# include <mutex>
+# include <thread>
+#elif BLAZE_BOOST_THREADS_PARALLEL_MODE
+# include <boost/thread/condition.hpp>
+# include <boost/thread/mutex.hpp>
+# include <boost/thread/thread.hpp>
+#endif
+
+#include <cstdlib>
+#include <blaze/math/constraints/Expression.h>
+#include <blaze/math/Functions.h>
+#include <blaze/system/SMP.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/ThreadPool.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend system for the C++11 and Boost thread-based parallelization.
+// \ingroup smp
+//
+// The ThreadBackend class template represents the backend system for the C++11 and Boost
+// thread-based parallelization. It provides the functionality to manage a pool of active
+// threads and to schedule (compound) assignment tasks for execution.\n
+// This class must \b NOT be used explicitly! It is reserved for internal use only. Using
+// this class explicitly might result in erroneous results and/or in undefined behavior.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+class ThreadBackend
+{
+ public:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ static inline size_t size ();
+ static inline void resize( size_t n, bool block=false );
+ static inline void wait ();
+ //@}
+ //**********************************************************************************************
+
+ //**Thread execution functions******************************************************************
+ /*!\name Thread execution functions */
+ //@{
+ template< typename Target, typename Source >
+ static inline void scheduleAssign( Target& target, const Source& source );
+
+ template< typename Target, typename Source >
+ static inline void scheduleAddAssign( Target& target, const Source& source );
+
+ template< typename Target, typename Source >
+ static inline void scheduleSubAssign( Target& target, const Source& source );
+
+ template< typename Target, typename Source >
+ static inline void scheduleMultAssign( Target& target, const Source& source );
+
+ template< typename Target, typename Source >
+ static inline void scheduleDivAssign( Target& target, const Source& source );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Private class Assigner**********************************************************************
+ /*!\brief Auxiliary functor for the threaded execution of a plain assignment.
+ */
+ template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+ struct Assigner
+ {
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the Assigner class template.
+ //
+ // \param target The target operand to be assigned to.
+ // \param source The source operand to be assigned to the target.
+ */
+ explicit inline Assigner( Target& target, const Source& source )
+ : target_( target ) // The target operand
+ , source_( source ) // The source operand
+ {}
+ //*******************************************************************************************
+
+ //**Function call operator*******************************************************************
+ /*!\brief Performs the assignment between the two given operands.
+ //
+ // \return void
+ */
+ inline void operator()() {
+ assign( target_, source_ );
+ }
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ Target target_; //!< The target operand.
+ const Source source_; //!< The source operand.
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Target );
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Source );
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Private class AddAssigner*******************************************************************
+ /*!\brief Auxiliary functor for the threaded execution of an addition assignment.
+ */
+ template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+ struct AddAssigner
+ {
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the AddAssigner class template.
+ //
+ // \param target The target operand to be assigned to.
+ // \param source The source operand to be added to the target.
+ */
+ explicit inline AddAssigner( Target& target, const Source& source )
+ : target_( target ) // The target operand
+ , source_( source ) // The source operand
+ {}
+ //*******************************************************************************************
+
+ //**Function call operator*******************************************************************
+ /*!\brief Performs the addition assignment between the two given operands.
+ //
+ // \return void
+ */
+ inline void operator()() {
+ addAssign( target_, source_ );
+ }
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ Target target_; //!< The target operand.
+ const Source source_; //!< The source operand.
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Target );
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Source );
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Private class SubAssigner*******************************************************************
+ /*!\brief Auxiliary functor for the threaded execution of a subtraction assignment.
+ */
+ template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+ struct SubAssigner
+ {
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SubAssigner class template.
+ //
+ // \param target The target operand to be assigned to.
+ // \param source The source operand to be subtracted from the target.
+ */
+ explicit inline SubAssigner( Target& target, const Source& source )
+ : target_( target ) // The target operand
+ , source_( source ) // The source operand
+ {}
+ //*******************************************************************************************
+
+ //**Function call operator*******************************************************************
+ /*!\brief Performs the subtraction assignment between the two given operands.
+ //
+ // \return void
+ */
+ inline void operator()() {
+ subAssign( target_, source_ );
+ }
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ Target target_; //!< The target operand.
+ const Source source_; //!< The source operand.
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Target );
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Source );
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Private class MultAssigner******************************************************************
+ /*!\brief Auxiliary functor for the threaded execution of a multiplication assignment.
+ */
+ template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+ struct MultAssigner
+ {
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the MultAssigner class template.
+ //
+ // \param target The target operand to be assigned to.
+ // \param source The source operand to be multiplied with the target.
+ */
+ explicit inline MultAssigner( Target& target, const Source& source )
+ : target_( target ) // The target operand
+ , source_( source ) // The source operand
+ {}
+ //*******************************************************************************************
+
+ //**Function call operator*******************************************************************
+ /*!\brief Performs the multiplication assignment between the two given operands.
+ //
+ // \return void
+ */
+ inline void operator()() {
+ multAssign( target_, source_ );
+ }
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ Target target_; //!< The target operand.
+ const Source source_; //!< The source operand.
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Target );
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Source );
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Private class DivAssigner*******************************************************************
+ /*!\brief Auxiliary functor for the threaded execution of a division assignment.
+ */
+ template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+ struct DivAssigner
+ {
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the DivAssigner class template.
+ //
+ // \param target The target operand to be assigned to.
+ // \param source The source operand to be divided from the target.
+ */
+ explicit inline DivAssigner( Target& target, const Source& source )
+ : target_( target ) // The target operand
+ , source_( source ) // The source operand
+ {}
+ //*******************************************************************************************
+
+ //**Function call operator*******************************************************************
+ /*!\brief Performs the division assignment between the two given operands.
+ //
+ // \return void
+ */
+ inline void operator()() {
+ divAssign( target_, source_ );
+ }
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ Target target_; //!< The target operand.
+ const Source source_; //!< The source operand.
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Target );
+ BLAZE_CONSTRAINT_MUST_BE_EXPRESSION_TYPE( Source );
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Initialization functions********************************************************************
+ /*!\name Initialization functions */
+ //@{
+ static inline size_t initPool();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ static ThreadPool<TT,MT,LT,CT> threadpool_; //!< The pool of active threads of the backend system.
+ /*!< It is initialized with the number of threads
+ specified via the environment variable
+ \c BLAZE_NUM_THREADS. However, it can be
+ explicitly resized to arbitrary numbers of
+ threads. */
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename TT, typename MT, typename LT, typename CT >
+ThreadPool<TT,MT,LT,CT> ThreadBackend<TT,MT,LT,CT>::threadpool_( initPool() );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the total number of threads managed by the thread backend system.
+//
+// \return The total number of threads of the thread backend system.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline size_t ThreadBackend<TT,MT,LT,CT>::size()
+{
+ return threadpool_.size();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changes the total number of threads managed by the thread backend system.
+//
+// \param n The new number of threads \f$[1..\infty)\f$.
+// \param block \a true if the function shall block, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid number of threads.
+//
+// This function changes the total number of threads managed by the thread backend system. If
+// \a n is smaller than the current size of the thread pool, the according number of threads is
+// removed from the backend system, otherwise new threads are added to the backend system. In
+// case an invalid number of threads is specified, an \a std::invalid_argument exception is
+// thrown. Via the \a block flag it is possible to block the function until the desired
+// number of threads is available.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline void ThreadBackend<TT,MT,LT,CT>::resize( size_t n, bool block )
+{
+ return threadpool_.resize( n, block );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Waiting for all scheduled tasks to be completed.
+//
+// \return void
+//
+// This function blocks until all scheduled tasks have been completed.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline void ThreadBackend<TT,MT,LT,CT>::wait()
+{
+ threadpool_.wait();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// THREAD EXECUTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scheduling an assignment of the given operands for execution.
+//
+// \param target The target operand to be assigned to.
+// \param source The target operand to be assigned to the target.
+// \return void
+//
+// This function schedules a plain assignment of the two given operands for execution.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+inline void ThreadBackend<TT,MT,LT,CT>::scheduleAssign( Target& target, const Source& source )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target );
+ threadpool_.schedule( Assigner<Target,Source>( target, source ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scheduling an addition assignment of the given operands for execution.
+//
+// \param target The target operand to be assigned to.
+// \param source The target operand to be added to the target.
+// \return void
+//
+// This function schedules an addition assignment of the two given operands for execution.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+inline void ThreadBackend<TT,MT,LT,CT>::scheduleAddAssign( Target& target, const Source& source )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target );
+ threadpool_.schedule( AddAssigner<Target,Source>( target, source ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scheduling a subtraction assignment of the given operands for execution.
+//
+// \param target The target operand to be assigned to.
+// \param source The target operand to be subtracted from the target.
+// \return void
+//
+// This function schedules a subtraction assignment of the two given operands for execution.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+inline void ThreadBackend<TT,MT,LT,CT>::scheduleSubAssign( Target& target, const Source& source )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target );
+ threadpool_.schedule( SubAssigner<Target,Source>( target, source ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scheduling a multiplication assignment of the given operands for execution.
+//
+// \param target The target operand to be assigned to.
+// \param source The target operand to be multiplied with the target.
+// \return void
+//
+// This function schedules a multiplication assignment of the two given operands for execution.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+inline void ThreadBackend<TT,MT,LT,CT>::scheduleMultAssign( Target& target, const Source& source )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target );
+ threadpool_.schedule( MultAssigner<Target,Source>( target, source ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scheduling a division assignment of the given operands for execution.
+//
+// \param target The target operand to be assigned to.
+// \param source The target operand to be divided from the target.
+// \return void
+//
+// This function schedules a division assignment of the two given operands for execution.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+template< typename Target // Type of the target operand
+ , typename Source > // Type of the source operand
+inline void ThreadBackend<TT,MT,LT,CT>::scheduleDivAssign( Target& target, const Source& source )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target );
+ threadpool_.schedule( DivAssigner<Target,Source>( target, source ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// INITIALIZATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the initial number of threads of the thread pool.
+//
+// \return The initial number of threads.
+//
+// This function determines the initial number of threads based on the \c BLAZE_NUM_THREADS
+// environment variable. In case the environment variable is not defined or not set, the
+// function returns 1. Otherwise it returns the specified number of threads.
+*/
+#if (defined _MSC_VER)
+# pragma warning(push)
+# pragma warning(disable:4996)
+#endif
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline size_t ThreadBackend<TT,MT,LT,CT>::initPool()
+{
+ const char* env = std::getenv( "BLAZE_NUM_THREADS" );
+
+ if( env == nullptr )
+ return 1UL;
+ else return max( 1, atoi( env ) );
+}
+#if (defined _MSC_VER)
+# pragma warning(pop)
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TYPE DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The type of the active thread backend system.
+// \ingroup smp
+//
+// This type represents the active thread backend system. This backend system must be used to
+// manage the active number of threads used to execute operations and to schedule tasks to be
+// executed.
+*/
+#if BLAZE_CPP_THREADS_PARALLEL_MODE
+typedef ThreadBackend< std::thread
+ , std::mutex
+ , std::unique_lock< std::mutex >
+ , std::condition_variable
+ > TheThreadBackend;
+#elif BLAZE_BOOST_THREADS_PARALLEL_MODE
+typedef ThreadBackend< boost::thread
+ , boost::mutex
+ , boost::unique_lock< boost::mutex >
+ , boost::condition_variable
+ > TheThreadBackend;
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/CompressedMatrix.h b/src/cpu/blaze/math/sparse/CompressedMatrix.h
new file mode 100644
index 00000000..e60c9417
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/CompressedMatrix.h
@@ -0,0 +1,5650 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/CompressedMatrix.h
+// \brief Implementation of a compressed MxN matrix
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_COMPRESSEDMATRIX_H_
+#define _BLAZE_MATH_SPARSE_COMPRESSEDMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/MatrixAccessProxy.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/system/StorageOrder.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Algorithm.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameSize.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup compressed_matrix CompressedMatrix
+// \ingroup sparse_matrix
+*/
+/*!\brief Efficient implementation of a \f$ M \times N \f$ compressed matrix.
+// \ingroup compressed_matrix
+//
+// The CompressedMatrix class template is the representation of an arbitrary sized sparse
+// matrix with \f$ M \cdot N \f$ dynamically allocated elements of arbitrary type. The type
+// of the elements and the storage order of the matrix can be specified via the two template
+// parameters:
+
+ \code
+ template< typename Type, bool SO >
+ class CompressedMatrix;
+ \endcode
+
+// - Type: specifies the type of the matrix elements. CompressedMatrix can be used with
+// any non-cv-qualified, non-reference, non-pointer element type.
+// - SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
+// The default value is blaze::rowMajor.
+//
+// Inserting/accessing elements in a compressed matrix can be done by several alternative
+// functions. The following example demonstrates all options:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Creating a row-major 4x3 compressed matrix with 4 rows and 3 columns
+ CompressedMatrix<double,rowMajor> A( 4, 3 );
+
+ // The function call operator provides access to all possible elements of the compressed matrix,
+ // including the zero elements. In case the function call operator is used to access an element
+ // that is currently not stored in the sparse matrix, the element is inserted into the matrix.
+ A(1,2) = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element
+ // is not contained in the matrix it is inserted into the matrix, if it is already contained
+ // in the matrix its value is modified.
+ A.set( 2, 0, -1.2 );
+
+ // An alternative for inserting elements into the matrix is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the matrix.
+ A.insert( 2, 1, 3.7 );
+
+ // A very efficient way to add new elements to a sparse matrix is the append() function.
+ // Note that append() requires that the appended element's index is strictly larger than
+ // the currently largest non-zero index of the specified row and that the matrix's capacity
+ // is large enough to hold the new element.
+ A.reserve( 3, 2 ); // Reserving space for 2 non-zero elements in row 3
+ A.append( 3, 1, -2.1 ); // Appending the value -2.1 at column index 1 in row 3
+ A.append( 3, 2, 1.4 ); // Appending the value 1.4 at column index 2 in row 3
+
+ // The most efficient way to fill a (newly created) sparse matrix with elements, however, is
+ // a combination of reserve(), append(), and the finalize() function.
+ CompressedMatrix<double,rowMajor> B( 4, 3 );
+ B.reserve( 3 ); // Reserving enough space for 3 non-zero elements
+ B.append( 0, 1, 1 ); // Appending the value 1 in row 0 with column index 1
+ B.finalize( 0 ); // Finalizing row 0
+ B.append( 1, 1, 2 ); // Appending the value 2 in row 1 with column index 1
+ B.finalize( 1 ); // Finalizing row 1
+ B.append( 2, 0, 3 ); // Appending the value 3 in row 2 with column index 0
+ B.finalize( 2 ); // Finalizing row 2
+
+ // In order to traverse all non-zero elements currently stored in the matrix, the begin()
+ // and end() functions can be used. In the example, all non-zero elements of the 2nd row
+ // of A are traversed.
+ for( CompressedMatrix<double,rowMajor>::Iterator i=A.begin(1); i!=A.end(1); ++i ) {
+ ... = i->value(); // Access to the value of the non-zero element
+ ... = i->index(); // Access to the index of the non-zero element
+ }
+ \endcode
+
+// The use of CompressedMatrix is very natural and intuitive. All operations (addition, subtraction,
+// multiplication, scaling, ...) can be performed on all possible combination of row-major and
+// column-major dense and sparse matrices with fitting element types. The following example gives
+// an impression of the use of CompressedMatrix:
+
+ \code
+ using blaze::CompressedMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ CompressedMatrix<double,rowMajor> A( 2, 3 ); // Default constructed, non-initialized, row-major 2x3 matrix
+ A(0,0) = 1.0; A(0,2) = 3.0; A(1,1) = 5.0; // Element initialization
+
+ CompressedMatrix<float,columnMajor> B( 2, 3 ); // Default constructed column-major single precision 2x3 matrix
+ B(0,1) = 3.0; B(1,0) = 2.0; B(1,2) = 6.0; // Element initialization
+
+ DynamicMatrixMatrix<float> C( 2, 3, 4.0F ); // Directly, homogeneously initialized single precision dense 2x3 matrix
+ CompressedMatrix<float> D( 3, 2 ); // Empty row-major sparse single precision matrix
+
+ CompressedMatrix<double,rowMajor> E( A ); // Creation of a new row-major matrix as a copy of A
+ CompressedMatrix<double,columnMajor> F; // Creation of a default column-major matrix
+
+ E = A + B; // Matrix addition and assignment to a row-major matrix
+ E = A - C; // Matrix subtraction and assignment to a column-major matrix
+ F = A * D; // Matrix multiplication between two matrices of different element types
+
+ A *= 2.0; // In-place scaling of matrix A
+ E = 2.0 * B; // Scaling of matrix B
+ F = D * 2.0; // Scaling of matrix D
+
+ E += A - B; // Addition assignment
+ E -= A + C; // Subtraction assignment
+ F *= A * D; // Multiplication assignment
+ \endcode
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO = defaultStorageOrder > // Storage order
+class CompressedMatrix : public SparseMatrix< CompressedMatrix<Type,SO>, SO >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ValueIndexPair<Type> ElementBase; //!< Base class for the sparse matrix element.
+ //**********************************************************************************************
+
+ //**Private class Element***********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Value-index-pair for the CompressedMatrix class.
+ */
+ struct Element : public ElementBase
+ {
+ // This operator is required due to a bug in all versions of the the MSVC compiler.
+ // A simple 'using ElementBase::operator=;' statement results in ambiguity problems.
+ template< typename Other >
+ inline Element& operator=( const Other& rhs )
+ {
+ ElementBase::operator=( rhs );
+ return *this;
+ }
+
+ friend class CompressedMatrix;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef CompressedMatrix<Type,SO> This; //!< Type of this CompressedMatrix instance.
+ typedef SparseMatrix<This,SO> BaseType; //!< Base type of this CompressedMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef CompressedMatrix<Type,!SO> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef CompressedMatrix<Type,!SO> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the sparse matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef MatrixAccessProxy<This> Reference; //!< Reference to a sparse matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant sparse matrix value.
+ typedef Element* Iterator; //!< Iterator over non-constant elements.
+ typedef const Element* ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a CompressedMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef CompressedMatrix<ET,SO> Other; //!< The type of the other CompressedMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline CompressedMatrix();
+ explicit inline CompressedMatrix( size_t m, size_t n );
+ explicit inline CompressedMatrix( size_t m, size_t n, size_t nonzeros );
+ explicit CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros );
+ inline CompressedMatrix( const CompressedMatrix& sm );
+ inline CompressedMatrix( CompressedMatrix&& sm ) noexcept;
+ template< typename MT, bool SO2 > inline CompressedMatrix( const DenseMatrix<MT,SO2>& dm );
+ template< typename MT, bool SO2 > inline CompressedMatrix( const SparseMatrix<MT,SO2>& sm );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~CompressedMatrix();
+ //@}
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i ) noexcept;
+ inline ConstIterator begin ( size_t i ) const noexcept;
+ inline ConstIterator cbegin( size_t i ) const noexcept;
+ inline Iterator end ( size_t i ) noexcept;
+ inline ConstIterator end ( size_t i ) const noexcept;
+ inline ConstIterator cend ( size_t i ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline CompressedMatrix& operator=( const CompressedMatrix& rhs );
+ inline CompressedMatrix& operator=( CompressedMatrix&& rhs ) noexcept;
+
+ template< typename MT, bool SO2 > inline CompressedMatrix& operator= ( const DenseMatrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline CompressedMatrix& operator= ( const SparseMatrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline CompressedMatrix& operator+=( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline CompressedMatrix& operator-=( const Matrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline CompressedMatrix& operator*=( const Matrix<MT,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, CompressedMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, CompressedMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline void clear();
+ inline Iterator set ( size_t i, size_t j, const Type& value );
+ inline Iterator insert ( size_t i, size_t j, const Type& value );
+ inline void erase ( size_t i, size_t j );
+ inline Iterator erase ( size_t i, Iterator pos );
+ inline Iterator erase ( size_t i, Iterator first, Iterator last );
+ void resize ( size_t m, size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ void reserve( size_t i, size_t nonzeros );
+ inline void trim ();
+ inline void trim ( size_t i );
+ inline CompressedMatrix& transpose();
+ inline CompressedMatrix& ctranspose();
+ template< typename Other > inline CompressedMatrix& scale( const Other& scalar );
+ template< typename Other > inline CompressedMatrix& scaleDiagonal( Other scalar );
+ inline void swap( CompressedMatrix& sm ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const Type& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+
+ template< typename MT, bool SO2 > inline void assign ( const DenseMatrix<MT,SO2>& rhs );
+ template< typename MT > inline void assign ( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void assign ( const SparseMatrix<MT,!SO>& rhs );
+ template< typename MT, bool SO2 > inline void addAssign( const DenseMatrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline void addAssign( const SparseMatrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline void subAssign( const DenseMatrix<MT,SO2>& rhs );
+ template< typename MT, bool SO2 > inline void subAssign( const SparseMatrix<MT,SO2>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ Iterator insert( Iterator pos, size_t i, size_t j, const Type& value );
+ inline size_t extendCapacity() const noexcept;
+ void reserveElements( size_t nonzeros );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t m_; //!< The current number of rows of the sparse matrix.
+ size_t n_; //!< The current number of columns of the sparse matrix.
+ size_t capacity_; //!< The current capacity of the pointer array.
+ Iterator* begin_; //!< Pointers to the first non-zero element of each row.
+ Iterator* end_; //!< Pointers one past the last non-zero element of each row.
+
+ static const Type zero_; //!< Neutral element for accesses to zero elements.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_CONSTRAINT_MUST_HAVE_SAME_SIZE ( ElementBase, Element );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
+//
+//=================================================================================================
+
+template< typename Type, bool SO >
+const Type CompressedMatrix<Type,SO>::zero_ = Type();
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for CompressedMatrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>::CompressedMatrix()
+ : m_ ( 0UL ) // The current number of rows of the sparse matrix
+ , n_ ( 0UL ) // The current number of columns of the sparse matrix
+ , capacity_( 0UL ) // The current capacity of the pointer array
+ , begin_ ( nullptr ) // Pointers to the first non-zero element of each row
+ , end_ ( nullptr ) // Pointers one past the last non-zero element of each row
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ M \times N \f$.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+//
+// The matrix is initialized to the zero matrix and has no free capacity.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>::CompressedMatrix( size_t m, size_t n )
+ : m_ ( m ) // The current number of rows of the sparse matrix
+ , n_ ( n ) // The current number of columns of the sparse matrix
+ , capacity_( m ) // The current capacity of the pointer array
+ , begin_( new Iterator[2UL*m+2UL] ) // Pointers to the first non-zero element of each row
+ , end_ ( begin_+(m+1UL) ) // Pointers one past the last non-zero element of each row
+{
+ for( size_t i=0UL; i<2UL*m_+2UL; ++i )
+ begin_[i] = nullptr;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ M \times N \f$.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized to the zero matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>::CompressedMatrix( size_t m, size_t n, size_t nonzeros )
+ : m_ ( m ) // The current number of rows of the sparse matrix
+ , n_ ( n ) // The current number of columns of the sparse matrix
+ , capacity_( m ) // The current capacity of the pointer array
+ , begin_( new Iterator[2UL*m+2UL] ) // Pointers to the first non-zero element of each row
+ , end_ ( begin_+(m+1UL) ) // Pointers one past the last non-zero element of each row
+{
+ begin_[0UL] = allocate<Element>( nonzeros );
+ for( size_t i=1UL; i<(2UL*m_+1UL); ++i )
+ begin_[i] = begin_[0UL];
+ end_[m_] = begin_[0UL]+nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a matrix of size \f$ M \times N \f$.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each row/column.
+//
+// The matrix is initialized to the zero matrix and will have the specified capacity in each
+// row/column. Note that in case of a row-major matrix the given vector must have at least
+// \a m elements, in case of a column-major matrix at least \a n elements.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+CompressedMatrix<Type,SO>::CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros )
+ : m_ ( m ) // The current number of rows of the sparse matrix
+ , n_ ( n ) // The current number of columns of the sparse matrix
+ , capacity_( m ) // The current capacity of the pointer array
+ , begin_( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
+ , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
+{
+ BLAZE_USER_ASSERT( nonzeros.size() == m, "Size of capacity vector and number of rows don't match" );
+
+ size_t newCapacity( 0UL );
+ for( std::vector<size_t>::const_iterator it=nonzeros.begin(); it!=nonzeros.end(); ++it )
+ newCapacity += *it;
+
+ begin_[0UL] = end_[0UL] = allocate<Element>( newCapacity );
+ for( size_t i=0UL; i<m_; ++i ) {
+ begin_[i+1UL] = end_[i+1UL] = begin_[i] + nonzeros[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for CompressedMatrix.
+//
+// \param sm Sparse matrix to be copied.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>::CompressedMatrix( const CompressedMatrix& sm )
+ : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
+ , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
+ , capacity_( sm.m_ ) // The current capacity of the pointer array
+ , begin_( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
+ , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
+{
+ const size_t nonzeros( sm.nonZeros() );
+
+ begin_[0UL] = allocate<Element>( nonzeros );
+ for( size_t i=0UL; i<m_; ++i )
+ begin_[i+1UL] = end_[i] = std::copy( sm.begin(i), sm.end(i), begin_[i] );
+ end_[m_] = begin_[0UL]+nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The move constructor for CompressedMatrix.
+//
+// \param sm The sparse matrix to be moved into this instance.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>::CompressedMatrix( CompressedMatrix&& sm ) noexcept
+ : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
+ , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
+ , capacity_( sm.capacity_ ) // The current capacity of the pointer array
+ , begin_ ( sm.begin_ ) // Pointers to the first non-zero element of each row
+ , end_ ( sm.end_ ) // Pointers one past the last non-zero element of each row
+{
+ sm.m_ = 0UL;
+ sm.n_ = 0UL;
+ sm.capacity_ = 0UL;
+ sm.begin_ = nullptr;
+ sm.end_ = nullptr;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from dense matrices.
+//
+// \param dm Dense matrix to be copied.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the foreign dense matrix
+ , bool SO2 > // Storage order of the foreign dense matrix
+inline CompressedMatrix<Type,SO>::CompressedMatrix( const DenseMatrix<MT,SO2>& dm )
+ : m_ ( (~dm).rows() ) // The current number of rows of the sparse matrix
+ , n_ ( (~dm).columns() ) // The current number of columns of the sparse matrix
+ , capacity_( m_ ) // The current capacity of the pointer array
+ , begin_ ( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
+ , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
+{
+ using blaze::assign;
+
+ for( size_t i=0UL; i<2UL*m_+2UL; ++i )
+ begin_[i] = nullptr;
+
+ assign( *this, ~dm );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different sparse matrices.
+//
+// \param sm Sparse matrix to be copied.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the foreign sparse matrix
+ , bool SO2 > // Storage order of the foreign sparse matrix
+inline CompressedMatrix<Type,SO>::CompressedMatrix( const SparseMatrix<MT,SO2>& sm )
+ : m_ ( (~sm).rows() ) // The current number of rows of the sparse matrix
+ , n_ ( (~sm).columns() ) // The current number of columns of the sparse matrix
+ , capacity_( m_ ) // The current capacity of the pointer array
+ , begin_ ( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
+ , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
+{
+ using blaze::assign;
+
+ const size_t nonzeros( (~sm).nonZeros() );
+
+ begin_[0UL] = allocate<Element>( nonzeros );
+ for( size_t i=0UL; i<m_; ++i )
+ begin_[i+1UL] = end_[i] = begin_[0UL];
+ end_[m_] = begin_[0UL]+nonzeros;
+
+ assign( *this, ~sm );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The destructor for CompressedMatrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>::~CompressedMatrix()
+{
+ if( begin_ != nullptr ) {
+ deallocate( begin_[0UL] );
+ delete[] begin_;
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief 2D-access to the sparse matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function returns a reference to the accessed value at position (\a i,\a j). In case the
+// compressed matrix does not yet store an element at position (\a i,\a j) , a new element is
+// inserted into the compressed matrix. Note that this function only performs an index check in
+// case BLAZE_USER_ASSERT() is active. In contrast, the at() function is guaranteed to perform a
+// check of the given access indices.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Reference
+ CompressedMatrix<Type,SO>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return Reference( *this, i, j );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief 2D-access to the sparse matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstReference
+ CompressedMatrix<Type,SO>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const ConstIterator pos( lowerBound( i, j ) );
+
+ if( pos == end_[i] || pos->index_ != j )
+ return zero_;
+ else
+ return pos->value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// This function returns a reference to the accessed value at position (\a i,\a j). In case the
+// compressed matrix does not yet store an element at position (\a i,\a j) , a new element is
+// inserted into the compressed matrix. In contrast to the subscript operator this function
+// always performs a check of the given access indices.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Reference
+ CompressedMatrix<Type,SO>::at( size_t i, size_t j )
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstReference
+ CompressedMatrix<Type,SO>::at( size_t i, size_t j ) const
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::begin( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
+ return begin_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstIterator
+ CompressedMatrix<Type,SO>::begin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
+ return begin_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstIterator
+ CompressedMatrix<Type,SO>::cbegin( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
+ return begin_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::end( size_t i ) noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
+ return end_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstIterator
+ CompressedMatrix<Type,SO>::end( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
+ return end_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstIterator
+ CompressedMatrix<Type,SO>::cend( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
+ return end_[i];
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for CompressedMatrix.
+//
+// \param rhs Sparse matrix to be copied.
+// \return Reference to the assigned sparse matrix.
+//
+// The sparse matrix is resized according to the given sparse matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>&
+ CompressedMatrix<Type,SO>::operator=( const CompressedMatrix& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ const size_t nonzeros( rhs.nonZeros() );
+
+ if( rhs.m_ > capacity_ || nonzeros > capacity() )
+ {
+ Iterator* newBegin( new Iterator[2UL*rhs.m_+2UL] );
+ Iterator* newEnd ( newBegin+(rhs.m_+1UL) );
+
+ newBegin[0UL] = allocate<Element>( nonzeros );
+ for( size_t i=0UL; i<rhs.m_; ++i ) {
+ newBegin[i+1UL] = newEnd[i] = std::copy( rhs.begin_[i], rhs.end_[i], newBegin[i] );
+ }
+ newEnd[rhs.m_] = newBegin[0UL]+nonzeros;
+
+ std::swap( begin_, newBegin );
+ end_ = newEnd;
+ capacity_ = rhs.m_;
+
+ if( newBegin != nullptr ) {
+ deallocate( newBegin[0UL] );
+ delete[] newBegin;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rhs.m_; ++i ) {
+ begin_[i+1UL] = end_[i] = std::copy( rhs.begin_[i], rhs.end_[i], begin_[i] );
+ }
+ }
+
+ m_ = rhs.m_;
+ n_ = rhs.n_;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Move assignment operator for CompressedMatrix.
+//
+// \param rhs The sparse matrix to be moved into this instance.
+// \return Reference to the assigned sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>&
+ CompressedMatrix<Type,SO>::operator=( CompressedMatrix&& rhs ) noexcept
+{
+ if( begin_ != nullptr ) {
+ deallocate( begin_[0UL] );
+ delete[] begin_;
+ }
+
+ m_ = rhs.m_;
+ n_ = rhs.n_;
+ capacity_ = rhs.capacity_;
+ begin_ = rhs.begin_;
+ end_ = rhs.end_;
+
+ rhs.m_ = 0UL;
+ rhs.n_ = 0UL;
+ rhs.capacity_ = 0UL;
+ rhs.begin_ = nullptr;
+ rhs.end_ = nullptr;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for dense matrices.
+//
+// \param rhs Dense matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline CompressedMatrix<Type,SO>&
+ CompressedMatrix<Type,SO>::operator=( const DenseMatrix<MT,SO2>& rhs )
+{
+ using blaze::assign;
+
+ if( (~rhs).canAlias( this ) ) {
+ CompressedMatrix tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( (~rhs).rows(), (~rhs).columns(), false );
+ assign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different sparse matrices.
+//
+// \param rhs Sparse matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side sparse matrix
+ , bool SO2 > // Storage order of the right-hand side sparse matrix
+inline CompressedMatrix<Type,SO>&
+ CompressedMatrix<Type,SO>::operator=( const SparseMatrix<MT,SO2>& rhs )
+{
+ using blaze::assign;
+
+ if( (~rhs).canAlias( this ) ||
+ (~rhs).rows() > capacity_ ||
+ (~rhs).nonZeros() > capacity() ) {
+ CompressedMatrix tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( (~rhs).rows(), (~rhs).columns(), false );
+ reset();
+ assign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline CompressedMatrix<Type,SO>&
+ CompressedMatrix<Type,SO>::operator+=( const Matrix<MT,SO2>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ addAssign( *this, ~rhs );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline CompressedMatrix<Type,SO>& CompressedMatrix<Type,SO>::operator-=( const Matrix<MT,SO2>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ subAssign( *this, ~rhs );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline CompressedMatrix<Type,SO>&
+ CompressedMatrix<Type,SO>::operator*=( const Matrix<MT,SO2>& rhs )
+{
+ if( (~rhs).rows() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ CompressedMatrix tmp( *this * (~rhs) );
+ swap( tmp );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a sparse matrix and
+// a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, CompressedMatrix<Type,SO> >&
+ CompressedMatrix<Type,SO>::operator*=( Other rhs )
+{
+ for( size_t i=0UL; i<m_; ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value_ *= rhs;
+ }
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a sparse matrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, CompressedMatrix<Type,SO> >&
+ CompressedMatrix<Type,SO>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<Type,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( size_t i=0UL; i<m_; ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value_ *= tmp;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<m_; ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value_ /= rhs;
+ }
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current number of rows of the sparse matrix.
+//
+// \return The number of rows of the sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline size_t CompressedMatrix<Type,SO>::rows() const noexcept
+{
+ return m_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current number of columns of the sparse matrix.
+//
+// \return The number of columns of the sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline size_t CompressedMatrix<Type,SO>::columns() const noexcept
+{
+ return n_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the sparse matrix.
+//
+// \return The capacity of the sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline size_t CompressedMatrix<Type,SO>::capacity() const noexcept
+{
+ if( begin_ != nullptr )
+ return end_[m_] - begin_[0UL];
+ else return 0UL;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline size_t CompressedMatrix<Type,SO>::capacity( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return begin_[i+1UL] - begin_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the sparse matrix
+//
+// \return The number of non-zero elements in the sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline size_t CompressedMatrix<Type,SO>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<m_; ++i )
+ nonzeros += nonZeros( i );
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline size_t CompressedMatrix<Type,SO>::nonZeros( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return end_[i] - begin_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::reset()
+{
+ for( size_t i=0UL; i<m_; ++i )
+ end_[i] = begin_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::reset( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ end_[i] = begin_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the sparse matrix.
+//
+// \return void
+//
+// After the clear() function, the size of the sparse matrix is 0.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::clear()
+{
+ end_[0UL] = end_[m_];
+ m_ = 0UL;
+ n_ = 0UL;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting an element of the compressed matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+//
+// This function sets the value of an element of the compressed matrix. In case the compressed
+// matrix already contains an element with row index \a i and column index \a j its value is
+// modified, else a new element with the given \a value is inserted.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::set( size_t i, size_t j, const Type& value )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const Iterator pos( lowerBound( i, j ) );
+
+ if( pos != end_[i] && pos->index_ == j ) {
+ pos->value() = value;
+ return pos;
+ }
+ else return insert( pos, i, j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting an element into the compressed matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid compressed matrix access index.
+//
+// This function inserts a new element into the compressed matrix. However, duplicate elements
+// are not allowed. In case the compressed matrix already contains an element with row index \a i
+// and column index \a j, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::insert( size_t i, size_t j, const Type& value )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const Iterator pos( lowerBound( i, j ) );
+
+ if( pos != end_[i] && pos->index_ == j ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Bad access index" );
+ }
+
+ return insert( pos, i, j, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting an element into the compressed matrix.
+//
+// \param pos The position of the new element.
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid compressed matrix access index.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::insert( Iterator pos, size_t i, size_t j, const Type& value )
+{
+ if( begin_[i+1UL] - end_[i] != 0 ) {
+ std::move_backward( pos, end_[i], end_[i]+1UL );
+ pos->value_ = value;
+ pos->index_ = j;
+ ++end_[i];
+
+ return pos;
+ }
+ else if( end_[m_] - begin_[m_] != 0 ) {
+ std::move_backward( pos, end_[m_-1UL], end_[m_-1UL]+1UL );
+
+ pos->value_ = value;
+ pos->index_ = j;
+
+ for( size_t k=i+1UL; k<m_+1UL; ++k ) {
+ ++begin_[k];
+ ++end_[k-1UL];
+ }
+
+ return pos;
+ }
+ else {
+ size_t newCapacity( extendCapacity() );
+
+ Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
+ Iterator* newEnd = newBegin+capacity_+1UL;
+
+ newBegin[0UL] = allocate<Element>( newCapacity );
+
+ for( size_t k=0UL; k<i; ++k ) {
+ const size_t nonzeros( end_[k] - begin_[k] );
+ const size_t total( begin_[k+1UL] - begin_[k] );
+ newEnd [k] = newBegin[k] + nonzeros;
+ newBegin[k+1UL] = newBegin[k] + total;
+ }
+ newEnd [i] = newBegin[i] + ( end_[i] - begin_[i] ) + 1;
+ newBegin[i+1UL] = newBegin[i] + ( begin_[i+1] - begin_[i] ) + 1;
+ for( size_t k=i+1UL; k<m_; ++k ) {
+ const size_t nonzeros( end_[k] - begin_[k] );
+ const size_t total( begin_[k+1UL] - begin_[k] );
+ newEnd [k] = newBegin[k] + nonzeros;
+ newBegin[k+1UL] = newBegin[k] + total;
+ }
+
+ newEnd[m_] = newEnd[capacity_] = newBegin[0UL]+newCapacity;
+
+ Iterator tmp = std::move( begin_[0UL], pos, newBegin[0UL] );
+ tmp->value_ = value;
+ tmp->index_ = j;
+ std::move( pos, end_[m_-1UL], tmp+1UL );
+
+ std::swap( newBegin, begin_ );
+ end_ = newEnd;
+ deallocate( newBegin[0UL] );
+ delete[] newBegin;
+
+ return tmp;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing an element from the sparse matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::erase( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const Iterator pos( find( i, j ) );
+ if( pos != end_[i] )
+ end_[i] = std::move( pos+1, end_[i], pos );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing an element from the sparse matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the sparse matrix. In case the storage order is set to
+// \a rowMajor the function erases an element from row \a i, in case the storage flag is set to
+// \a columnMajor the function erases an element from column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::erase( size_t i, Iterator pos )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_USER_ASSERT( pos >= begin_[i] && pos <= end_[i], "Invalid compressed matrix iterator" );
+
+ if( pos != end_[i] )
+ end_[i] = std::move( pos+1, end_[i], pos );
+
+ return pos;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing a range of elements from the sparse matrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of element from the sparse matrix. In case the storage order is
+// set to \a rowMajor the function erases a range of elements from row \a i, in case the storage
+// flag is set to \a columnMajor the function erases a range of elements from column \a i.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::erase( size_t i, Iterator first, Iterator last )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( first <= last, "Invalid iterator range" );
+ BLAZE_USER_ASSERT( first >= begin_[i] && first <= end_[i], "Invalid compressed matrix iterator" );
+ BLAZE_USER_ASSERT( last >= begin_[i] && last <= end_[i], "Invalid compressed matrix iterator" );
+
+ if( first != last )
+ end_[i] = std::move( last, end_[i], first );
+
+ return first;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the sparse matrix.
+//
+// \param m The new number of rows of the sparse matrix.
+// \param n The new number of columns of the sparse matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+void CompressedMatrix<Type,SO>::resize( size_t m, size_t n, bool preserve )
+{
+ BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
+ BLAZE_INTERNAL_ASSERT( begin_ == nullptr || size_t( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
+
+ if( m == m_ && n == n_ ) return;
+
+ if( begin_ == nullptr )
+ {
+ begin_ = new Iterator[2UL*m+2UL];
+ end_ = begin_+m+1UL;
+
+ for( size_t i=0UL; i<2UL*m+2UL; ++i ) {
+ begin_[i] = nullptr;
+ }
+
+ capacity_ = m;
+ }
+ else if( m > capacity_ )
+ {
+ Iterator* newBegin( new Iterator[2UL*m+2UL] );
+ Iterator* newEnd ( newBegin+m+1UL );
+
+ newBegin[0UL] = begin_[0UL];
+
+ if( preserve ) {
+ for( size_t i=0UL; i<m_; ++i ) {
+ newEnd [i] = end_ [i];
+ newBegin[i+1UL] = begin_[i+1UL];
+ }
+ for( size_t i=m_; i<m; ++i ) {
+ newBegin[i+1UL] = newEnd[i] = begin_[m_];
+ }
+ }
+ else {
+ for( size_t i=0UL; i<m; ++i ) {
+ newBegin[i+1UL] = newEnd[i] = begin_[0UL];
+ }
+ }
+
+ newEnd[m] = end_[m_];
+
+ std::swap( newBegin, begin_ );
+ delete[] newBegin;
+ end_ = newEnd;
+ capacity_ = m;
+ }
+ else if( m > m_ )
+ {
+ end_[m] = end_[m_];
+
+ if( !preserve ) {
+ for( size_t i=0UL; i<m_; ++i )
+ end_[i] = begin_[i];
+ }
+
+ for( size_t i=m_; i<m; ++i ) {
+ begin_[i+1UL] = end_[i] = begin_[m_];
+ }
+ }
+ else
+ {
+ if( preserve ) {
+ for( size_t i=0UL; i<m; ++i )
+ end_[i] = lowerBound( i, n );
+ }
+ else {
+ for( size_t i=0UL; i<m; ++i )
+ end_[i] = begin_[i];
+ }
+
+ end_[m] = end_[m_];
+ }
+
+ m_ = m;
+ n_ = n;
+
+ BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
+ BLAZE_INTERNAL_ASSERT( size_t( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the sparse matrix.
+//
+// \param nonzeros The new minimum capacity of the sparse matrix.
+// \return void
+//
+// This function increases the capacity of the sparse matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::reserve( size_t nonzeros )
+{
+ if( nonzeros > capacity() )
+ reserveElements( nonzeros );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of a specific row/column of the sparse matrix.
+//
+// \param i The row/column index \f$[0..M-1]\f$ or \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the sparse matrix to at least
+// \a nonzeros elements. The current values of the sparse matrix and all other individual
+// row/column capacities are preserved. In case the storage order is set to \a rowMajor, the
+// function reserves capacity for row \a i and the index has to be in the range \f$[0..M-1]\f$.
+// In case the storage order is set to \a columnMajor, the function reserves capacity for column
+// \a i and the index has to be in the range \f$[0..N-1]\f$.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+void CompressedMatrix<Type,SO>::reserve( size_t i, size_t nonzeros )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
+ BLAZE_INTERNAL_ASSERT( static_cast<size_t>( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
+
+ const size_t current( capacity(i) );
+
+ if( current >= nonzeros ) return;
+
+ const ptrdiff_t additional( nonzeros - current );
+
+ if( end_[m_] - begin_[m_] < additional )
+ {
+ const size_t newCapacity( begin_[m_] - begin_[0UL] + additional );
+ BLAZE_INTERNAL_ASSERT( newCapacity > capacity(), "Invalid capacity value" );
+
+ Iterator* newBegin( new Iterator[2UL*m_+2UL] );
+ Iterator* newEnd ( newBegin+m_+1UL );
+
+ newBegin[0UL] = allocate<Element>( newCapacity );
+ newEnd [m_ ] = newBegin[0UL]+newCapacity;
+
+ for( size_t k=0UL; k<i; ++k ) {
+ newEnd [k ] = transfer( begin_[k], end_[k], newBegin[k] );
+ newBegin[k+1UL] = newBegin[k] + capacity(k);
+ }
+ newEnd [i ] = transfer( begin_[i], end_[i], newBegin[i] );
+ newBegin[i+1UL] = newBegin[i] + nonzeros;
+ for( size_t k=i+1UL; k<m_; ++k ) {
+ newEnd [k ] = transfer( begin_[k], end_[k], newBegin[k] );
+ newBegin[k+1UL] = newBegin[k] + capacity(k);
+ }
+
+ BLAZE_INTERNAL_ASSERT( newBegin[m_] == newEnd[m_], "Invalid pointer calculations" );
+
+ std::swap( newBegin, begin_ );
+ deallocate( newBegin[0UL] );
+ delete[] newBegin;
+ end_ = newEnd;
+ capacity_ = m_;
+ }
+ else
+ {
+ begin_[m_] += additional;
+ for( size_t j=m_-1UL; j>i; --j ) {
+ begin_[j] = std::move_backward( begin_[j], end_[j], end_[j]+additional );
+ end_ [j] += additional;
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
+ BLAZE_INTERNAL_ASSERT( static_cast<size_t>( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::trim()
+{
+ for( size_t i=0UL; i<m_; ++i )
+ trim( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing all excessive capacity of a specific row/column of the sparse matrix.
+//
+// \param i The index of the row/column to be trimmed (\f$[0..M-1]\f$ or \f$[0..N-1]\f$).
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::trim( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ if( i < ( m_ - 1UL ) )
+ end_[i+1] = std::move( begin_[i+1], end_[i+1], end_[i] );
+ begin_[i+1] = end_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>& CompressedMatrix<Type,SO>::transpose()
+{
+ CompressedMatrix tmp( trans( *this ) );
+ swap( tmp );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline CompressedMatrix<Type,SO>& CompressedMatrix<Type,SO>::ctranspose()
+{
+ CompressedMatrix tmp( ctrans( *this ) );
+ swap( tmp );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the sparse matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the scalar value
+inline CompressedMatrix<Type,SO>& CompressedMatrix<Type,SO>::scale( const Other& scalar )
+{
+ for( size_t i=0UL; i<m_; ++i )
+ for( Iterator element=begin_[i]; element!=end_[i]; ++element )
+ element->value_ *= scalar;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling the diagonal of the sparse matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the sparse matrix.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the scalar value
+inline CompressedMatrix<Type,SO>& CompressedMatrix<Type,SO>::scaleDiagonal( Other scalar )
+{
+ const size_t size( blaze::min( m_, n_ ) );
+
+ for( size_t i=0UL; i<size; ++i ) {
+ Iterator pos = lowerBound( i, i );
+ if( pos != end_[i] && pos->index_ == i )
+ pos->value_ *= scalar;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two sparse matrices.
+//
+// \param sm The sparse matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::swap( CompressedMatrix& sm ) noexcept
+{
+ std::swap( m_, sm.m_ );
+ std::swap( n_, sm.n_ );
+ std::swap( capacity_, sm.capacity_ );
+ std::swap( begin_, sm.begin_ );
+ std::swap( end_ , sm.end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Calculating a new matrix capacity.
+//
+// \return The new sparse matrix capacity.
+//
+// This function calculates a new matrix capacity based on the current capacity of the sparse
+// matrix. Note that the new capacity is restricted to the interval \f$[7..M \cdot N]\f$.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline size_t CompressedMatrix<Type,SO>::extendCapacity() const noexcept
+{
+ size_t nonzeros( 2UL*capacity()+1UL );
+ nonzeros = blaze::max( nonzeros, 7UL );
+
+ BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reserving the specified number of sparse matrix elements.
+//
+// \param nonzeros The number of matrix elements to be reserved.
+// \return void
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+void CompressedMatrix<Type,SO>::reserveElements( size_t nonzeros )
+{
+ Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
+ Iterator* newEnd = newBegin+capacity_+1UL;
+
+ newBegin[0UL] = allocate<Element>( nonzeros );
+
+ for( size_t k=0UL; k<m_; ++k ) {
+ BLAZE_INTERNAL_ASSERT( begin_[k] <= end_[k], "Invalid row pointers" );
+ newEnd [k] = transfer( begin_[k], end_[k], newBegin[k] );
+ newBegin[k+1UL] = newBegin[k] + ( begin_[k+1UL] - begin_[k] );
+ }
+
+ newEnd[m_] = newBegin[0UL]+nonzeros;
+
+ std::swap( newBegin, begin_ );
+ end_ = newEnd;
+
+ if( newBegin != nullptr ) {
+ deallocate( newBegin[0UL] );
+ delete[] newBegin;
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned sparse matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::find( size_t i, size_t j )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).find( i, j ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an row/column iterator to the element.
+// Otherwise an iterator just past the last non-zero element of row \a i or column \a j (the
+// end() iterator) is returned. Note that the returned sparse matrix iterator is subject to
+// invalidation due to inserting operations via the function call operator or the insert()
+// function!
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstIterator
+ CompressedMatrix<Type,SO>::find( size_t i, size_t j ) const
+{
+ const ConstIterator pos( lowerBound( i, j ) );
+ if( pos != end_[i] && pos->index_ == j )
+ return pos;
+ else return end_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::lowerBound( size_t i, size_t j )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).lowerBound( i, j ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index not less then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index not less then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstIterator
+ CompressedMatrix<Type,SO>::lowerBound( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return std::lower_bound( begin_[i], end_[i], j,
+ []( const Element& element, size_t index )
+ {
+ return element.index() < index;
+ } );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::Iterator
+ CompressedMatrix<Type,SO>::upperBound( size_t i, size_t j )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).upperBound( i, j ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major matrix, this function returns a row iterator to the first element with
+// an index greater then the given column index. In case of a column-major matrix, the function
+// returns a column iterator to the first element with an index greater then the given row
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed matrix
+// iterator is subject to invalidation due to inserting operations via the function call operator
+// or the insert() function!
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline typename CompressedMatrix<Type,SO>::ConstIterator
+ CompressedMatrix<Type,SO>::upperBound( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return std::upper_bound( begin_[i], end_[i], j,
+ []( size_t index, const Element& element )
+ {
+ return index < element.index();
+ } );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Appending an element to the specified row/column of the sparse matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse matrix with elements. It appends
+// a new element to the end of the specified row/column without any additional memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (newly created) sparse matrix:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::CompressedMatrix<double,rowMajor> A( 4, 3 );
+
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 0, 1, 1.0 ); // Appending the value 1 in row 0 with column index 1
+ A.finalize( 0 ); // Finalizing row 0
+ A.append( 1, 1, 2.0 ); // Appending the value 2 in row 1 with column index 1
+ A.finalize( 1 ); // Finalizing row 1
+ A.finalize( 2 ); // Finalizing the empty row 2 to prepare row 3
+ A.append( 3, 0, 3.0 ); // Appending the value 3 in row 3 with column index 0
+ A.finalize( 3 ); // Finalizing row 3
+ \endcode
+
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::append( size_t i, size_t j, const Type& value, bool check )
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_USER_ASSERT( end_[i] < end_[m_], "Not enough reserved capacity left" );
+ BLAZE_USER_ASSERT( begin_[i] == end_[i] || j > ( end_[i]-1UL )->index_, "Index is not strictly increasing" );
+
+ end_[i]->value_ = value;
+
+ if( !check || !isDefault( end_[i]->value_ ) ) {
+ end_[i]->index_ = j;
+ ++end_[i];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..M-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a matrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void CompressedMatrix<Type,SO>::finalize( size_t i )
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
+
+ begin_[i+1UL] = end_[i];
+ if( i != m_-1UL )
+ end_[i+1UL] = end_[i];
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the matrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool CompressedMatrix<Type,SO>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the matrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename Other > // Data type of the foreign expression
+inline bool CompressedMatrix<Type,SO>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline bool CompressedMatrix<Type,SO>::canSMPAssign() const noexcept
+{
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline void CompressedMatrix<Type,SO>::assign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ if( m_ == 0UL || n_ == 0UL )
+ return;
+
+ size_t nonzeros( 0UL );
+
+ for( size_t i=1UL; i<=m_; ++i )
+ begin_[i] = end_[i] = end_[m_];
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ begin_[i] = end_[i] = begin_[0UL]+nonzeros;
+
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? i : i+1UL )
+ :( n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ {
+ if( nonzeros == capacity() ) {
+ reserveElements( extendCapacity() );
+ for( size_t k=i+1UL; k<=m_; ++k )
+ begin_[k] = end_[k] = end_[m_];
+ }
+
+ end_[i]->value_ = (~rhs)(i,j);
+
+ if( !isDefault( end_[i]->value_ ) ) {
+ end_[i]->index_ = j;
+ ++end_[i];
+ ++nonzeros;
+ }
+ }
+ }
+
+ begin_[m_] = begin_[0UL]+nonzeros;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CompressedMatrix<Type,SO>::assign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+ BLAZE_INTERNAL_ASSERT( capacity() >= (~rhs).nonZeros(), "Invalid capacity detected" );
+
+ if( m_ == 0UL || begin_[0] == nullptr )
+ return;
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ begin_[i+1UL] = end_[i] = std::copy( (~rhs).begin(i), (~rhs).end(i), begin_[i] );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CompressedMatrix<Type,SO>::assign( const SparseMatrix<MT,!SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+ BLAZE_INTERNAL_ASSERT( capacity() >= (~rhs).nonZeros(), "Invalid capacity detected" );
+
+ typedef ConstIterator_<MT> RhsIterator;
+
+ // Counting the number of elements per row
+ std::vector<size_t> rowLengths( m_, 0UL );
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ ++rowLengths[element->index()];
+ }
+
+ // Resizing the sparse matrix
+ for( size_t i=0UL; i<m_; ++i ) {
+ begin_[i+1UL] = end_[i+1UL] = begin_[i] + rowLengths[i];
+ }
+
+ // Appending the elements to the rows of the sparse matrix
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ append( element->index(), j, element->value() );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline void CompressedMatrix<Type,SO>::addAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ CompressedMatrix tmp( serial( *this + (~rhs) ) );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side sparse matrix
+ , bool SO2 > // Storage order of the right-hand side sparse matrix
+inline void CompressedMatrix<Type,SO>::addAssign( const SparseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ CompressedMatrix tmp( serial( *this + (~rhs) ) );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO2 > // Storage order of the right-hand side dense matrix
+inline void CompressedMatrix<Type,SO>::subAssign( const DenseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ CompressedMatrix tmp( serial( *this - (~rhs) ) );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+template< typename MT // Type of the right-hand side sparse matrix
+ , bool SO2 > // Storage order of the right-hand sparse matrix
+inline void CompressedMatrix<Type,SO>::subAssign( const SparseMatrix<MT,SO2>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ CompressedMatrix tmp( serial( *this - (~rhs) ) );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of CompressedMatrix for column-major matrices.
+// \ingroup compressed_matrix
+//
+// This specialization of CompressedMatrix adapts the class template to the requirements of
+// column-major matrices.
+*/
+template< typename Type > // Data type of the sparse matrix
+class CompressedMatrix<Type,true> : public SparseMatrix< CompressedMatrix<Type,true>, true >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ValueIndexPair<Type> ElementBase; //!< Base class for the sparse matrix element.
+ //**********************************************************************************************
+
+ //**Private class Element***********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Value-index-pair for the CompressedMatrix class.
+ */
+ struct Element : public ElementBase
+ {
+ // This operator is required due to a bug in all versions of the the MSVC compiler.
+ // A simple 'using ElementBase::operator=;' statement results in ambiguity problems.
+ template< typename Other >
+ inline Element& operator=( const Other& rhs )
+ {
+ ElementBase::operator=( rhs );
+ return *this;
+ }
+
+ friend class CompressedMatrix;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef CompressedMatrix<Type,true> This; //!< Type of this CompressedMatrix instance.
+ typedef SparseMatrix<This,true> BaseType; //!< Base type of this CompressedMatrix instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef CompressedMatrix<Type,false> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef CompressedMatrix<Type,false> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the sparse matrix elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const This& CompositeType; //!< Data type for composite expression templates.
+ typedef MatrixAccessProxy<This> Reference; //!< Reference to a non-constant matrix value.
+ typedef const Type& ConstReference; //!< Reference to a constant matrix value.
+ typedef Element* Iterator; //!< Iterator over non-constant elements.
+ typedef const Element* ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a CompressedMatrix with different data/element type.
+ */
+ template< typename ET > // Data type of the other matrix
+ struct Rebind {
+ typedef CompressedMatrix<ET,true> Other; //!< The type of the other CompressedMatrix.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline CompressedMatrix();
+ explicit inline CompressedMatrix( size_t m, size_t n );
+ explicit inline CompressedMatrix( size_t m, size_t n, size_t nonzeros );
+ explicit CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros );
+ inline CompressedMatrix( const CompressedMatrix& sm );
+ inline CompressedMatrix( CompressedMatrix&& sm ) noexcept;
+ template< typename MT, bool SO > inline CompressedMatrix( const DenseMatrix<MT,SO>& dm );
+ template< typename MT, bool SO > inline CompressedMatrix( const SparseMatrix<MT,SO>& sm );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~CompressedMatrix();
+ //@}
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j ) noexcept;
+ inline ConstReference operator()( size_t i, size_t j ) const noexcept;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i ) noexcept;
+ inline ConstIterator begin ( size_t i ) const noexcept;
+ inline ConstIterator cbegin( size_t i ) const noexcept;
+ inline Iterator end ( size_t i ) noexcept;
+ inline ConstIterator end ( size_t i ) const noexcept;
+ inline ConstIterator cend ( size_t i ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline CompressedMatrix& operator=( const CompressedMatrix& rhs );
+ inline CompressedMatrix& operator=( CompressedMatrix&& rhs ) noexcept;
+
+ template< typename MT, bool SO > inline CompressedMatrix& operator= ( const DenseMatrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline CompressedMatrix& operator= ( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline CompressedMatrix& operator+=( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline CompressedMatrix& operator-=( const Matrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline CompressedMatrix& operator*=( const Matrix<MT,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, CompressedMatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, CompressedMatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t rows() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t j ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t j ) const;
+ inline void reset();
+ inline void reset( size_t j );
+ inline void clear();
+ inline Iterator set ( size_t i, size_t j, const Type& value );
+ inline Iterator insert ( size_t i, size_t j, const Type& value );
+ inline void erase ( size_t i, size_t j );
+ inline Iterator erase ( size_t j, Iterator pos );
+ inline Iterator erase ( size_t j, Iterator first, Iterator last );
+ void resize ( size_t m, size_t n, bool preserve=true );
+ inline void reserve( size_t nonzeros );
+ void reserve( size_t j, size_t nonzeros );
+ inline void trim ();
+ inline void trim ( size_t j );
+ inline CompressedMatrix& transpose();
+ inline CompressedMatrix& ctranspose();
+ template< typename Other > inline CompressedMatrix& scale( const Other& scalar );
+ template< typename Other > inline CompressedMatrix& scaleDiagonal( Other scalar );
+ inline void swap( CompressedMatrix& sm ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const Type& value, bool check=false );
+ inline void finalize( size_t j );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+
+ template< typename MT, bool SO > inline void assign ( const DenseMatrix<MT,SO>& rhs );
+ template< typename MT > inline void assign ( const SparseMatrix<MT,true>& rhs );
+ template< typename MT > inline void assign ( const SparseMatrix<MT,false>& rhs );
+ template< typename MT, bool SO > inline void addAssign( const DenseMatrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline void subAssign( const DenseMatrix<MT,SO>& rhs );
+ template< typename MT, bool SO > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ Iterator insert( Iterator pos, size_t i, size_t j, const Type& value );
+ inline size_t extendCapacity() const noexcept;
+ void reserveElements( size_t nonzeros );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t m_; //!< The current number of rows of the sparse matrix.
+ size_t n_; //!< The current number of columns of the sparse matrix.
+ size_t capacity_; //!< The current capacity of the pointer array.
+ Iterator* begin_; //!< Pointers to the first non-zero element of each column.
+ Iterator* end_; //!< Pointers one past the last non-zero element of each column.
+
+ static const Type zero_; //!< Neutral element for accesses to zero elements.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_CONSTRAINT_MUST_HAVE_SAME_SIZE ( ElementBase, Element );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
+//
+//=================================================================================================
+
+template< typename Type >
+const Type CompressedMatrix<Type,true>::zero_ = Type();
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The default constructor for CompressedMatrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>::CompressedMatrix()
+ : m_ ( 0UL ) // The current number of rows of the sparse matrix
+ , n_ ( 0UL ) // The current number of columns of the sparse matrix
+ , capacity_( 0UL ) // The current capacity of the pointer array
+ , begin_ ( nullptr ) // Pointers to the first non-zero element of each column
+ , end_ ( nullptr ) // Pointers one past the last non-zero element of each column
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ M \times N \f$.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+//
+// The matrix is initialized to the zero matrix and has no free capacity.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n )
+ : m_ ( m ) // The current number of rows of the sparse matrix
+ , n_ ( n ) // The current number of columns of the sparse matrix
+ , capacity_( n ) // The current capacity of the pointer array
+ , begin_( new Iterator[2UL*n+2UL] ) // Pointers to the first non-zero element of each column
+ , end_ ( begin_+(n+1UL) ) // Pointers one past the last non-zero element of each column
+{
+ for( size_t j=0UL; j<2UL*n_+2UL; ++j )
+ begin_[j] = nullptr;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ M \times N \f$.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param nonzeros The number of expected non-zero elements.
+//
+// The matrix is initialized to the zero matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n, size_t nonzeros )
+ : m_ ( m ) // The current number of rows of the sparse matrix
+ , n_ ( n ) // The current number of columns of the sparse matrix
+ , capacity_( n ) // The current capacity of the pointer array
+ , begin_( new Iterator[2UL*n+2UL] ) // Pointers to the first non-zero element of each column
+ , end_ ( begin_+(n+1UL) ) // Pointers one past the last non-zero element of each column
+{
+ begin_[0UL] = allocate<Element>( nonzeros );
+ for( size_t j=1UL; j<(2UL*n_+1UL); ++j )
+ begin_[j] = begin_[0UL];
+ end_[n_] = begin_[0UL]+nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Constructor for a matrix of size \f$ M \times N \f$.
+//
+// \param m The number of rows of the matrix.
+// \param n The number of columns of the matrix.
+// \param nonzeros The expected number of non-zero elements in each column.
+//
+// The matrix is initialized to the zero matrix and will have the specified capacity in each
+// column. Note that the given vector must have at least \a n elements.
+*/
+template< typename Type > // Data type of the sparse matrix
+CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros )
+ : m_ ( m ) // The current number of rows of the sparse matrix
+ , n_ ( n ) // The current number of columns of the sparse matrix
+ , capacity_( n ) // The current capacity of the pointer array
+ , begin_( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
+ , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
+{
+ BLAZE_USER_ASSERT( nonzeros.size() == n, "Size of capacity vector and number of columns don't match" );
+
+ size_t newCapacity( 0UL );
+ for( std::vector<size_t>::const_iterator it=nonzeros.begin(); it!=nonzeros.end(); ++it )
+ newCapacity += *it;
+
+ begin_[0UL] = end_[0UL] = allocate<Element>( newCapacity );
+ for( size_t j=0UL; j<n_; ++j ) {
+ begin_[j+1UL] = end_[j+1UL] = begin_[j] + nonzeros[j];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The copy constructor for CompressedMatrix.
+//
+// \param sm Sparse matrix to be copied.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>::CompressedMatrix( const CompressedMatrix& sm )
+ : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
+ , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
+ , capacity_( sm.n_ ) // The current capacity of the pointer array
+ , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
+ , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
+{
+ const size_t nonzeros( sm.nonZeros() );
+
+ begin_[0UL] = allocate<Element>( nonzeros );
+ for( size_t j=0UL; j<n_; ++j )
+ begin_[j+1UL] = end_[j] = std::copy( sm.begin(j), sm.end(j), begin_[j] );
+ end_[n_] = begin_[0UL]+nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The move constructor for CompressedMatrix.
+//
+// \param sm The sparse matrix to be moved into this instance.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>::CompressedMatrix( CompressedMatrix&& sm ) noexcept
+ : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
+ , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
+ , capacity_( sm.capacity_ ) // The current capacity of the pointer array
+ , begin_ ( sm.begin_ ) // Pointers to the first non-zero element of each column
+ , end_ ( sm.end_ ) // Pointers one past the last non-zero element of each column
+{
+ sm.m_ = 0UL;
+ sm.n_ = 0UL;
+ sm.capacity_ = 0UL;
+ sm.begin_ = nullptr;
+ sm.end_ = nullptr;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from dense matrices.
+//
+// \param dm Dense matrix to be copied.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the foreign dense matrix
+ , bool SO > // Storage order of the foreign dense matrix
+inline CompressedMatrix<Type,true>::CompressedMatrix( const DenseMatrix<MT,SO>& dm )
+ : m_ ( (~dm).rows() ) // The current number of rows of the sparse matrix
+ , n_ ( (~dm).columns() ) // The current number of columns of the sparse matrix
+ , capacity_( n_ ) // The current capacity of the pointer array
+ , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
+ , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
+{
+ using blaze::assign;
+
+ for( size_t j=0UL; j<2UL*n_+2UL; ++j )
+ begin_[j] = nullptr;
+
+ assign( *this, ~dm );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion constructor from different sparse matrices.
+//
+// \param sm Sparse matrix to be copied.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the foreign sparse matrix
+ , bool SO > // Storage order of the foreign sparse matrix
+inline CompressedMatrix<Type,true>::CompressedMatrix( const SparseMatrix<MT,SO>& sm )
+ : m_ ( (~sm).rows() ) // The current number of rows of the sparse matrix
+ , n_ ( (~sm).columns() ) // The current number of columns of the sparse matrix
+ , capacity_( n_ ) // The current capacity of the pointer array
+ , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
+ , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
+{
+ using blaze::assign;
+
+ const size_t nonzeros( (~sm).nonZeros() );
+
+ begin_[0UL] = allocate<Element>( nonzeros );
+ for( size_t j=0UL; j<n_; ++j )
+ begin_[j+1UL] = end_[j] = begin_[0UL];
+ end_[n_] = begin_[0UL]+nonzeros;
+
+ assign( *this, ~sm );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The destructor for CompressedMatrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>::~CompressedMatrix()
+{
+ if( begin_ != nullptr ) {
+ deallocate( begin_[0UL] );
+ delete[] begin_;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the sparse matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function returns a reference to the accessed value at position (\a i,\a j). In case the
+// compressed matrix does not yet store an element at position (\a i,\a j) , a new element is
+// inserted into the compressed matrix. Note that this function only performs an index check in
+// case BLAZE_USER_ASSERT() is active. In contrast, the at() function is guaranteed to perform a
+// check of the given access indices.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Reference
+ CompressedMatrix<Type,true>::operator()( size_t i, size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return Reference( *this, i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the sparse matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstReference
+ CompressedMatrix<Type,true>::operator()( size_t i, size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const ConstIterator pos( lowerBound( i, j ) );
+
+ if( pos == end_[j] || pos->index_ != i )
+ return zero_;
+ else
+ return pos->value_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// This function returns a reference to the accessed value at position (\a i,\a j). In case the
+// compressed matrix does not yet store an element at position (\a i,\a j) , a new element is
+// inserted into the compressed matrix. In contrast to the subscript operator this function
+// always performs a check of the given access indices.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Reference
+ CompressedMatrix<Type,true>::at( size_t i, size_t j )
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the matrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstReference
+ CompressedMatrix<Type,true>::at( size_t i, size_t j ) const
+{
+ if( i >= m_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= n_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::begin( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
+ return begin_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstIterator
+ CompressedMatrix<Type,true>::begin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
+ return begin_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstIterator
+ CompressedMatrix<Type,true>::cbegin( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
+ return begin_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::end( size_t j ) noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
+ return end_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstIterator
+ CompressedMatrix<Type,true>::end( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
+ return end_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstIterator
+ CompressedMatrix<Type,true>::cend( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
+ return end_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for CompressedMatrix.
+//
+// \param rhs Sparse matrix to be copied.
+// \return Reference to the assigned sparse matrix.
+//
+// The sparse matrix is resized according to the given sparse matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>&
+ CompressedMatrix<Type,true>::operator=( const CompressedMatrix& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ const size_t nonzeros( rhs.nonZeros() );
+
+ if( rhs.n_ > capacity_ || nonzeros > capacity() )
+ {
+ Iterator* newBegin( new Iterator[2UL*rhs.n_+2UL] );
+ Iterator* newEnd ( newBegin+(rhs.n_+1UL) );
+
+ newBegin[0UL] = allocate<Element>( nonzeros );
+ for( size_t j=0UL; j<rhs.n_; ++j ) {
+ newBegin[j+1UL] = newEnd[j] = std::copy( rhs.begin_[j], rhs.end_[j], newBegin[j] );
+ }
+ newEnd[rhs.n_] = newBegin[0UL]+nonzeros;
+
+ std::swap( begin_, newBegin );
+ end_ = newEnd;
+ capacity_ = rhs.n_;
+
+ if( newBegin != nullptr ) {
+ deallocate( newBegin[0UL] );
+ delete[] newBegin;
+ }
+ }
+ else {
+ for( size_t j=0UL; j<rhs.n_; ++j ) {
+ begin_[j+1UL] = end_[j] = std::copy( rhs.begin_[j], rhs.end_[j], begin_[j] );
+ }
+ }
+
+ m_ = rhs.m_;
+ n_ = rhs.n_;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Move assignment operator for CompressedMatrix.
+//
+// \param rhs The sparse matrix to be moved into this instance.
+// \return Reference to the assigned sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>&
+ CompressedMatrix<Type,true>::operator=( CompressedMatrix&& rhs ) noexcept
+{
+ if( begin_ != nullptr ) {
+ deallocate( begin_[0UL] );
+ delete[] begin_;
+ }
+
+ m_ = rhs.m_;
+ n_ = rhs.n_;
+ capacity_ = rhs.capacity_;
+ begin_ = rhs.begin_;
+ end_ = rhs.end_;
+
+ rhs.m_ = 0UL;
+ rhs.n_ = 0UL;
+ rhs.capacity_ = 0UL;
+ rhs.begin_ = nullptr;
+ rhs.end_ = nullptr;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for dense matrices.
+//
+// \param rhs Dense matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline CompressedMatrix<Type,true>&
+ CompressedMatrix<Type,true>::operator=( const DenseMatrix<MT,SO>& rhs )
+{
+ using blaze::assign;
+
+ if( (~rhs).canAlias( this ) ) {
+ CompressedMatrix tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( (~rhs).rows(), (~rhs).columns(), false );
+ assign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different sparse matrices.
+//
+// \param rhs Sparse matrix to be copied.
+// \return Reference to the assigned matrix.
+//
+// The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
+// copy of this matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline CompressedMatrix<Type,true>&
+ CompressedMatrix<Type,true>::operator=( const SparseMatrix<MT,SO>& rhs )
+{
+ using blaze::assign;
+
+ if( (~rhs).canAlias( this ) ||
+ (~rhs).columns() > capacity_ ||
+ (~rhs).nonZeros() > capacity() ) {
+ CompressedMatrix tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ resize( (~rhs).rows(), (~rhs).columns(), false );
+ reset();
+ assign( *this, ~rhs );
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::operator+=( const Matrix<MT,SO>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ addAssign( *this, ~rhs );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the matrix.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::operator-=( const Matrix<MT,SO>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ subAssign( *this, ~rhs );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the matrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+//
+// In case the current sizes of the two given matrices don't match, a \a std::invalid_argument
+// is thrown.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline CompressedMatrix<Type,true>&
+ CompressedMatrix<Type,true>::operator*=( const Matrix<MT,SO>& rhs )
+{
+ if( (~rhs).rows() != n_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ CompressedMatrix tmp( *this * (~rhs) );
+ swap( tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse matrix and
+// \brief a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, CompressedMatrix<Type,true> >&
+ CompressedMatrix<Type,true>::operator*=( Other rhs )
+{
+ for( size_t j=0UL; j<n_; ++j ) {
+ const Iterator last( end(j) );
+ for( Iterator element=begin(j); element!=last; ++element )
+ element->value_ *= rhs;
+ }
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse matrix by a scalar value
+// \brief (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, CompressedMatrix<Type,true> >&
+ CompressedMatrix<Type,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<Type,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( size_t j=0UL; j<n_; ++j ) {
+ const Iterator last( end(j) );
+ for( Iterator element=begin(j); element!=last; ++element )
+ element->value_ *= tmp;
+ }
+ }
+ else {
+ for( size_t j=0UL; j<n_; ++j ) {
+ const Iterator last( end(j) );
+ for( Iterator element=begin(j); element!=last; ++element )
+ element->value_ /= rhs;
+ }
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of rows of the sparse matrix.
+//
+// \return The number of rows of the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline size_t CompressedMatrix<Type,true>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current number of columns of the sparse matrix.
+//
+// \return The number of columns of the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline size_t CompressedMatrix<Type,true>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse matrix.
+//
+// \return The capacity of the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline size_t CompressedMatrix<Type,true>::capacity() const noexcept
+{
+ if( begin_ != nullptr )
+ return end_[n_] - begin_[0UL];
+ else return 0UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified column.
+//
+// \param j The index of the column.
+// \return The current capacity of column \a j.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline size_t CompressedMatrix<Type,true>::capacity( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return begin_[j+1UL] - begin_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the sparse matrix
+//
+// \return The number of non-zero elements in the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline size_t CompressedMatrix<Type,true>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t j=0UL; j<n_; ++j )
+ nonzeros += nonZeros( j );
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified column.
+//
+// \param j The index of the column.
+// \return The number of non-zero elements of column \a j.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline size_t CompressedMatrix<Type,true>::nonZeros( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return end_[j] - begin_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type > // Data type of the sparse matrix
+inline void CompressedMatrix<Type,true>::reset()
+{
+ for( size_t j=0UL; j<n_; ++j )
+ end_[j] = begin_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified column to the default initial values.
+//
+// \param j The index of the column.
+// \return void
+//
+// This function reset the values in the specified column to their default value. Note that
+// the capacity of the column remains unchanged.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline void CompressedMatrix<Type,true>::reset( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ end_[j] = begin_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Clearing the sparse matrix.
+//
+// \return void
+//
+// After the clear() function, the size of the sparse matrix is 0.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline void CompressedMatrix<Type,true>::clear()
+{
+ end_[0UL] = end_[n_];
+ m_ = 0UL;
+ n_ = 0UL;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the compressed matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+//
+// This function sets the value of an element of the compressed matrix. In case the compressed
+// matrix already contains an element with row index \a i and column index \a j its value is
+// modified, else a new element with the given \a value is inserted.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::set( size_t i, size_t j, const Type& value )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const Iterator pos( lowerBound( i, j ) );
+
+ if( pos != end_[j] && pos->index_ == i ) {
+ pos->value() = value;
+ return pos;
+ }
+ else return insert( pos, i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the compressed matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid compressed matrix access index.
+//
+// This function inserts a new element into the compressed matrix. However, duplicate elements
+// are not allowed. In case the compressed matrix already contains an element with row index \a i
+// and column index \a j, a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::insert( size_t i, size_t j, const Type& value )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const Iterator pos( lowerBound( i, j ) );
+
+ if( pos != end_[j] && pos->index_ == i ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Bad access index" );
+ }
+
+ return insert( pos, i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the compressed matrix.
+//
+// \param pos The position of the new element.
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid compressed matrix access index.
+*/
+template< typename Type > // Data type of the sparse matrix
+typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::insert( Iterator pos, size_t i, size_t j, const Type& value )
+{
+ if( begin_[j+1UL] - end_[j] != 0 ) {
+ std::move_backward( pos, end_[j], end_[j]+1UL );
+ pos->value_ = value;
+ pos->index_ = i;
+ ++end_[j];
+
+ return pos;
+ }
+ else if( end_[n_] - begin_[n_] != 0 ) {
+ std::move_backward( pos, end_[n_-1UL], end_[n_-1]+1UL );
+
+ pos->value_ = value;
+ pos->index_ = i;
+
+ for( size_t k=j+1UL; k<n_+1UL; ++k ) {
+ ++begin_[k];
+ ++end_[k-1UL];
+ }
+
+ return pos;
+ }
+ else {
+ size_t newCapacity( extendCapacity() );
+
+ Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
+ Iterator* newEnd = newBegin+capacity_+1UL;
+
+ newBegin[0UL] = allocate<Element>( newCapacity );
+
+ for( size_t k=0UL; k<j; ++k ) {
+ const size_t nonzeros( end_[k] - begin_[k] );
+ const size_t total( begin_[k+1UL] - begin_[k] );
+ newEnd [k] = newBegin[k] + nonzeros;
+ newBegin[k+1UL] = newBegin[k] + total;
+ }
+ newEnd [j] = newBegin[j] + ( end_[j] - begin_[j] ) + 1;
+ newBegin[j+1UL] = newBegin[j] + ( begin_[j+1UL] - begin_[j] ) + 1;
+ for( size_t k=j+1UL; k<n_; ++k ) {
+ const size_t nonzeros( end_[k] - begin_[k] );
+ const size_t total( begin_[k+1UL] - begin_[k] );
+ newEnd [k] = newBegin[k] + nonzeros;
+ newBegin[k+1UL] = newBegin[k] + total;
+ }
+
+ newEnd[n_] = newEnd[capacity_] = newBegin[0UL]+newCapacity;
+
+ Iterator tmp = std::move( begin_[0UL], pos, newBegin[0UL] );
+ tmp->value_ = value;
+ tmp->index_ = i;
+ std::move( pos, end_[n_-1UL], tmp+1UL );
+
+ std::swap( newBegin, begin_ );
+ end_ = newEnd;
+ deallocate( newBegin[0UL] );
+ delete[] newBegin;
+
+ return tmp;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse matrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline void CompressedMatrix<Type,true>::erase( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const Iterator pos( find( i, j ) );
+ if( pos != end_[j] )
+ end_[j] = std::move( pos+1, end_[j], pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse matrix.
+//
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return void
+//
+// This function erases an element from column \a j of the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::erase( size_t j, Iterator pos )
+{
+ BLAZE_USER_ASSERT( j < columns() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( pos >= begin_[j] && pos <= end_[j], "Invalid compressed matrix iterator" );
+
+ if( pos != end_[j] )
+ end_[j] = std::move( pos+1, end_[j], pos );
+
+ return pos;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse matrix.
+//
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return void
+//
+// This function erases a range of elements from column \a j of the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::erase( size_t j, Iterator first, Iterator last )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid row access index" );
+ BLAZE_USER_ASSERT( first <= last, "Invalid iterator range" );
+ BLAZE_USER_ASSERT( first >= begin_[j] && first <= end_[j], "Invalid compressed matrix iterator" );
+ BLAZE_USER_ASSERT( last >= begin_[j] && last <= end_[j], "Invalid compressed matrix iterator" );
+
+ if( first != last )
+ end_[j] = std::move( last, end_[j], first );
+
+ return first;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Changing the size of the sparse matrix.
+//
+// \param m The new number of rows of the sparse matrix.
+// \param n The new number of columns of the sparse matrix.
+// \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the matrix using the given size to \f$ m \times n \f$. During this
+// operation, new dynamic memory may be allocated in case the capacity of the matrix is too
+// small. Note that this function may invalidate all existing views (submatrices, rows, columns,
+// ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
+// potentially changes all matrix elements. In order to preserve the old matrix values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename Type > // Data type of the sparse matrix
+void CompressedMatrix<Type,true>::resize( size_t m, size_t n, bool preserve )
+{
+ BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
+ BLAZE_INTERNAL_ASSERT( begin_ == nullptr || size_t( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
+
+ if( m == m_ && n == n_ ) return;
+
+ if( begin_ == nullptr )
+ {
+ begin_ = new Iterator[2UL*n+2UL];
+ end_ = begin_+n+1UL;
+
+ for( size_t j=0UL; j<2UL*n+2UL; ++j ) {
+ begin_[j] = nullptr;
+ }
+
+ capacity_ = n;
+ }
+ else if( n > capacity_ )
+ {
+ Iterator* newBegin( new Iterator[2UL*n+2UL] );
+ Iterator* newEnd ( newBegin+n+1UL );
+
+ newBegin[0UL] = begin_[0UL];
+
+ if( preserve ) {
+ for( size_t j=0UL; j<n_; ++j ) {
+ newEnd [j] = end_ [j];
+ newBegin[j+1UL] = begin_[j+1UL];
+ }
+ for( size_t j=n_; j<n; ++j ) {
+ newBegin[j+1UL] = newEnd[j] = begin_[n_];
+ }
+ }
+ else {
+ for( size_t j=0UL; j<n; ++j ) {
+ newBegin[j+1UL] = newEnd[j] = begin_[0UL];
+ }
+ }
+
+ newEnd[n] = end_[n_];
+
+ std::swap( newBegin, begin_ );
+ delete[] newBegin;
+ end_ = newEnd;
+ capacity_ = n;
+ }
+ else if( n > n_ )
+ {
+ end_[n] = end_[n_];
+
+ if( !preserve ) {
+ for( size_t j=0UL; j<n_; ++j )
+ end_[j] = begin_[j];
+ }
+
+ for( size_t j=n_; j<n; ++j ) {
+ begin_[j+1UL] = end_[j] = begin_[n_];
+ }
+ }
+ else
+ {
+ if( preserve ) {
+ for( size_t j=0UL; j<n; ++j )
+ end_[j] = lowerBound( m, j );
+ }
+ else {
+ for( size_t j=0UL; j<n; ++j )
+ end_[j] = begin_[j];
+ }
+
+ end_[n] = end_[n_];
+ }
+
+ m_ = m;
+ n_ = n;
+
+ BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
+ BLAZE_INTERNAL_ASSERT( size_t( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse matrix.
+//
+// \param nonzeros The new minimum capacity of the sparse matrix.
+// \return void
+//
+// This function increases the capacity of the sparse matrix to at least \a nonzeros elements.
+// The current values of the matrix elements and the individual capacities of the matrix rows
+// are preserved.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline void CompressedMatrix<Type,true>::reserve( size_t nonzeros )
+{
+ if( nonzeros > capacity() )
+ reserveElements( nonzeros );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific column of the sparse matrix.
+//
+// \param j The column index. The index has to be in the range \f$[0..M-1]\f$.
+// \param nonzeros The new minimum capacity of the specified column.
+// \return void
+//
+// This function increases the capacity of column \a j of the sparse matrix to at least \a nonzeros
+// elements. The current values of the sparse matrix and all other individual column capacities are
+// preserved.
+*/
+template< typename Type > // Data type of the sparse matrix
+void CompressedMatrix<Type,true>::reserve( size_t j, size_t nonzeros )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
+ BLAZE_INTERNAL_ASSERT( static_cast<size_t>( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
+
+ const size_t current( capacity(j) );
+
+ if( current >= nonzeros ) return;
+
+ const ptrdiff_t additional( nonzeros - current );
+
+ if( end_[n_] - begin_[n_] < additional )
+ {
+ const size_t newCapacity( begin_[n_] - begin_[0UL] + additional );
+ BLAZE_INTERNAL_ASSERT( newCapacity > capacity(), "Invalid capacity value" );
+
+ Iterator* newBegin( new Iterator[2UL*n_+2UL] );
+ Iterator* newEnd ( newBegin+n_+1UL );
+
+ newBegin[0UL] = allocate<Element>( newCapacity );
+ newEnd [n_ ] = newBegin[0UL]+newCapacity;
+
+ for( size_t k=0UL; k<j; ++k ) {
+ newEnd [k ] = transfer( begin_[k], end_[k], newBegin[k] );
+ newBegin[k+1UL] = newBegin[k] + capacity(k);
+ }
+ newEnd [j ] = transfer( begin_[j], end_[j], newBegin[j] );
+ newBegin[j+1UL] = newBegin[j] + nonzeros;
+ for( size_t k=j+1UL; k<n_; ++k ) {
+ newEnd [k ] = transfer( begin_[k], end_[k], newBegin[k] );
+ newBegin[k+1UL] = newBegin[k] + capacity(k);
+ }
+
+ BLAZE_INTERNAL_ASSERT( newBegin[n_] == newEnd[n_], "Invalid pointer calculations" );
+
+ std::swap( newBegin, begin_ );
+ deallocate( newBegin[0UL] );
+ delete[] newBegin;
+ end_ = newEnd;
+ capacity_ = n_;
+ }
+ else
+ {
+ begin_[n_] += additional;
+ for( size_t k=n_-1UL; k>j; --k ) {
+ begin_[k] = std::move_backward( begin_[k], end_[k], end_[k]+additional );
+ end_ [k] += additional;
+ }
+ }
+
+ BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
+ BLAZE_INTERNAL_ASSERT( static_cast<size_t>( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all column-specific reserve() calls
+// It removes all excessive capacity from all columns. Note that this function does not remove
+// the overall capacity but only reduces the capacity per column.
+*/
+template< typename Type > // Data type of the sparse matrix
+void CompressedMatrix<Type,true>::trim()
+{
+ for( size_t j=0UL; j<n_; ++j )
+ trim( j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific column of the sparse matrix.
+//
+// \param j The index of the column to be trimmed (\f$[0..N-1]\f$).
+// \return void
+//
+// This function can be used to reverse the effect of a column-specific reserve() call. It
+// removes all excessive capacity from the specified column. The excessive capacity is assigned
+// to the subsequent column.
+*/
+template< typename Type > // Data type of the sparse matrix
+void CompressedMatrix<Type,true>::trim( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ if( j < ( n_ - 1UL ) )
+ end_[j+1] = std::move( begin_[j+1], end_[j+1], end_[j] );
+ begin_[j+1] = end_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::transpose()
+{
+ CompressedMatrix tmp( trans( *this ) );
+ swap( tmp );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the matrix.
+//
+// \return Reference to the transposed matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::ctranspose()
+{
+ CompressedMatrix tmp( ctrans( *this ) );
+ swap( tmp );
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse matrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the matrix scaling.
+// \return Reference to the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename Other > // Data type of the scalar value
+inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::scale( const Other& scalar )
+{
+ for( size_t j=0UL; j<n_; ++j )
+ for( Iterator element=begin_[j]; element!=end_[j]; ++element )
+ element->value_ *= scalar;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling the diagonal of the sparse matrix by the scalar value \a scalar.
+//
+// \param scalar The scalar value for the diagonal scaling.
+// \return Reference to the sparse matrix.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename Other > // Data type of the scalar value
+inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::scaleDiagonal( Other scalar )
+{
+ const size_t size( blaze::min( m_, n_ ) );
+
+ for( size_t j=0UL; j<size; ++j ) {
+ Iterator pos = lowerBound( j, j );
+ if( pos != end_[j] && pos->index_ == j )
+ pos->value_ *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Swapping the contents of two sparse matrices.
+//
+// \param sm The sparse matrix to be swapped.
+// \return void
+*/
+template< typename Type > // Data type of the sparse matrix
+inline void CompressedMatrix<Type,true>::swap( CompressedMatrix& sm ) noexcept
+{
+ std::swap( m_, sm.m_ );
+ std::swap( n_, sm.n_ );
+ std::swap( capacity_, sm.capacity_ );
+ std::swap( begin_, sm.begin_ );
+ std::swap( end_ , sm.end_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating a new matrix capacity.
+//
+// \return The new sparse matrix capacity.
+//
+// This function calculates a new matrix capacity based on the current capacity of the sparse
+// matrix. Note that the new capacity is restricted to the interval \f$[7..M \cdot N]\f$.
+*/
+template< typename Type > // Data type of the sparse matrix
+inline size_t CompressedMatrix<Type,true>::extendCapacity() const noexcept
+{
+ size_t nonzeros( 2UL*capacity()+1UL );
+ nonzeros = blaze::max( nonzeros, 7UL );
+
+ BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reserving the specified number of sparse matrix elements.
+//
+// \param nonzeros The number of matrix elements to be reserved.
+// \return void
+*/
+template< typename Type > // Data type of the sparse matrix
+void CompressedMatrix<Type,true>::reserveElements( size_t nonzeros )
+{
+ Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
+ Iterator* newEnd = newBegin+capacity_+1UL;
+
+ newBegin[0UL] = allocate<Element>( nonzeros );
+
+ for( size_t k=0UL; k<n_; ++k ) {
+ BLAZE_INTERNAL_ASSERT( begin_[k] <= end_[k], "Invalid column pointers" );
+ newEnd [k] = transfer( begin_[k], end_[k], newBegin[k] );
+ newBegin[k+1UL] = newBegin[k] + ( begin_[k+1UL] - begin_[k] );
+ }
+
+ newEnd[n_] = newBegin[0UL]+nonzeros;
+
+ std::swap( newBegin, begin_ );
+ end_ = newEnd;
+
+ if( newBegin != nullptr ) {
+ deallocate( newBegin[0UL] );
+ delete[] newBegin;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an iterator to the element. Otherwise an
+// iterator just past the last non-zero element of column \a j (the end() iterator) is returned.
+// Note that the returned sparse matrix iterator is subject to invalidation due to inserting
+// operations via the subscript operator or the insert() function!
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::find( size_t i, size_t j )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).find( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific matrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// matrix. It specifically searches for the element with row index \a i and column index \a j.
+// In case the element is found, the function returns an iterator to the element. Otherwise an
+// iterator just past the last non-zero element of column \a j (the end() iterator) is returned.
+// Note that the returned sparse matrix iterator is subject to invalidation due to inserting
+// operations via the subscript operator or the insert() function!
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstIterator
+ CompressedMatrix<Type,true>::find( size_t i, size_t j ) const
+{
+ const ConstIterator pos( lowerBound( i, j ) );
+ if( pos != end_[j] && pos->index_ == i )
+ return pos;
+ else return end_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// The function returns a column iterator to the first element with an index not less then the
+// given row index. In combination with the upperBound() function this function can be used to
+// create a pair of iterators specifying a range of indices. Note that the returned compressed
+// matrix iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::lowerBound( size_t i, size_t j )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).lowerBound( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// The function returns a column iterator to the first element with an index not less then the
+// given row index. In combination with the upperBound() function this function can be used to
+// create a pair of iterators specifying a range of indices. Note that the returned compressed
+// matrix iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstIterator
+ CompressedMatrix<Type,true>::lowerBound( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return std::lower_bound( begin_[j], end_[j], i,
+ []( const Element& element, size_t index )
+ {
+ return element.index() < index;
+ } );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// The function returns a column iterator to the first element with an index greater then the
+// given row index. In combination with the upperBound() function this function can be used to
+// create a pair of iterators specifying a range of indices. Note that the returned compressed
+// matrix iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::Iterator
+ CompressedMatrix<Type,true>::upperBound( size_t i, size_t j )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).upperBound( i, j ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// The function returns a column iterator to the first element with an index greater then the
+// given row index. In combination with the upperBound() function this function can be used to
+// create a pair of iterators specifying a range of indices. Note that the returned compressed
+// matrix iterator is subject to invalidation due to inserting operations via the function call
+// operator or the insert() function!
+*/
+template< typename Type > // Data type of the sparse matrix
+inline typename CompressedMatrix<Type,true>::ConstIterator
+ CompressedMatrix<Type,true>::upperBound( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return std::upper_bound( begin_[j], end_[j], i,
+ []( size_t index, const Element& element )
+ {
+ return index < element.index();
+ } );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the specified column of the sparse matrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse matrix with elements. It appends
+// a new element to the end of the specified column without any additional memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified column of the sparse matrix
+// - the current number of non-zero elements in the matrix must be smaller than the capacity of
+// the matrix.
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a (new created) sparse matrix:
+
+ \code
+ blaze::CompressedMatrix<double,columnMajor> A( 3, 4 );
+ A.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ A.append( 1, 0, 1.0 ); // Appending the value 1 in column 0 with row index 1
+ A.finalize( 0 ); // Finalizing column 0
+ A.append( 1, 1, 2.0 ); // Appending the value 2 in column 1 with row index 1
+ A.finalize( 1 ); // Finalizing column 1
+ A.finalize( 1 ); // Finalizing the empty column 2 to prepare column 3
+ A.append( 0, 3, 3.0 ); // Appending the value 3 in column 3 with row index 0
+ A.finalize( 3 ); // Finalizing column 3
+ \endcode
+
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename Type > // Data type of the sparse matrix
+inline void CompressedMatrix<Type,true>::append( size_t i, size_t j, const Type& value, bool check )
+{
+ BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < n_, "Invalid column access index" );
+ BLAZE_USER_ASSERT( end_[j] < end_[n_], "Not enough reserved capacity left" );
+ BLAZE_USER_ASSERT( begin_[j] == end_[j] || i > ( end_[j]-1UL )->index_, "Index is not strictly increasing" );
+
+ end_[j]->value_ = value;
+
+ if( !check || !isDefault( end_[j]->value_ ) ) {
+ end_[j]->index_ = i;
+ ++end_[j];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a column.
+//
+// \param j The index of the column to be finalized \f$[0..M-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill the matrix with elements.
+// After completion of column \a j via the append() function, this function can be called to
+// finalize column \a j and prepare the next column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename Type > // Data type of the sparse matrix
+inline void CompressedMatrix<Type,true>::finalize( size_t j )
+{
+ BLAZE_USER_ASSERT( j < n_, "Invalid row access index" );
+
+ begin_[j+1UL] = end_[j];
+ if( j != n_-1UL )
+ end_[j+1UL] = end_[j];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address can alias with the vector. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool CompressedMatrix<Type,true>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this matrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the vector. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool CompressedMatrix<Type,true>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the matrix can be used in SMP assignments.
+//
+// \return \a true in case the matrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the matrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename Type > // Data type of the sparse matrix
+inline bool CompressedMatrix<Type,true>::canSMPAssign() const noexcept
+{
+ return false;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void CompressedMatrix<Type,true>::assign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ if( m_ == 0UL || n_ == 0UL )
+ return;
+
+ size_t nonzeros( 0UL );
+
+ for( size_t j=1UL; j<=n_; ++j )
+ begin_[j] = end_[j] = end_[n_];
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ begin_[j] = end_[j] = begin_[0UL]+nonzeros;
+
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( IsStrictlyLower<MT>::value ? j+1UL : j )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ {
+ if( nonzeros == capacity() ) {
+ reserveElements( extendCapacity() );
+ for( size_t k=j+1UL; k<=n_; ++k )
+ begin_[k] = end_[k] = end_[n_];
+ }
+
+ end_[j]->value_ = (~rhs)(i,j);
+
+ if( !isDefault( end_[j]->value_ ) ) {
+ end_[j]->index_ = i;
+ ++end_[j];
+ ++nonzeros;
+ }
+ }
+ }
+
+ begin_[n_] = begin_[0UL]+nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CompressedMatrix<Type,true>::assign( const SparseMatrix<MT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+ BLAZE_INTERNAL_ASSERT( capacity() >= (~rhs).nonZeros(), "Invalid capacity detected" );
+
+ if( n_ == 0UL || begin_[0] == nullptr )
+ return;
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ begin_[j+1UL] = end_[j] = std::copy( (~rhs).begin(j), (~rhs).end(j), begin_[j] );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT > // Type of the right-hand side sparse matrix
+inline void CompressedMatrix<Type,true>::assign( const SparseMatrix<MT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+ BLAZE_INTERNAL_ASSERT( capacity() >= (~rhs).nonZeros(), "Invalid capacity detected" );
+
+ typedef ConstIterator_<MT> RhsIterator;
+
+ // Counting the number of elements per column
+ std::vector<size_t> columnLengths( n_, 0UL );
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ ++columnLengths[element->index()];
+ }
+
+ // Resizing the sparse matrix
+ for( size_t j=0UL; j<n_; ++j ) {
+ begin_[j+1UL] = end_[j+1UL] = begin_[j] + columnLengths[j];
+ }
+
+ // Appending the elements to the columns of the sparse matrix
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ append( i, element->index(), element->value() );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void CompressedMatrix<Type,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ CompressedMatrix tmp( serial( *this + (~rhs) ) );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline void CompressedMatrix<Type,true>::addAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ CompressedMatrix tmp( serial( *this + (~rhs) ) );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void CompressedMatrix<Type,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ CompressedMatrix tmp( serial( *this - (~rhs) ) );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type > // Data type of the sparse matrix
+template< typename MT // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline void CompressedMatrix<Type,true>::subAssign( const SparseMatrix<MT,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ CompressedMatrix tmp( serial( *this - (~rhs) ) );
+ swap( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// COMPRESSEDMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name CompressedMatrix operators */
+//@{
+template< typename Type, bool SO >
+inline void reset( CompressedMatrix<Type,SO>& m );
+
+template< typename Type, bool SO >
+inline void reset( CompressedMatrix<Type,SO>& m, size_t i );
+
+template< typename Type, bool SO >
+inline void clear( CompressedMatrix<Type,SO>& m );
+
+template< typename Type, bool SO >
+inline bool isDefault( const CompressedMatrix<Type,SO>& m );
+
+template< typename Type, bool SO >
+inline bool isIntact( const CompressedMatrix<Type,SO>& m );
+
+template< typename Type, bool SO >
+inline void swap( CompressedMatrix<Type,SO>& a, CompressedMatrix<Type,SO>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given compressed matrix.
+// \ingroup compressed_matrix
+//
+// \param m The matrix to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void reset( CompressedMatrix<Type,SO>& m )
+{
+ m.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column of the given compressed matrix.
+// \ingroup compressed_matrix
+//
+// \param m The matrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given compressed matrix to
+// their default value. In case the given matrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void reset( CompressedMatrix<Type,SO>& m, size_t i )
+{
+ m.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given compressed matrix.
+// \ingroup compressed_matrix
+//
+// \param m The matrix to be cleared.
+// \return void
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void clear( CompressedMatrix<Type,SO>& m )
+{
+ m.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given compressed matrix is in default state.
+// \ingroup compressed_matrix
+//
+// \param m The matrix to be tested for its default state.
+// \return \a true in case the given matrix's rows and columns are zero, \a false otherwise.
+//
+// This function checks whether the compressed matrix is in default (constructed) state, i.e. if
+// it's number of rows and columns is 0. In case it is in default state, the function returns
+// \a true, else it will return \a false. The following example demonstrates the use of the
+// \a isDefault() function:
+
+ \code
+ blaze::CompressedMatrix<int> A;
+ // ... Resizing and initialization
+ if( isDefault( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline bool isDefault( const CompressedMatrix<Type,SO>& m )
+{
+ return ( m.rows() == 0UL && m.columns() == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given compressed matrix are intact.
+// \ingroup compressed_matrix
+//
+// \param m The compressed matrix to be tested.
+// \return \a true in case the given matrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the compressed matrix are intact, i.e. if
+// its state is valid. In case the invariants are intact, the function returns \a true, else
+// it will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::CompressedMatrix<int> A;
+ // ... Resizing and initialization
+ if( isIntact( A ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline bool isIntact( const CompressedMatrix<Type,SO>& m )
+{
+ return ( m.nonZeros() <= m.capacity() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two compressed matrices.
+// \ingroup compressed_matrix
+//
+// \param a The first matrix to be swapped.
+// \param b The second matrix to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the sparse matrix
+ , bool SO > // Storage order
+inline void swap( CompressedMatrix<Type,SO>& a, CompressedMatrix<Type,SO>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool SO >
+struct IsResizable< CompressedMatrix<T,SO> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2, size_t M, size_t N >
+struct AddTrait< CompressedMatrix<T1,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct AddTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO2 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct AddTrait< StaticMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct AddTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO1 >;
+};
+
+template< typename T1, bool SO, typename T2, size_t M, size_t N >
+struct AddTrait< CompressedMatrix<T1,SO>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct AddTrait< CompressedMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO2 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct AddTrait< HybridMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct AddTrait< HybridMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO1 >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct AddTrait< CompressedMatrix<T1,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct AddTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO2 >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct AddTrait< DynamicMatrix<T1,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct AddTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO, typename T2, bool AF, bool PF >
+struct AddTrait< CompressedMatrix<T1,SO>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct AddTrait< CompressedMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO2 >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2 >
+struct AddTrait< CustomMatrix<T1,AF,PF,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
+struct AddTrait< CustomMatrix<T1,AF,PF,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< AddTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct AddTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = CompressedMatrix< AddTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct AddTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = CompressedMatrix< AddTrait_<T1,T2>, false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2, size_t M, size_t N >
+struct SubTrait< CompressedMatrix<T1,SO>, StaticMatrix<T2,M,N,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct SubTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO2 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct SubTrait< StaticMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct SubTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO1 >;
+};
+
+template< typename T1, bool SO, typename T2, size_t M, size_t N >
+struct SubTrait< CompressedMatrix<T1,SO>, HybridMatrix<T2,M,N,SO> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct SubTrait< CompressedMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO2 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO, typename T2 >
+struct SubTrait< HybridMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct SubTrait< HybridMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO1 >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct SubTrait< CompressedMatrix<T1,SO>, DynamicMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct SubTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO2 >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct SubTrait< DynamicMatrix<T1,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct SubTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO, typename T2, bool AF, bool PF >
+struct SubTrait< CompressedMatrix<T1,SO>, CustomMatrix<T2,AF,PF,SO> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct SubTrait< CompressedMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO2 >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO, typename T2 >
+struct SubTrait< CustomMatrix<T1,AF,PF,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
+struct SubTrait< CustomMatrix<T1,AF,PF,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< SubTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct SubTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
+{
+ using Type = CompressedMatrix< SubTrait_<T1,T2> , SO >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct SubTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = CompressedMatrix< SubTrait_<T1,T2> , false >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2 >
+struct MultTrait< CompressedMatrix<T1,SO>, T2, EnableIf_< IsNumeric<T2> > >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, typename T2, bool SO >
+struct MultTrait< T1, CompressedMatrix<T2,SO>, EnableIf_< IsNumeric<T1> > >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, SO >;
+};
+
+template< typename T1, bool SO, typename T2, size_t N >
+struct MultTrait< CompressedMatrix<T1,SO>, StaticVector<T2,N,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2, bool SO >
+struct MultTrait< StaticVector<T1,N,true>, CompressedMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO, typename T2, size_t N >
+struct MultTrait< CompressedMatrix<T1,SO>, HybridVector<T2,N,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2, bool SO >
+struct MultTrait< HybridVector<T1,N,true>, CompressedMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct MultTrait< CompressedMatrix<T1,SO>, DynamicVector<T2,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, bool SO >
+struct MultTrait< DynamicVector<T1,true>, CompressedMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO, typename T2, bool AF, bool PF >
+struct MultTrait< CompressedMatrix<T1,SO>, CustomVector<T2,AF,PF,false> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2, bool SO >
+struct MultTrait< CustomVector<T1,AF,PF,true>, CompressedMatrix<T2,SO> >
+{
+ using Type = DynamicVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO, typename T2 >
+struct MultTrait< CompressedMatrix<T1,SO>, CompressedVector<T2,false> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2, bool SO >
+struct MultTrait< CompressedVector<T1,true>, CompressedMatrix<T2,SO> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct MultTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct MultTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
+struct MultTrait< CompressedMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
+struct MultTrait< HybridMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct MultTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct MultTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
+struct MultTrait< CompressedMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
+struct MultTrait< CustomMatrix<T1,AF,PF,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+struct MultTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, SO1 >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2 >
+struct DivTrait< CompressedMatrix<T1,SO>, T2, EnableIf_< IsNumeric<T2> > >
+{
+ using Type = CompressedMatrix< DivTrait_<T1,T2>, SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO, typename T2 >
+struct MathTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
+{
+ using HighType = CompressedMatrix< typename MathTrait<T1,T2>::HighType, SO >;
+ using LowType = CompressedMatrix< typename MathTrait<T1,T2>::LowType , SO >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO >
+struct SubmatrixTrait< CompressedMatrix<T1,SO> >
+{
+ using Type = CompressedMatrix<T1,SO>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO >
+struct RowTrait< CompressedMatrix<T1,SO> >
+{
+ using Type = CompressedVector<T1,true>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool SO >
+struct ColumnTrait< CompressedMatrix<T1,SO> >
+{
+ using Type = CompressedVector<T1,false>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/CompressedVector.h b/src/cpu/blaze/math/sparse/CompressedVector.h
new file mode 100644
index 00000000..92aa789a
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/CompressedVector.h
@@ -0,0 +1,2655 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/CompressedVector.h
+// \brief Implementation of an arbitrarily sized compressed vector
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_COMPRESSEDVECTOR_H_
+#define _BLAZE_MATH_SPARSE_COMPRESSEDVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Forward.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/ValueIndexPair.h>
+#include <blaze/math/sparse/VectorAccessProxy.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MathTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/IsResizable.h>
+#include <blaze/math/typetraits/IsSMPAssignable.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/system/TransposeFlag.h>
+#include <blaze/util/Algorithm.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameSize.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Memory.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup compressed_vector CompressedVector
+// \ingroup sparse_vector
+*/
+/*!\brief Efficient implementation of an arbitrary sized sparse vector.
+// \ingroup compressed_vector
+//
+// The CompressedVector class is the representation of an arbitrarily sized sparse vector,
+// which stores only non-zero elements of arbitrary type. The type of the elements and the
+// transpose flag of the vector can be specified via the two template parameters:
+
+ \code
+ template< typename Type, bool TF >
+ class CompressedVector;
+ \endcode
+
+// - Type: specifies the type of the vector elements. CompressedVector can be used with any
+// non-cv-qualified, non-reference, non-pointer element type.
+// - TF : specifies whether the vector is a row vector (\a blaze::rowVector) or a column
+// vector (\a blaze::columnVector). The default value is \a blaze::columnVector.
+//
+// Inserting/accessing elements in a compressed vector can be done by several alternative
+// functions. The following example demonstrates all options:
+
+ \code
+ // Creating a compressed column vector of size 100
+ CompressedVector<double,columnVector> a( 100 );
+
+ // The subscript operator provides access to all possible elements of the compressed vector,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse vector, the element is inserted into the vector.
+ a[42] = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element
+ // is not contained in the vector it is inserted into the vector, if it is already contained
+ // in the vector its value is modified.
+ a.set( 45, -1.2 );
+
+ // An alternative for inserting elements into the vector is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the vector.
+ a.insert( 50, 3.7 );
+
+ // A very efficient way to add new elements to a sparse vector is the append() function.
+ // Note that append() requires that the appended element's index is strictly larger than
+ // the currently largest non-zero index of the vector and that the vector's capacity
+ // is large enough to hold the new element.
+ a.reserve( 10 );
+ a.append( 51, -2.1 );
+
+ // In order to traverse all non-zero elements currently stored in the vector, the begin()
+ // and end() functions can be used. In the example, all non-zero elements of the vector are
+ // traversed.
+ for( CompressedVector<double,false>::Iterator it=a.begin(); it!=a.end(); ++it ) {
+ ... = it->value(); // Access to the value of the non-zero element
+ ... = it->index(); // Access to the index of the non-zero element
+ }
+ \endcode
+
+// The use of CompressedVector is very natural and intuitive. All operations (addition, subtraction,
+// multiplication, scaling, ...) can be performed on all possible combinations of dense and sparse
+// vectors with fitting element types. The following example gives an impression of the use of
+// CompressedVector:
+
+ \code
+ using blaze::CompressedVector;
+ using blaze::DynamicVector;
+ using blaze::CompressedMatrix;
+
+ CompressedVector<double> a( 2 ); // Default constructed, non-initialized 2D vectors
+ a[0] = 1.0; // Initialization of the first element
+ a[1] = 2.0; // Initialization of the second element
+
+ CompressedVector<double> b( 2 ); // Empty sparse vector
+ DynamicVector<float> c( 2, 2.0F ); // Directly, homogeneously initialized dense vector
+ CompressedVector<double> d; // Default constructed dynamic vector
+ CompressedMatrix<double> A; // Default constructed row-major matrix
+
+ d = a + b; // Vector addition between vectors of equal element type
+ d = a - c; // Vector subtraction between a sparse and dense vector with different element types
+ d = a * b; // Component-wise vector multiplication
+
+ a *= 2.0; // In-place scaling of vector
+ d = a * 2.0; // Scaling of vector a
+ d = 2.0 * a; // Scaling of vector a
+
+ d += a - b; // Addition assignment
+ d -= a + c; // Subtraction assignment
+ d *= a * b; // Multiplication assignment
+
+ double scalar = trans( a ) * b; // Scalar/dot/inner product between two vectors
+
+ A = a * trans( b ); // Outer product between two vectors
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool TF = defaultTransposeFlag > // Transpose flag
+class CompressedVector : public SparseVector< CompressedVector<Type,TF>, TF >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef ValueIndexPair<Type> ElementBase; //!< Base class for the compressed vector element.
+ //**********************************************************************************************
+
+ //**Private class Element***********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\brief Value-index-pair for the CompressedVector class.
+ */
+ struct Element : public ElementBase
+ {
+ // This operator is required due to a bug in all versions of the the MSVC compiler.
+ // A simple 'using ElementBase::operator=;' statement results in ambiguity problems.
+ template< typename Other >
+ inline Element& operator=( const Other& rhs )
+ {
+ ElementBase::operator=( rhs );
+ return *this;
+ }
+
+ friend class CompressedVector;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef CompressedVector<Type,TF> This; //!< Type of this CompressedVector instance.
+ typedef SparseVector<This,TF> BaseType; //!< Base type of this CompressedVector instance.
+ typedef This ResultType; //!< Result type for expression template evaluations.
+ typedef CompressedVector<Type,!TF> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef Type ElementType; //!< Type of the compressed vector elements.
+ typedef const Type& ReturnType; //!< Return type for expression template evaluations.
+ typedef const CompressedVector& CompositeType; //!< Data type for composite expression templates.
+ typedef VectorAccessProxy<This> Reference; //!< Reference to a non-constant vector value.
+ typedef const Type& ConstReference; //!< Reference to a constant vector value.
+ typedef Element* Iterator; //!< Iterator over non-constant elements.
+ typedef const Element* ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Rebind struct definition********************************************************************
+ /*!\brief Rebind mechanism to obtain a CompressedVector with different data/element type.
+ */
+ template< typename ET > // Data type of the other vector
+ struct Rebind {
+ typedef CompressedVector<ET,TF> Other; //!< The type of the other CompressedVector.
+ };
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation flag for SMP assignments.
+ /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
+ (shared memory parallel) assignments (both on the left-hand and right-hand side of the
+ assignment). */
+ enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline CompressedVector() noexcept;
+ explicit inline CompressedVector( size_t size ) noexcept;
+ explicit inline CompressedVector( size_t size, size_t nonzeros );
+ inline CompressedVector( const CompressedVector& sv );
+ inline CompressedVector( CompressedVector&& sv ) noexcept;
+ template< typename VT > inline CompressedVector( const DenseVector<VT,TF>& dv );
+ template< typename VT > inline CompressedVector( const SparseVector<VT,TF>& sv );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~CompressedVector();
+ //@}
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) noexcept;
+ inline ConstReference operator[]( size_t index ) const noexcept;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Iterator begin () noexcept;
+ inline ConstIterator begin () const noexcept;
+ inline ConstIterator cbegin() const noexcept;
+ inline Iterator end () noexcept;
+ inline ConstIterator end () const noexcept;
+ inline ConstIterator cend () const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline CompressedVector& operator=( const CompressedVector& rhs );
+ inline CompressedVector& operator=( CompressedVector&& rhs ) noexcept;
+
+ template< typename VT > inline CompressedVector& operator= ( const DenseVector<VT,TF>& rhs );
+ template< typename VT > inline CompressedVector& operator= ( const SparseVector<VT,TF>& rhs );
+ template< typename VT > inline CompressedVector& operator+=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CompressedVector& operator-=( const Vector<VT,TF>& rhs );
+ template< typename VT > inline CompressedVector& operator*=( const DenseVector<VT,TF>& rhs );
+ template< typename VT > inline CompressedVector& operator*=( const SparseVector<VT,TF>& rhs );
+ template< typename VT > inline CompressedVector& operator/=( const DenseVector<VT,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, CompressedVector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, CompressedVector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline void clear();
+ inline Iterator set ( size_t index, const Type& value );
+ inline Iterator insert( size_t index, const Type& value );
+ inline void erase ( size_t index );
+ inline Iterator erase ( Iterator pos );
+ inline Iterator erase ( Iterator first, Iterator last );
+ inline void resize( size_t n, bool preserve=true );
+ void reserve( size_t n );
+ template< typename Other > inline CompressedVector& scale( const Other& scalar );
+ inline void swap( CompressedVector& sv ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index );
+ inline ConstIterator find ( size_t index ) const;
+ inline Iterator lowerBound( size_t index );
+ inline ConstIterator lowerBound( size_t index ) const;
+ inline Iterator upperBound( size_t index );
+ inline ConstIterator upperBound( size_t index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append( size_t index, const Type& value, bool check=false );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,TF>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,TF>& rhs );
+ template< typename VT > inline void addAssign ( const DenseVector <VT,TF>& rhs );
+ template< typename VT > inline void addAssign ( const SparseVector<VT,TF>& rhs );
+ template< typename VT > inline void subAssign ( const DenseVector <VT,TF>& rhs );
+ template< typename VT > inline void subAssign ( const SparseVector<VT,TF>& rhs );
+ template< typename VT > inline void multAssign( const DenseVector <VT,TF>& rhs );
+ template< typename VT > inline void divAssign ( const DenseVector <VT,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ Iterator insert( Iterator pos, size_t index, const Type& value );
+ inline size_t extendCapacity() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ size_t size_; //!< The current size/dimension of the compressed vector.
+ size_t capacity_; //!< The maximum capacity of the compressed vector.
+ Iterator begin_; //!< Pointer to the first non-zero element of the compressed vector.
+ Iterator end_; //!< Pointer one past the last non-zero element of the compressed vector.
+
+ static const Type zero_; //!< Neutral element for accesses to zero elements.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ BLAZE_CONSTRAINT_MUST_HAVE_SAME_SIZE( ElementBase, Element );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
+//
+//=================================================================================================
+
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+const Type CompressedVector<Type,TF>::zero_ = Type();
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for CompressedVector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline CompressedVector<Type,TF>::CompressedVector() noexcept
+ : size_ ( 0UL ) // The current size/dimension of the compressed vector
+ , capacity_( 0UL ) // The maximum capacity of the compressed vector
+ , begin_ ( nullptr ) // Pointer to the first non-zero element of the compressed vector
+ , end_ ( nullptr ) // Pointer to the last non-zero element of the compressed vector
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a compressed vector of size \a n.
+//
+// \param n The size of the vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline CompressedVector<Type,TF>::CompressedVector( size_t n ) noexcept
+ : size_ ( n ) // The current size/dimension of the compressed vector
+ , capacity_( 0UL ) // The maximum capacity of the compressed vector
+ , begin_ ( nullptr ) // Pointer to the first non-zero element of the compressed vector
+ , end_ ( nullptr ) // Pointer to the last non-zero element of the compressed vector
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a compressed vector of size \a n.
+//
+// \param n The size of the vector.
+// \param nonzeros The number of expected non-zero elements.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline CompressedVector<Type,TF>::CompressedVector( size_t n, size_t nonzeros )
+ : size_ ( n ) // The current size/dimension of the compressed vector
+ , capacity_( nonzeros ) // The maximum capacity of the compressed vector
+ , begin_ ( allocate<Element>( capacity_ ) ) // Pointer to the first non-zero element of the compressed vector
+ , end_ ( begin_ ) // Pointer to the last non-zero element of the compressed vector
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for CompressedVector.
+//
+// \param sv Compressed vector to be copied.
+//
+// The copy constructor is explicitly defined due to the required dynamic memory management
+// and in order to enable/facilitate NRV optimization.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline CompressedVector<Type,TF>::CompressedVector( const CompressedVector& sv )
+ : size_ ( sv.size_ ) // The current size/dimension of the compressed vector
+ , capacity_( sv.nonZeros() ) // The maximum capacity of the compressed vector
+ , begin_ ( allocate<Element>( capacity_ ) ) // Pointer to the first non-zero element of the compressed vector
+ , end_ ( begin_+capacity_ ) // Pointer to the last non-zero element of the compressed vector
+{
+ std::copy( sv.begin_, sv.end_, begin_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The move constructor for CompressedVector.
+//
+// \param sv The compressed vector to be moved into this instance.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline CompressedVector<Type,TF>::CompressedVector( CompressedVector&& sv ) noexcept
+ : size_ ( sv.size_ ) // The current size/dimension of the compressed vector
+ , capacity_( sv.capacity_ ) // The maximum capacity of the compressed vector
+ , begin_ ( sv.begin_ ) // Pointer to the first non-zero element of the compressed vector
+ , end_ ( sv.end_ ) // Pointer to the last non-zero element of the compressed vector
+{
+ sv.size_ = 0UL;
+ sv.capacity_ = 0UL;
+ sv.begin_ = nullptr;
+ sv.end_ = nullptr;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from dense vectors.
+//
+// \param dv Dense vector to be copied.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the foreign dense vector
+inline CompressedVector<Type,TF>::CompressedVector( const DenseVector<VT,TF>& dv )
+ : size_ ( (~dv).size() ) // The current size/dimension of the compressed vector
+ , capacity_( 0UL ) // The maximum capacity of the compressed vector
+ , begin_ ( nullptr ) // Pointer to the first non-zero element of the compressed vector
+ , end_ ( nullptr ) // Pointer to the last non-zero element of the compressed vector
+{
+ using blaze::assign;
+ assign( *this, ~dv );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different sparse vectors.
+//
+// \param sv Sparse vector to be copied.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the foreign sparse vector
+inline CompressedVector<Type,TF>::CompressedVector( const SparseVector<VT,TF>& sv )
+ : size_ ( (~sv).size() ) // The current size/dimension of the compressed vector
+ , capacity_( (~sv).nonZeros() ) // The maximum capacity of the compressed vector
+ , begin_ ( allocate<Element>( capacity_ ) ) // Pointer to the first non-zero element of the compressed vector
+ , end_ ( begin_ ) // Pointer to the last non-zero element of the compressed vector
+{
+ using blaze::assign;
+ assign( *this, ~sv );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The destructor for CompressedVector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline CompressedVector<Type,TF>::~CompressedVector()
+{
+ deallocate( begin_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the compressed vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function returns a reference to the accessed value at position \a index. In case the
+// compressed vector does not yet store an element for index \a index, a new element is inserted
+// into the compressed vector. An alternative for traversing the non-zero elements of the sparse
+// vector are the begin() and end() functions.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Reference
+ CompressedVector<Type,TF>::operator[]( size_t index ) noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid compressed vector access index" );
+
+ return Reference( *this, index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the compressed vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstReference
+ CompressedVector<Type,TF>::operator[]( size_t index ) const noexcept
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid compressed vector access index" );
+
+ const ConstIterator pos( lowerBound( index ) );
+
+ if( pos == end_ || pos->index_ != index )
+ return zero_;
+ else
+ return pos->value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the compressed vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid compressed vector access index.
+//
+// This function returns a reference to the accessed value at position \a index. In case the
+// compressed vector does not yet store an element for index \a index, a new element is inserted
+// into the compressed vector. In contrast to the subscript operator this function always
+// performs a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Reference
+ CompressedVector<Type,TF>::at( size_t index )
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid compressed vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the compressed vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid compressed vector access index.
+//
+// This function returns a reference to the accessed value at position \a index. In case the
+// compressed vector does not yet store an element for index \a index, a new element is inserted
+// into the compressed vector. In contrast to the subscript operator this function always
+// performs a check of the given access index.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstReference
+ CompressedVector<Type,TF>::at( size_t index ) const
+{
+ if( index >= size_ ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid compressed vector access index" );
+ }
+ return (*this)[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first non-zero element of the compressed vector.
+//
+// \return Iterator to the first non-zero element of the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Iterator CompressedVector<Type,TF>::begin() noexcept
+{
+ return Iterator( begin_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first non-zero element of the compressed vector.
+//
+// \return Iterator to the first non-zero element of the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstIterator
+ CompressedVector<Type,TF>::begin() const noexcept
+{
+ return ConstIterator( begin_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first non-zero element of the compressed vector.
+//
+// \return Iterator to the first non-zero element of the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstIterator
+ CompressedVector<Type,TF>::cbegin() const noexcept
+{
+ return ConstIterator( begin_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last non-zero element of the compressed vector.
+//
+// \return Iterator just past the last non-zero element of the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Iterator CompressedVector<Type,TF>::end() noexcept
+{
+ return Iterator( end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last non-zero element of the compressed vector.
+//
+// \return Iterator just past the last non-zero element of the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstIterator
+ CompressedVector<Type,TF>::end() const noexcept
+{
+ return ConstIterator( end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last non-zero element of the compressed vector.
+//
+// \return Iterator just past the last non-zero element of the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstIterator
+ CompressedVector<Type,TF>::cend() const noexcept
+{
+ return ConstIterator( end_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for CompressedVector.
+//
+// \param rhs Compressed vector to be copied.
+// \return Reference to the assigned compressed vector.
+//
+// The compressed vector is resized according to the given compressed vector and initialized
+// as a copy of this vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline CompressedVector<Type,TF>&
+ CompressedVector<Type,TF>::operator=( const CompressedVector& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ const size_t nonzeros( rhs.nonZeros() );
+
+ if( nonzeros > capacity_ ) {
+ Iterator newBegin( allocate<Element>( nonzeros ) );
+ end_ = std::copy( rhs.begin_, rhs.end_, newBegin );
+ std::swap( begin_, newBegin );
+ deallocate( newBegin );
+
+ size_ = rhs.size_;
+ capacity_ = nonzeros;
+ }
+ else {
+ end_ = std::copy( rhs.begin_, rhs.end_, begin_ );
+ size_ = rhs.size_;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Move assignment operator for CompressedVector.
+//
+// \param rhs The compressed vector to be moved into this instance.
+// \return Reference to the assigned compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline CompressedVector<Type,TF>&
+ CompressedVector<Type,TF>::operator=( CompressedVector&& rhs ) noexcept
+{
+ deallocate( begin_ );
+
+ size_ = rhs.size_;
+ capacity_ = rhs.capacity_;
+ begin_ = rhs.begin_;
+ end_ = rhs.end_;
+
+ rhs.size_ = 0UL;
+ rhs.capacity_ = 0UL;
+ rhs.begin_ = nullptr;
+ rhs.end_ = nullptr;
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for dense vectors.
+//
+// \param rhs Dense vector to be copied.
+// \return Reference to the assigned compressed vector.
+//
+// The vector is resized according to the given dense vector and initialized as a copy of
+// this vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline CompressedVector<Type,TF>&
+ CompressedVector<Type,TF>::operator=( const DenseVector<VT,TF>& rhs )
+{
+ using blaze::assign;
+
+ if( (~rhs).canAlias( this ) ) {
+ CompressedVector tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ size_ = (~rhs).size();
+ end_ = begin_;
+ assign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different sparse vectors.
+//
+// \param rhs Sparse vector to be copied.
+// \return Reference to the assigned compressed vector.
+//
+// The vector is resized according to the given sparse vector and initialized as a copy of
+// this vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline CompressedVector<Type,TF>&
+ CompressedVector<Type,TF>::operator=( const SparseVector<VT,TF>& rhs )
+{
+ using blaze::assign;
+
+ if( (~rhs).canAlias( this ) || (~rhs).nonZeros() > capacity_ ) {
+ CompressedVector tmp( ~rhs );
+ swap( tmp );
+ }
+ else {
+ size_ = (~rhs).size();
+ end_ = begin_;
+ assign( *this, ~rhs );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the compressed vector.
+// \return Reference to the compressed vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CompressedVector<Type,TF>& CompressedVector<Type,TF>::operator+=( const Vector<VT,TF>& rhs )
+{
+ using blaze::addAssign;
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ addAssign( *this, ~rhs );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the compressed vector.
+// \return Reference to the compressed vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CompressedVector<Type,TF>& CompressedVector<Type,TF>::operator-=( const Vector<VT,TF>& rhs )
+{
+ using blaze::subAssign;
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ subAssign( *this, ~rhs );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the compressed vector.
+// \return Reference to the compressed vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CompressedVector<Type,TF>&
+ CompressedVector<Type,TF>::operator*=( const DenseVector<VT,TF>& rhs )
+{
+ using blaze::multAssign;
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ CompressedVector tmp( *this * (~rhs) );
+ swap( tmp );
+ }
+ else {
+ CompositeType_<VT> tmp( ~rhs );
+ multAssign( *this, tmp );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the compressed vector.
+// \return Reference to the compressed vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CompressedVector<Type,TF>&
+ CompressedVector<Type,TF>::operator*=( const SparseVector<VT,TF>& rhs )
+{
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ CompressedVector tmp( *this * (~rhs) );
+ swap( tmp );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the compressed vector.
+// \exception std::invalid_argument Vector sizes do not match.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side vector
+inline CompressedVector<Type,TF>& CompressedVector<Type,TF>::operator/=( const DenseVector<VT,TF>& rhs )
+{
+ using blaze::divAssign;
+
+ if( (~rhs).size() != size_ ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( (~rhs).canAlias( this ) ) {
+ CompressedVector tmp( *this / (~rhs) );
+ swap( tmp );
+ }
+ else {
+ CompositeType_<VT> tmp( ~rhs );
+ divAssign( *this, tmp );
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment operator for the multiplication between a compressed vector
+// and a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the compressed vector.
+//
+// This operator can only be used for built-in data types. Additionally, the elements of the
+// compressed vector must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, CompressedVector<Type,TF> >&
+ CompressedVector<Type,TF>::operator*=( Other rhs )
+{
+ for( Iterator element=begin_; element!=end_; ++element )
+ element->value_ *= rhs;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment operator for the division of a compressed vector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the compressed vector.
+//
+// This operator can only be used for built-in data types. Additionally, the elements of the
+// compressed vector must either support the multiplication assignment operator for the given
+// floating point data type or the division assignment operator for the given integral data
+// type.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, CompressedVector<Type,TF> >&
+ CompressedVector<Type,TF>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<Type,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( Iterator element=begin_; element!=end_; ++element )
+ element->value_ *= tmp;
+ }
+ else {
+ for( Iterator element=begin_; element!=end_; ++element )
+ element->value_ /= rhs;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the compressed vector.
+//
+// \return The size of the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline size_t CompressedVector<Type,TF>::size() const noexcept
+{
+ return size_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the compressed vector.
+//
+// \return The capacity of the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline size_t CompressedVector<Type,TF>::capacity() const noexcept
+{
+ return capacity_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of non-zero elements in the compressed vector.
+//
+// \return The number of non-zero elements in the compressed vector.
+//
+// Note that the number of non-zero elements is always smaller than the current size of the
+// compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline size_t CompressedVector<Type,TF>::nonZeros() const
+{
+ return end_ - begin_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void CompressedVector<Type,TF>::reset()
+{
+ end_ = begin_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the compressed vector.
+//
+// \return void
+//
+// After the clear() function, the size of the compressed vector is 0.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void CompressedVector<Type,TF>::clear()
+{
+ size_ = 0UL;
+ end_ = begin_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting an element of the compressed vector.
+//
+// \param index The index of the element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+//
+// This function sets the value of an element of the compressed vector. In case the sparse vector
+// already contains an element with index \a index its value is modified, else a new element with
+// the given \a value is inserted.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Iterator
+ CompressedVector<Type,TF>::set( size_t index, const Type& value )
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid compressed vector access index" );
+
+ const Iterator pos( lowerBound( index ) );
+
+ if( pos != end_ && pos->index_ == index ) {
+ pos->value() = value;
+ return pos;
+ }
+ else return insert( pos, index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting an element into the compressed vector.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid compressed vector access index.
+//
+// This function inserts a new element into the compressed vector. However, duplicate elements
+// are not allowed. In case the sparse vector already contains an element with index \a index,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+typename CompressedVector<Type,TF>::Iterator
+ CompressedVector<Type,TF>::insert( size_t index, const Type& value )
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid compressed vector access index" );
+
+ const Iterator pos( lowerBound( index ) );
+
+ if( pos != end_ && pos->index_ == index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Bad access index" );
+ }
+
+ return insert( pos, index, value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting an element into the compressed vector.
+//
+// \param pos The position of the new element.
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid compressed vector access index.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+typename CompressedVector<Type,TF>::Iterator
+ CompressedVector<Type,TF>::insert( Iterator pos, size_t index, const Type& value )
+{
+ if( nonZeros() != capacity_ ) {
+ std::move_backward( pos, end_, end_+1 );
+ pos->value_ = value;
+ pos->index_ = index;
+ ++end_;
+
+ return pos;
+ }
+ else {
+ size_t newCapacity( extendCapacity() );
+
+ Iterator newBegin = allocate<Element>( newCapacity );
+ Iterator tmp = std::move( begin_, pos, newBegin );
+ tmp->value_ = value;
+ tmp->index_ = index;
+ end_ = std::move( pos, end_, tmp+1 );
+
+ std::swap( newBegin, begin_ );
+ deallocate( newBegin );
+ capacity_ = newCapacity;
+
+ return tmp;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing an element from the compressed vector.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void CompressedVector<Type,TF>::erase( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid compressed vector access index" );
+
+ const Iterator pos( find( index ) );
+ if( pos != end_ )
+ end_ = std::move( pos+1, end_, pos );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing an element from the compressed vector.
+//
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Iterator CompressedVector<Type,TF>::erase( Iterator pos )
+{
+ BLAZE_USER_ASSERT( pos >= begin_ && pos <= end_, "Invalid compressed vector iterator" );
+
+ if( pos != end_ )
+ end_ = std::move( pos+1, end_, pos );
+ return pos;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Erasing a range of elements from the compressed vector.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Iterator
+ CompressedVector<Type,TF>::erase( Iterator first, Iterator last )
+{
+ BLAZE_USER_ASSERT( first <= last, "Invalid iterator range" );
+ BLAZE_USER_ASSERT( first >= begin_ && first <= end_, "Invalid compressed vector iterator" );
+ BLAZE_USER_ASSERT( last >= begin_ && last <= end_, "Invalid compressed vector iterator" );
+
+ if( first != last )
+ end_ = std::move( last, end_, first );
+ return first;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Changing the size of the compressed vector.
+//
+// \param n The new size of the compressed vector.
+// \param preserve \a true if the old values of the vector should be preserved, \a false if not.
+// \return void
+//
+// This function resizes the compressed vector using the given size to \a n. During this
+// operation, new dynamic memory may be allocated in case the capacity of the compressed
+// vector is too small. Note that this function may invalidate all existing views (subvectors,
+// ...) on the vector if it is used to shrink the vector. Additionally, the resize operation
+// potentially changes all vector elements. In order to preserve the old vector values, the
+// \a preserve flag can be set to \a true.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void CompressedVector<Type,TF>::resize( size_t n, bool preserve )
+{
+ if( preserve ) {
+ end_ = lowerBound( n );
+ }
+ else {
+ end_ = begin_;
+ }
+
+ size_ = n;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the compressed vector.
+//
+// \param n The new minimum capacity of the compressed vector.
+// \return void
+//
+// This function increases the capacity of the compressed vector to at least \a n elements. The
+// current values of the vector elements are preserved.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+void CompressedVector<Type,TF>::reserve( size_t n )
+{
+ if( n > capacity_ ) {
+ const size_t newCapacity( n );
+
+ // Allocating a new data and index array
+ Iterator newBegin = allocate<Element>( newCapacity );
+
+ // Replacing the old data and index array
+ end_ = transfer( begin_, end_, newBegin );
+ std::swap( newBegin, begin_ );
+ capacity_ = newCapacity;
+ deallocate( newBegin );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Scaling of the compressed vector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the vector scaling.
+// \return Reference to the compressed vector.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline CompressedVector<Type,TF>& CompressedVector<Type,TF>::scale( const Other& scalar )
+{
+ for( Iterator element=begin_; element!=end_; ++element )
+ element->value_ *= scalar;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two compressed vectors.
+//
+// \param sv The compressed vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void CompressedVector<Type,TF>::swap( CompressedVector& sv ) noexcept
+{
+ std::swap( size_, sv.size_ );
+ std::swap( capacity_, sv.capacity_ );
+ std::swap( begin_, sv.begin_ );
+ std::swap( end_, sv.end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Calculating a new vector capacity.
+//
+// \return The new compressed vector capacity.
+//
+// This function calculates a new vector capacity based on the current capacity of the sparse
+// vector. Note that the new capacity is restricted to the interval \f$[7..size]\f$.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline size_t CompressedVector<Type,TF>::extendCapacity() const noexcept
+{
+ using blaze::max;
+ using blaze::min;
+
+ size_t nonzeros( 2UL*capacity_+1UL );
+ nonzeros = max( nonzeros, 7UL );
+ nonzeros = min( nonzeros, size_ );
+
+ BLAZE_INTERNAL_ASSERT( nonzeros > capacity_, "Invalid capacity value" );
+
+ return nonzeros;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Searches for a specific vector element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// vector. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the compressed vector (the end() iterator) is returned. Note
+// that the returned compressed vector iterator is subject to invalidation due to inserting
+// operations via the subscript operator or the insert() function!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Iterator CompressedVector<Type,TF>::find( size_t index )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).find( index ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Searches for a specific vector element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// vector. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the compressed vector (the end() iterator) is returned. Note
+// that the returned compressed vector iterator is subject to invalidation due to inserting
+// operations via the subscript operator or the insert() function!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstIterator CompressedVector<Type,TF>::find( size_t index ) const
+{
+ const ConstIterator pos( lowerBound( index ) );
+ if( pos != end_ && pos->index_ == index )
+ return pos;
+ else return end_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed vector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Iterator
+ CompressedVector<Type,TF>::lowerBound( size_t index )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).lowerBound( index ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed vector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstIterator
+ CompressedVector<Type,TF>::lowerBound( size_t index ) const
+{
+ return std::lower_bound( begin_, end_, index,
+ []( const Element& element, size_t i )
+ {
+ return element.index() < i;
+ } );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the lowerBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed vector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::Iterator
+ CompressedVector<Type,TF>::upperBound( size_t index )
+{
+ return const_cast<Iterator>( const_cast<const This&>( *this ).upperBound( index ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the lowerBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned compressed vector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline typename CompressedVector<Type,TF>::ConstIterator
+ CompressedVector<Type,TF>::upperBound( size_t index ) const
+{
+ return std::upper_bound( begin_, end_, index,
+ []( size_t i, const Element& element )
+ {
+ return i < element.index();
+ } );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Appending an element to the compressed vector.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a compressed vector with elements. It
+// appends a new element to the end of the compressed vector without any memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the compressed vector
+// - the current number of non-zero elements must be smaller than the capacity of the vector
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void CompressedVector<Type,TF>::append( size_t index, const Type& value, bool check )
+{
+ BLAZE_USER_ASSERT( index < size_, "Invalid compressed vector access index" );
+ BLAZE_USER_ASSERT( nonZeros() < capacity(), "Not enough reserved capacity" );
+ BLAZE_USER_ASSERT( begin_ == end_ || (end_-1UL)->index_ < index, "Index is not strictly increasing" );
+
+ end_->value_ = value;
+
+ if( !check || !isDefault( end_->value_ ) ) {
+ end_->index_ = index;
+ ++end_;
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address can alias with the vector. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool CompressedVector<Type,TF>::canAlias( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this vector, \a false if not.
+//
+// This function returns whether the given address is aliased with the vector. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool CompressedVector<Type,TF>::isAliased( const Other* alias ) const noexcept
+{
+ return static_cast<const void*>( this ) == static_cast<const void*>( alias );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector can be used in SMP assignments.
+//
+// \return \a true in case the vector can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the vector can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current size of the
+// vector).
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline bool CompressedVector<Type,TF>::canSMPAssign() const noexcept
+{
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void CompressedVector<Type,TF>::assign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<size_; ++i )
+ {
+ if( nonzeros == capacity_ )
+ reserve( extendCapacity() );
+
+ end_->value_ = (~rhs)[i];
+
+ if( !isDefault( end_->value_ ) ) {
+ end_->index_ = i;
+ ++end_;
+ ++nonzeros;
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CompressedVector<Type,TF>::assign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ // Using the following formulation instead of a std::copy function call of the form
+ //
+ // end_ = std::copy( (~rhs).begin(), (~rhs).end(), begin_ );
+ //
+ // results in much less requirements on the ConstIterator type provided from the right-hand
+ // sparse vector type
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ append( element->index(), element->value() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void CompressedVector<Type,TF>::addAssign( const DenseVector<VT,TF>& rhs )
+{
+ typedef AddTrait_< This, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( AddType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<AddType> );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CompressedVector<Type,TF>::addAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ CompressedVector tmp( serial( *this + (~rhs) ) );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void CompressedVector<Type,TF>::subAssign( const DenseVector<VT,TF>& rhs )
+{
+ typedef SubTrait_< This, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( SubType, TF );
+ BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<SubType> );
+
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void CompressedVector<Type,TF>::subAssign( const SparseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ CompressedVector tmp( serial( *this - (~rhs) ) );
+ swap( tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void CompressedVector<Type,TF>::multAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ for( Iterator element=begin_; element!=end_; ++element ) {
+ element->value_ *= (~rhs)[element->index_];
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void CompressedVector<Type,TF>::divAssign( const DenseVector<VT,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" );
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( VT );
+
+ for( Iterator element=begin_; element!=end_; ++element ) {
+ element->value_ /= (~rhs)[element->index_];
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPRESSEDVECTOR OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name CompressedVector operators */
+//@{
+template< typename Type, bool TF >
+inline void reset( CompressedVector<Type,TF>& v );
+
+template< typename Type, bool TF >
+inline void clear( CompressedVector<Type,TF>& v );
+
+template< typename Type, bool TF >
+inline bool isDefault( const CompressedVector<Type,TF>& v );
+
+template< typename Type, bool TF >
+inline bool isIntact( const CompressedVector<Type,TF>& v ) noexcept;
+
+template< typename Type, bool TF >
+inline void swap( CompressedVector<Type,TF>& a, CompressedVector<Type,TF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given compressed vector.
+// \ingroup compressed_vector
+//
+// \param v The compressed vector to be resetted.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void reset( CompressedVector<Type,TF>& v )
+{
+ v.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given compressed vector.
+// \ingroup compressed_vector
+//
+// \param v The compressed vector to be cleared.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void clear( CompressedVector<Type,TF>& v )
+{
+ v.clear();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given compressed vector is in default state.
+// \ingroup compressed_vector
+//
+// \param v The compressed vector to be tested for its default state.
+// \return \a true in case the given vector's size is zero, \a false otherwise.
+//
+// This function checks whether the compressed vector is in default (constructed) state, i.e. if
+// it's size is 0. In case it is in default state, the function returns \a true, else it will
+// return \a false. The following example demonstrates the use of the \a isDefault() function:
+
+ \code
+ blaze::CompressedVector<double> a;
+ // ... Resizing and initialization
+ if( isDefault( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline bool isDefault( const CompressedVector<Type,TF>& v )
+{
+ return ( v.size() == 0UL );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given compressed vector are intact.
+// \ingroup compressed_vector
+//
+// \param v The compressed vector to be tested.
+// \return \a true in case the given vector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the compressed vector are intact, i.e. if
+// its state is valid. In case the invariants are intact, the function returns \a true, else
+// it will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::CompressedVector<double> a;
+ // ... Resizing and initialization
+ if( isIntact( a ) ) { ... }
+ \endcode
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline bool isIntact( const CompressedVector<Type,TF>& v ) noexcept
+{
+ return ( v.nonZeros() <= v.capacity() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two compressed vectors.
+// \ingroup compressed_vector
+//
+// \param a The first compressed vector to be swapped.
+// \param b The second compressed vector to be swapped.
+// \return void
+*/
+template< typename Type // Data type of the vector
+ , bool TF > // Transpose flag
+inline void swap( CompressedVector<Type,TF>& a, CompressedVector<Type,TF>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESIZABLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T, bool TF >
+struct IsResizable< CompressedVector<T,TF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2, size_t N >
+struct AddTrait< CompressedVector<T1,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct AddTrait< StaticVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ using Type = StaticVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct AddTrait< CompressedVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct AddTrait< HybridVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ using Type = HybridVector< AddTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct AddTrait< CompressedVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< AddTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct AddTrait< DynamicVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using Type = DynamicVector< AddTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct AddTrait< CompressedVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = DynamicVector< AddTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct AddTrait< CustomVector<T1,AF,PF,TF>, CompressedVector<T2,TF> >
+{
+ using Type = DynamicVector< AddTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct AddTrait< CompressedVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< AddTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2, size_t N >
+struct SubTrait< CompressedVector<T1,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct SubTrait< StaticVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ using Type = StaticVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct SubTrait< CompressedVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = HybridVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct SubTrait< HybridVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ using Type = HybridVector< SubTrait_<T1,T2>, N, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct SubTrait< CompressedVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using Type = DynamicVector< SubTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct SubTrait< DynamicVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using Type = DynamicVector< SubTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct SubTrait< CompressedVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = DynamicVector< SubTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct SubTrait< CustomVector<T1,AF,PF,TF>, CompressedVector<T2,TF> >
+{
+ using Type = DynamicVector< SubTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct SubTrait< CompressedVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< SubTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2 >
+struct MultTrait< CompressedVector<T1,TF>, T2, EnableIf_< IsNumeric<T2> > >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2, bool TF >
+struct MultTrait< T1, CompressedVector<T2,TF>, EnableIf_< IsNumeric<T1> > >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct MultTrait< CompressedVector<T1,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2, size_t N >
+struct MultTrait< CompressedVector<T1,false>, StaticVector<T2,N,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, typename T2, size_t N >
+struct MultTrait< CompressedVector<T1,true>, StaticVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MultTrait< StaticVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< StaticVector<T1,N,false>, CompressedVector<T2,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< StaticVector<T1,N,true>, CompressedVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct MultTrait< CompressedVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2, size_t N >
+struct MultTrait< CompressedVector<T1,false>, HybridVector<T2,N,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, typename T2, size_t N >
+struct MultTrait< CompressedVector<T1,true>, HybridVector<T2,N,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct MultTrait< HybridVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< HybridVector<T1,N,false>, CompressedVector<T2,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, size_t N, typename T2 >
+struct MultTrait< HybridVector<T1,N,true>, CompressedVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct MultTrait< CompressedVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2 >
+struct MultTrait< CompressedVector<T1,false>, DynamicVector<T2,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, typename T2 >
+struct MultTrait< CompressedVector<T1,true>, DynamicVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct MultTrait< DynamicVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2 >
+struct MultTrait< DynamicVector<T1,false>, CompressedVector<T2,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2 >
+struct MultTrait< DynamicVector<T1,true>, CompressedVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct MultTrait< CompressedVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2, bool AF, bool PF >
+struct MultTrait< CompressedVector<T1,false>, CustomVector<T2,AF,PF,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, true >;
+};
+
+template< typename T1, typename T2, bool AF, bool PF >
+struct MultTrait< CompressedVector<T1,true>, CustomVector<T2,AF,PF,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct MultTrait< CustomVector<T1,AF,PF,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2 >
+struct MultTrait< CustomVector<T1,AF,PF,false>, CompressedVector<T2,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, bool AF, bool PF, typename T2 >
+struct MultTrait< CustomVector<T1,AF,PF,true>, CompressedVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct MultTrait< CompressedVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< MultTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, typename T2 >
+struct MultTrait< CompressedVector<T1,false>, CompressedVector<T2,true> >
+{
+ using Type = CompressedMatrix< MultTrait_<T1,T2>, false >;
+};
+
+template< typename T1, typename T2 >
+struct MultTrait< CompressedVector<T1,true>, CompressedVector<T2,false> >
+{
+ using Type = MultTrait_<T1,T2>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CROSSTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2 >
+struct CrossTrait< CompressedVector<T1,TF>, StaticVector<T2,3UL,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct CrossTrait< StaticVector<T1,3UL,TF>, CompressedVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct CrossTrait< CompressedVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct CrossTrait< HybridVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct CrossTrait< CompressedVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct CrossTrait< DynamicVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct CrossTrait< CompressedVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ private:
+ using T = MultTrait_<T1,T2>;
+
+ public:
+ using Type = StaticVector< SubTrait_<T,T>, 3UL, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2 >
+struct DivTrait< CompressedVector<T1,TF>, T2, EnableIf_< IsNumeric<T2> > >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct DivTrait< CompressedVector<T1,TF>, StaticVector<T2,N,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct DivTrait< StaticVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, size_t N >
+struct DivTrait< CompressedVector<T1,TF>, HybridVector<T2,N,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, size_t N, bool TF, typename T2 >
+struct DivTrait< HybridVector<T1,N,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct DivTrait< CompressedVector<T1,TF>, DynamicVector<T2,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct DivTrait< DynamicVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2, bool AF, bool PF >
+struct DivTrait< CompressedVector<T1,TF>, CustomVector<T2,AF,PF,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool AF, bool PF, bool TF, typename T2 >
+struct DivTrait< CustomVector<T1,AF,PF,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+
+template< typename T1, bool TF, typename T2 >
+struct DivTrait< CompressedVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using Type = CompressedVector< DivTrait_<T1,T2>, TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF, typename T2 >
+struct MathTrait< CompressedVector<T1,TF>, CompressedVector<T2,TF> >
+{
+ using HighType = CompressedVector< typename MathTrait<T1,T2>::HighType, TF >;
+ using LowType = CompressedVector< typename MathTrait<T1,T2>::LowType , TF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, bool TF >
+struct SubvectorTrait< CompressedVector<T1,TF> >
+{
+ using Type = CompressedVector<T1,TF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/Forward.h b/src/cpu/blaze/math/sparse/Forward.h
new file mode 100644
index 00000000..5a752496
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/Forward.h
@@ -0,0 +1,52 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/Forward.h
+// \brief Header file for all forward declarations for sparse vectors and matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_FORWARD_H_
+#define _BLAZE_MATH_SPARSE_FORWARD_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+template< typename, bool > class CompressedMatrix;
+template< typename, bool > class CompressedVector;
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/MatrixAccessProxy.h b/src/cpu/blaze/math/sparse/MatrixAccessProxy.h
new file mode 100644
index 00000000..d966482d
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/MatrixAccessProxy.h
@@ -0,0 +1,694 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/MatrixAccessProxy.h
+// \brief Header file for the MatrixAccessProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_MATRIXACCESSPROXY_H_
+#define _BLAZE_MATH_SPARSE_MATRIXACCESSPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for sparse, \f$ M \times N \f$ matrices.
+// \ingroup sparse_matrix
+//
+// The MatrixAccessProxy provides safe access to the elements of a non-const sparse matrices.\n
+// The proxied access to the elements of a sparse matrix is necessary since it may be possible
+// that several insertion operations happen in the same statement. The following code illustrates
+// this with two examples by means of the CompressedMatrix class:
+
+ \code
+ blaze::CompressedMatrix<double> A( 4, 4 );
+
+ // Standard usage of the function call operator to initialize a matrix element.
+ // Only a single sparse matrix element is accessed!
+ A(0,1) = 1.0;
+
+ // Initialization of a matrix element via another matrix element.
+ // Two sparse matrix accesses in one statement!
+ A(1,2) = A(0,1);
+
+ // Multiple accesses to elements of the sparse matrix in one statement!
+ const double result = A(0,2) + A(1,2) + A(2,2);
+ \endcode
+
+// The problem (especially with the last statement) is that several insertion operations might
+// take place due to the access via the function call operator. If the function call operator
+// would return a direct reference to one of the accessed elements, this reference might be
+// invalidated during the evaluation of a subsequent function call operator, which results in
+// undefined behavior. This class provides the necessary functionality to guarantee a safe access
+// to the sparse matrix elements while preserving the intuitive use of the function call operator.
+*/
+template< typename MT > // Type of the sparse matrix
+class MatrixAccessProxy : public Proxy< MatrixAccessProxy<MT>, ElementType_<MT> >
+{
+ private:
+ //**Enumerations********************************************************************************
+ //! Compile time flag indicating whether the given matrix type is a row-major matrix.
+ enum : bool { rmm = IsRowMajorMatrix<MT>::value };
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<MT> RepresentedType; //!< Type of the represented sparse matrix element.
+ typedef RepresentedType& RawReference; //!< Raw reference to the represented element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline MatrixAccessProxy( MT& sm, size_t i, size_t j );
+ inline MatrixAccessProxy( const MatrixAccessProxy& map );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~MatrixAccessProxy();
+ //@}
+ //**********************************************************************************************
+
+ //**Operators***********************************************************************************
+ /*!\name Operators */
+ //@{
+ inline const MatrixAccessProxy& operator=( const MatrixAccessProxy& map ) const;
+
+ template< typename T >
+ inline const MatrixAccessProxy& operator=( initializer_list<T> list ) const;
+
+ template< typename T >
+ inline const MatrixAccessProxy& operator=( initializer_list< initializer_list<T> > list ) const;
+
+ template< typename T > inline const MatrixAccessProxy& operator= ( const T& value ) const;
+ template< typename T > inline const MatrixAccessProxy& operator+=( const T& value ) const;
+ template< typename T > inline const MatrixAccessProxy& operator-=( const T& value ) const;
+ template< typename T > inline const MatrixAccessProxy& operator*=( const T& value ) const;
+ template< typename T > inline const MatrixAccessProxy& operator/=( const T& value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline RawReference get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RawReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ MT& sm_; //!< Reference to the accessed sparse matrix.
+ size_t i_; //!< Row-index of the accessed sparse matrix element.
+ size_t j_; //!< Column-index of the accessed sparse matrix element.
+ //@}
+ //**********************************************************************************************
+
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a MatrixAccessProxy.
+//
+// \param sm Reference to the accessed sparse matrix.
+// \param i The row-index of the accessed sparse matrix element.
+// \param j The column-index of the accessed sparse matrix element.
+*/
+template< typename MT > // Type of the sparse matrix
+inline MatrixAccessProxy<MT>::MatrixAccessProxy( MT& sm, size_t i, size_t j )
+ : sm_( sm ) // Reference to the accessed sparse matrix
+ , i_ ( i ) // Row-index of the accessed sparse matrix element
+ , j_ ( j ) // Column-index of the accessed sparse matrix element
+{
+ const Iterator_<MT> element( sm_.find( i_, j_ ) );
+ const size_t index( rmm ? i_ : j_ );
+ if( element == sm_.end(index) )
+ sm_.insert( i_, j_, RepresentedType() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for MatrixAccessProxy.
+//
+// \param map Sparse matrix access proxy to be copied.
+*/
+template< typename MT > // Type of the sparse matrix
+inline MatrixAccessProxy<MT>::MatrixAccessProxy( const MatrixAccessProxy& map )
+ : sm_( map.sm_ ) // Reference to the accessed sparse matrix
+ , i_ ( map.i_ ) // Row-index of the accessed sparse matrix element
+ , j_ ( map.j_ ) // Column-index of the accessed sparse matrix element
+{
+ BLAZE_INTERNAL_ASSERT( sm_.find(i_,j_) != sm_.end( rmm ? i_ : j_ ), "Missing matrix element detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The destructor for MatrixAccessProxy.
+*/
+template< typename MT > // Type of the sparse matrix
+inline MatrixAccessProxy<MT>::~MatrixAccessProxy()
+{
+ const Iterator_<MT> element( sm_.find( i_, j_ ) );
+ const size_t index( rmm ? i_ : j_ );
+ if( element != sm_.end( index ) && isDefault( element->value() ) )
+ sm_.erase( index, element );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for MatrixAccessProxy.
+//
+// \param map Sparse matrix access proxy to be copied.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the sparse matrix
+inline const MatrixAccessProxy<MT>& MatrixAccessProxy<MT>::operator=( const MatrixAccessProxy& map ) const
+{
+ get() = map.get();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed sparse matrix element.
+//
+// \param list The list to be assigned to the sparse matrix element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse matrix
+template< typename T > // Type of the right-hand side elements
+inline const MatrixAccessProxy<VT>&
+ MatrixAccessProxy<VT>::operator=( initializer_list<T> list ) const
+{
+ get() = list;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed sparse matrix element.
+//
+// \param list The list to be assigned to the sparse matrix element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse matrix
+template< typename T > // Type of the right-hand side elements
+inline const MatrixAccessProxy<VT>&
+ MatrixAccessProxy<VT>::operator=( initializer_list< initializer_list<T> > list ) const
+{
+ get() = list;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed sparse matrix element.
+//
+// \param value The new value of the sparse matrix element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename T > // Type of the right-hand side value
+inline const MatrixAccessProxy<MT>& MatrixAccessProxy<MT>::operator=( const T& value ) const
+{
+ get() = value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed sparse matrix element.
+//
+// \param value The right-hand side value to be added to the sparse matrix element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename T > // Type of the right-hand side value
+inline const MatrixAccessProxy<MT>& MatrixAccessProxy<MT>::operator+=( const T& value ) const
+{
+ get() += value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed sparse matrix element.
+//
+// \param value The right-hand side value to be subtracted from the sparse matrix element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename T > // Type of the right-hand side value
+inline const MatrixAccessProxy<MT>& MatrixAccessProxy<MT>::operator-=( const T& value ) const
+{
+ get() -= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed sparse matrix element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename T > // Type of the right-hand side value
+inline const MatrixAccessProxy<MT>& MatrixAccessProxy<MT>::operator*=( const T& value ) const
+{
+ get() *= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed sparse matrix element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned access proxy.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename T > // Type of the right-hand side value
+inline const MatrixAccessProxy<MT>& MatrixAccessProxy<MT>::operator/=( const T& value ) const
+{
+ get() /= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed sparse matrix element.
+//
+// \return Direct/raw reference to the accessed sparse matrix element.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename MatrixAccessProxy<MT>::RawReference MatrixAccessProxy<MT>::get() const noexcept
+{
+ const Iterator_<MT> element( sm_.find( i_, j_ ) );
+ BLAZE_INTERNAL_ASSERT( element != sm_.end( rmm ? i_ : j_ ), "Missing matrix element detected" );
+ return element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted sparse matrix element..
+//
+// \return \a true in case access to the sparse matrix element is restricted, \a false if not.
+*/
+template< typename MT > // Type of the sparse matrix
+inline bool MatrixAccessProxy<MT>::isRestricted() const noexcept
+{
+ return false;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed sparse matrix element.
+//
+// \return Direct/raw reference to the accessed sparse matrix element.
+*/
+template< typename MT > // Type of the sparse matrix
+inline MatrixAccessProxy<MT>::operator RawReference() const noexcept
+{
+ return get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name MatrixAccessProxy global functions */
+//@{
+template< typename MT >
+inline void reset( const MatrixAccessProxy<MT>& proxy );
+
+template< typename MT >
+inline void clear( const MatrixAccessProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isDefault( const MatrixAccessProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isReal( const MatrixAccessProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isZero( const MatrixAccessProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isOne( const MatrixAccessProxy<MT>& proxy );
+
+template< typename MT >
+inline bool isnan( const MatrixAccessProxy<MT>& proxy );
+
+template< typename MT >
+inline void swap( const MatrixAccessProxy<MT>& a, const MatrixAccessProxy<MT>& b ) noexcept;
+
+template< typename MT, typename T >
+inline void swap( const MatrixAccessProxy<MT>& a, T& b ) noexcept;
+
+template< typename T, typename MT >
+inline void swap( T& a, const MatrixAccessProxy<MT>& v ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup sparse_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function resets the element represented by the access proxy to its default initial value.
+// In case the access proxy represents a vector- or matrix-like data structure that provides a
+// reset() function, this function resets all elements of the vector/matrix to the default initial
+// values.
+*/
+template< typename MT >
+inline void reset( const MatrixAccessProxy<MT>& proxy )
+{
+ using blaze::reset;
+
+ reset( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup sparse_matrix
+//
+// \param proxy The given access proxy.
+// \return void
+//
+// This function clears the element represented by the access proxy to its default initial state.
+// In case the access proxy represents a vector- or matrix-like data structure that provides a
+// clear() function, this function clears the vector/matrix to its default initial state.
+*/
+template< typename MT >
+inline void clear( const MatrixAccessProxy<MT>& proxy )
+{
+ using blaze::clear;
+
+ clear( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup sparse_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isDefault( const MatrixAccessProxy<MT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the matrix element represents a real number.
+// \ingroup sparse_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the matrix element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isReal( const MatrixAccessProxy<MT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup sparse_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isZero( const MatrixAccessProxy<MT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup sparse_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isOne( const MatrixAccessProxy<MT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup sparse_matrix
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT >
+inline bool isnan( const MatrixAccessProxy<MT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two access proxies.
+// \ingroup sparse_matrix
+//
+// \param a The first access proxy to be swapped.
+// \param b The second access proxy to be swapped.
+// \return void
+*/
+template< typename MT >
+inline void swap( const MatrixAccessProxy<MT>& a, const MatrixAccessProxy<MT>& b ) noexcept
+{
+ using std::swap;
+
+ swap( a.get(), b.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of an access proxy with another element.
+// \ingroup sparse_matrix
+//
+// \param a The access proxy to be swapped.
+// \param b The other element to be swapped.
+// \return void
+*/
+template< typename MT, typename T >
+inline void swap( const MatrixAccessProxy<MT>& a, T& b ) noexcept
+{
+ using std::swap;
+
+ swap( a.get(), b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of an access proxy with another element.
+// \ingroup sparse_matrix
+//
+// \param a The other element to be swapped.
+// \param b The access proxy to be swapped.
+// \return void
+*/
+template< typename T, typename MT >
+inline void swap( T& a, const MatrixAccessProxy<MT>& b ) noexcept
+{
+ using std::swap;
+
+ swap( a, b.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/SparseElement.h b/src/cpu/blaze/math/sparse/SparseElement.h
new file mode 100644
index 00000000..1d64e1ac
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/SparseElement.h
@@ -0,0 +1,63 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/SparseElement.h
+// \brief Header file for the SparseElement base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_SPARSEELEMENT_H_
+#define _BLAZE_MATH_SPARSE_SPARSEELEMENT_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for all sparse element types.
+// \ingroup math
+//
+// The SparseElement class is the base class for all sparse element types. All types that
+// conceptually represent a sparse vector or matrix element and that provide a \c value()
+// and an \c index() member function have to derive from this class in order to qualify
+// as sparse element. Only in case a class is derived from the SparseElement base class,
+// the IsSparseElement type trait recognizes the class as valid sparse element.
+*/
+struct SparseElement
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/SparseMatrix.h b/src/cpu/blaze/math/sparse/SparseMatrix.h
new file mode 100644
index 00000000..259506bd
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/SparseMatrix.h
@@ -0,0 +1,1589 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/SparseMatrix.h
+// \brief Header file for utility functions for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_SPARSEMATRIX_H_
+#define _BLAZE_MATH_SPARSE_SPARSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Triangular.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Conjugate.h>
+#include <blaze/math/shims/Equal.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/StorageOrder.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsIdentity.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsSquare.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniTriangular.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SparseMatrix operators */
+//@{
+template< typename T1, typename T2, bool SO >
+inline bool operator==( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,false>& rhs );
+
+template< typename T1, typename T2, bool SO >
+inline bool operator==( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,true>& rhs );
+
+template< typename T1, typename T2, bool SO >
+inline bool operator==( const SparseMatrix<T1,SO>& lhs, const SparseMatrix<T2,!SO>& rhs );
+
+template< typename T1, bool SO1, typename T2, bool SO2 >
+inline bool operator!=( const SparseMatrix<T1,SO1>& lhs, const SparseMatrix<T2,SO2>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of two row-major sparse matrices.
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the comparison.
+// \param rhs The right-hand side sparse matrix for the comparison.
+// \return \a true if the two sparse matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline bool operator==( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,false>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+ typedef ConstIterator_< RemoveReference_<CT1> > LhsConstIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RhsConstIterator;
+
+ // Early exit in case the matrix sizes don't match
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
+ return false;
+
+ // Evaluation of the two sparse matrix operands
+ CT1 A( ~lhs );
+ CT2 B( ~rhs );
+
+ // In order to compare the two matrices, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ const LhsConstIterator lend( A.end(i) );
+ const RhsConstIterator rend( B.end(i) );
+
+ LhsConstIterator lelem( A.begin(i) );
+ RhsConstIterator relem( B.begin(i) );
+
+ while( lelem != lend && relem != rend )
+ {
+ if( lelem->index() < relem->index() ) {
+ if( !isDefault( lelem->value() ) )
+ return false;
+ ++lelem;
+ }
+ else if( lelem->index() > relem->index() ) {
+ if( !isDefault( relem->value() ) )
+ return false;
+ ++relem;
+ }
+ else if( !equal( lelem->value(), relem->value() ) ) {
+ return false;
+ }
+ else {
+ ++lelem;
+ ++relem;
+ }
+ }
+
+ while( lelem != lend ) {
+ if( !isDefault( lelem->value() ) )
+ return false;
+ ++lelem;
+ }
+
+ while( relem != rend ) {
+ if( !isDefault( relem->value() ) )
+ return false;
+ ++relem;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of two column-major sparse matrices.
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the comparison.
+// \param rhs The right-hand side sparse matrix for the comparison.
+// \return \a true if the two sparse matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 > // Type of the right-hand side sparse matrix
+inline bool operator==( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,true>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+ typedef ConstIterator_< RemoveReference_<CT1> > LhsConstIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RhsConstIterator;
+
+ // Early exit in case the matrix sizes don't match
+ if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
+ return false;
+
+ // Evaluation of the two sparse matrix operands
+ CT1 A( ~lhs );
+ CT2 B( ~rhs );
+
+ // In order to compare the two matrices, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ const LhsConstIterator lend( A.end(j) );
+ const RhsConstIterator rend( B.end(j) );
+
+ LhsConstIterator lelem( A.begin(j) );
+ RhsConstIterator relem( B.begin(j) );
+
+ while( lelem != lend && relem != rend )
+ {
+ if( lelem->index() < relem->index() ) {
+ if( !isDefault( lelem->value() ) )
+ return false;
+ ++lelem;
+ }
+ else if( lelem->index() > relem->index() ) {
+ if( !isDefault( relem->value() ) )
+ return false;
+ ++relem;
+ }
+ else if( !equal( lelem->value(), relem->value() ) ) {
+ return false;
+ }
+ else {
+ ++lelem;
+ ++relem;
+ }
+ }
+
+ while( lelem != lend ) {
+ if( !isDefault( lelem->value() ) )
+ return false;
+ ++lelem;
+ }
+
+ while( relem != rend ) {
+ if( !isDefault( relem->value() ) )
+ return false;
+ ++relem;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of two sparse matrices with different storage order.
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the comparison.
+// \param rhs The right-hand side sparse matrix for the comparison.
+// \return \a true if the two sparse matrices are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order
+inline bool operator==( const SparseMatrix<T1,SO>& lhs, const SparseMatrix<T2,!SO>& rhs )
+{
+ const OppositeType_<T2> tmp( ~rhs );
+ return ( ~lhs == tmp );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of two sparse matrices.
+// \ingroup sparse_matrix
+//
+// \param lhs The left-hand side sparse matrix for the comparison.
+// \param rhs The right-hand side sparse matrix for the comparison.
+// \return \a true if the two sparse matrices are not equal, \a false if they are equal.
+*/
+template< typename T1 // Type of the left-hand side sparse matrix
+ , bool SO1 // Storage order of the left-hand side sparse matrix
+ , typename T2 // Type of the right-hand side sparse matrix
+ , bool SO2 > // Storage order of the right-hand side sparse matrix
+inline bool operator!=( const SparseMatrix<T1,SO1>& lhs, const SparseMatrix<T2,SO2>& rhs )
+{
+ return !( lhs == rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SparseMatrix functions */
+//@{
+template< typename MT, bool SO >
+bool isnan( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isSymmetric( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isHermitian( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isUniform( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isLower( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isUniLower( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isStrictlyLower( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isUpper( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isUniUpper( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isStrictlyUpper( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isDiagonal( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+bool isIdentity( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+const ElementType_<MT> min( const SparseMatrix<MT,SO>& sm );
+
+template< typename MT, bool SO >
+const ElementType_<MT> max( const SparseMatrix<MT,SO>& sm );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks the given sparse matrix for not-a-number elements.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked for not-a-number elements.
+// \return \a true if at least one element of the sparse matrix is not-a-number, \a false otherwise.
+//
+// This function checks the sparse matrix for not-a-number (NaN) elements. If at least one
+// element of the matrix is not-a-number, the function returns \a true, otherwise it returns
+// \a false.
+
+ \code
+ blaze::CompressedMatrix<double> A( 3UL, 4UL );
+ // ... Initialization
+ if( isnan( A ) ) { ... }
+ \endcode
+
+// Note that this function only works for matrices with floating point elements. The attempt to
+// use it for a matrix with a non-floating point element type results in a compile time error.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isnan( const SparseMatrix<MT,SO>& sm )
+{
+ typedef CompositeType_<MT> CT;
+ typedef ConstIterator_< RemoveReference_<CT> > ConstIterator;
+
+ CT A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
+ if( isnan( element->value() ) ) return true;
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
+ if( isnan( element->value() ) ) return true;
+ }
+ }
+
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is symmetric.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is symmetric, \a false if not.
+//
+// This function checks if the given sparse matrix is symmetric. The matrix is considered to be
+// symmetric if it is a square matrix whose transpose is equal to itself (\f$ A = A^T \f$). The
+// following code example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isSymmetric( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a symmetric matrix:
+
+ \code
+ if( isSymmetric( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isSymmetric( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsSymmetric<MT>::value )
+ return true;
+
+ if( !isSquare( ~sm ) )
+ return false;
+
+ if( (~sm).rows() < 2UL )
+ return true;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
+ {
+ const size_t j( element->index() );
+
+ if( i == j || isDefault( element->value() ) )
+ continue;
+
+ const ConstIterator pos( A.find( j, i ) );
+ if( pos == A.end(j) || !equal( pos->value(), element->value() ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
+ {
+ const size_t i( element->index() );
+
+ if( j == i || isDefault( element->value() ) )
+ continue;
+
+ const ConstIterator pos( A.find( j, i ) );
+ if( pos == A.end(i) || !equal( pos->value(), element->value() ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is Hermitian.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is Hermitian, \a false if not.
+//
+// This function checks if the given sparse matrix is an Hermitian matrix. The matrix is considered
+// to be an Hermitian matrix if it is a square matrix whose conjugate transpose is equal to itself
+// (\f$ A = \overline{A^T} \f$), i.e. each matrix element \f$ a_{ij} \f$ is equal to the complex
+// conjugate of the element \f$ a_{ji} \f$. The following code example demonstrates the use of the
+// function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isHermitian( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in an Hermitian matrix:
+
+ \code
+ if( isHermitian( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isHermitian( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ElementType_<MT> ET;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsHermitian<MT>::value )
+ return true;
+
+ if( !IsNumeric<ET>::value || !isSquare( ~sm ) )
+ return false;
+
+ if( (~sm).rows() < 2UL )
+ return true;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
+ {
+ const size_t j( element->index() );
+
+ if( isDefault( element->value() ) )
+ continue;
+
+ if( i == j && !isReal( element->value() ) )
+ return false;
+
+ const ConstIterator pos( A.find( j, i ) );
+ if( pos == A.end(j) || !equal( pos->value(), conj( element->value() ) ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
+ {
+ const size_t i( element->index() );
+
+ if( isDefault( element->value() ) )
+ continue;
+
+ if( j == i && !isReal( element->value() ) )
+ return false;
+
+ const ConstIterator pos( A.find( j, i ) );
+ if( pos == A.end(i) || !equal( pos->value(), conj( element->value() ) ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checks if the given row-major triangular sparse matrix is a uniform matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+*/
+template< typename MT > // Type of the sparse matrix
+bool isUniform_backend( const SparseMatrix<MT,false>& sm, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
+
+ typedef ConstIterator_<MT> ConstIterator;
+
+ const size_t ibegin( ( IsStrictlyLower<MT>::value )?( 1UL ):( 0UL ) );
+ const size_t iend ( ( IsStrictlyUpper<MT>::value )?( (~sm).rows()-1UL ):( (~sm).rows() ) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ for( ConstIterator element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checks if the given column-major triangular sparse matrix is a uniform matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+*/
+template< typename MT > // Type of the sparse matrix
+bool isUniform_backend( const SparseMatrix<MT,true>& sm, TrueType )
+{
+ BLAZE_CONSTRAINT_MUST_BE_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
+
+ typedef ConstIterator_<MT> ConstIterator;
+
+ const size_t jbegin( ( IsStrictlyUpper<MT>::value )?( 1UL ):( 0UL ) );
+ const size_t jend ( ( IsStrictlyLower<MT>::value )?( (~sm).columns()-1UL ):( (~sm).columns() ) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ for( ConstIterator element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checks if the given row-major general sparse matrix is a uniform matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+*/
+template< typename MT > // Type of the sparse matrix
+bool isUniform_backend( const SparseMatrix<MT,false>& sm, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
+
+ typedef ConstReference_<MT> ConstReference;
+ typedef ConstIterator_<MT> ConstIterator;
+
+ const size_t maxElements( (~sm).rows() * (~sm).columns() );
+
+ if( (~sm).nonZeros() != maxElements )
+ {
+ for( size_t i=0UL; i<(~sm).rows(); ++i ) {
+ for( ConstIterator element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+ else
+ {
+ BLAZE_INTERNAL_ASSERT( (~sm).find(0UL,0UL) != (~sm).end(0UL), "Missing element detected" );
+
+ ConstReference cmp( (~sm)(0UL,0UL) );
+
+ for( size_t i=0UL; i<(~sm).rows(); ++i ) {
+ for( ConstIterator element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
+ if( element->value() != cmp )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checks if the given column-major general sparse matrix is a uniform matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+*/
+template< typename MT > // Type of the sparse matrix
+bool isUniform_backend( const SparseMatrix<MT,true>& sm, FalseType )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRIANGULAR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT );
+
+ BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
+ BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
+
+ typedef ConstReference_<MT> ConstReference;
+ typedef ConstIterator_<MT> ConstIterator;
+
+ const size_t maxElements( (~sm).rows() * (~sm).columns() );
+
+ if( (~sm).nonZeros() != maxElements )
+ {
+ for( size_t j=0UL; j<(~sm).columns(); ++j ) {
+ for( ConstIterator element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+ else
+ {
+ BLAZE_INTERNAL_ASSERT( (~sm).find(0UL,0UL) != (~sm).end(0UL), "Missing element detected" );
+
+ ConstReference cmp( (~sm)(0UL,0UL) );
+
+ for( size_t j=0UL; j<(~sm).columns(); ++j ) {
+ for( ConstIterator element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
+ if( element->value() != cmp )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is a uniform matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a uniform matrix, \a false if not.
+//
+// This function checks if the given sparse matrix is a uniform matrix. The matrix is considered
+// to be uniform if all its elements are identical. The following code example demonstrates the
+// use of the function:
+
+ \code
+ blaze::DynamicMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isUniform( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a uniform matrix:
+
+ \code
+ if( isUniform( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isUniform( const SparseMatrix<MT,SO>& sm )
+{
+ if( IsUniTriangular<MT>::value )
+ return false;
+
+ if( (~sm).rows() == 0UL || (~sm).columns() == 0UL ||
+ ( (~sm).rows() == 1UL && (~sm).columns() == 1UL ) )
+ return true;
+
+ CompositeType_<MT> A( ~sm ); // Evaluation of the sparse matrix operand
+
+ return isUniform_backend( A, typename IsTriangular<MT>::Type() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is a lower triangular matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a lower triangular matrix, \a false if not.
+//
+// This function checks if the given sparse matrix is a lower triangular matrix. The matrix is
+// considered to be lower triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ l_{0,0} & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & l_{1,1} & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & l_{2,2} & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & l_{N,N} \\
+ \end{array}\right).\f]
+
+// \f$ 0 \times 0 \f$ or \f$ 1 \times 1 \f$ matrices are considered as trivially lower triangular.
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isLower( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a lower triangular matrix:
+
+ \code
+ if( isLower( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isLower( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsLower<MT>::value )
+ return true;
+
+ if( !isSquare( ~sm ) )
+ return false;
+
+ if( (~sm).rows() < 2UL )
+ return true;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows()-1UL; ++i ) {
+ for( ConstIterator element=A.lowerBound(i,i+1UL); element!=A.end(i); ++element )
+ {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=1UL; j<A.columns(); ++j ) {
+ for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
+ {
+ if( element->index() >= j )
+ break;
+
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is a lower unitriangular matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a lower unitriangular matrix, \a false if not.
+//
+// This function checks if the given sparse matrix is a lower unitriangular matrix. The matrix is
+// considered to be lower unitriangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & 1 & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & 1 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & 1 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isUniLower( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a lower unitriangular matrix:
+
+ \code
+ if( isUniLower( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isUniLower( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsUniLower<MT>::value )
+ return true;
+
+ if( !isSquare( ~sm ) )
+ return false;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ ConstIterator element( A.lowerBound(i,i) );
+
+ if( element == A.end(i) || element->index() != i || !isOne( element->value() ) )
+ return false;
+
+ ++element;
+
+ for( ; element!=A.end(i); ++element ) {
+ if( !isZero( element->value() ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ bool hasDiagonalElement( false );
+
+ for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
+ {
+ if( element->index() >= j ) {
+ if( element->index() != j || !isOne( element->value() ) )
+ return false;
+ hasDiagonalElement = true;
+ break;
+ }
+
+ if( !isZero( element->value() ) )
+ return false;
+ }
+
+ if( !hasDiagonalElement ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is a strictly lower triangular matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a strictly lower triangular matrix, \a false if not.
+//
+// This function checks if the given sparse matrix is a strictly lower triangular matrix. The
+// matrix is considered to be strictly lower triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & 0 & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & 0 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & 0 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isStrictlyLower( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a strictly lower triangular
+// matrix:
+
+ \code
+ if( isStrictlyLower( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isStrictlyLower( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsStrictlyLower<MT>::value )
+ return true;
+
+ if( IsUniLower<MT>::value || IsUniUpper<MT>::value || !isSquare( ~sm ) )
+ return false;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( ConstIterator element=A.lowerBound(i,i); element!=A.end(i); ++element )
+ {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
+ {
+ if( element->index() > j )
+ break;
+
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is an upper triangular matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is an upper triangular matrix, \a false if not.
+//
+// This function checks if the given sparse matrix is an upper triangular matrix. The matrix is
+// considered to be upper triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ u_{0,0} & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & u_{1,1} & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & u_{2,2} & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & u_{N,N} \\
+ \end{array}\right).\f]
+
+// \f$ 0 \times 0 \f$ or \f$ 1 \times 1 \f$ matrices are considered as trivially upper triangular.
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isUpper( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in an upper triangular matrix:
+
+ \code
+ if( isUpper( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isUpper( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsUpper<MT>::value )
+ return true;
+
+ if( !isSquare( ~sm ) )
+ return false;
+
+ if( (~sm).rows() < 2UL )
+ return true;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=1UL; i<A.rows(); ++i ) {
+ for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
+ {
+ if( element->index() >= i )
+ break;
+
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns()-1UL; ++j ) {
+ for( ConstIterator element=A.lowerBound(j+1UL,j); element!=A.end(j); ++element )
+ {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is an upper unitriangular matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is an upper unitriangular matrix, \a false if not.
+//
+// This function checks if the given sparse matrix is an upper unitriangular matrix. The matrix is
+// considered to be upper unitriangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & 1 & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & 1 & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & 1 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isUniUpper( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in an upper unitriangular matrix:
+
+ \code
+ if( isUniUpper( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isUniUpper( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsUniUpper<MT>::value )
+ return true;
+
+ if( !isSquare( ~sm ) )
+ return false;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ bool hasDiagonalElement( false );
+
+ for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
+ {
+ if( element->index() >= i ) {
+ if( element->index() != i || !isOne( element->value() ) )
+ return false;
+ hasDiagonalElement = true;
+ break;
+ }
+ else if( !isZero( element->value() ) ) {
+ return false;
+ }
+ }
+
+ if( !hasDiagonalElement ) {
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ ConstIterator element( A.lowerBound(j,j) );
+
+ if( element == A.end(j) || element->index() != j || !isOne( element->value() ) )
+ return false;
+
+ ++element;
+
+ for( ; element!=A.end(j); ++element ) {
+ if( !isZero( element->value() ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse matrix is a strictly upper triangular matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is a strictly upper triangular matrix, \a false if not.
+//
+// This function checks if the given sparse matrix is a strictly upper triangular matrix. The
+// matrix is considered to be strictly upper triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & 0 & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & 0 & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & 0 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isStrictlyUpper( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a strictly upper triangular
+// matrix:
+
+ \code
+ if( isStrictlyUpper( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isStrictlyUpper( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsStrictlyUpper<MT>::value )
+ return true;
+
+ if( IsUniLower<MT>::value || IsUniUpper<MT>::value || !isSquare( ~sm ) )
+ return false;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
+ {
+ if( element->index() > i )
+ break;
+
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( ConstIterator element=A.lowerBound(j,j); element!=A.end(j); ++element )
+ {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the give sparse matrix is diagonal.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is diagonal, \a false if not.
+//
+// This function tests whether the matrix is diagonal, i.e. if the non-diagonal elements are
+// default elements. In case of integral or floating point data types, a diagonal matrix has
+// the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ aa & 0 & 0 & \cdots & 0 \\
+ 0 & bb & 0 & \cdots & 0 \\
+ 0 & 0 & cc & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & 0 \\
+ 0 & 0 & 0 & 0 & xx \\
+ \end{array}\right)\f]
+
+// The following example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isDiagonal( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in a diagonal matrix:
+
+ \code
+ if( isDiagonal( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isDiagonal( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsDiagonal<MT>::value )
+ return true;
+
+ if( !isSquare( ~sm ) )
+ return false;
+
+ if( (~sm).rows() < 2UL )
+ return true;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i ) {
+ for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
+ if( element->index() != i && !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j ) {
+ for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
+ if( element->index() != j && !isDefault( element->value() ) )
+ return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the give sparse matrix is an identity matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The sparse matrix to be checked.
+// \return \a true if the matrix is an identity matrix, \a false if not.
+//
+// This function tests whether the matrix is an identity matrix, i.e. if the diagonal elements
+// are 1 and the non-diagonal elements are 0. In case of integral or floating point data types,
+// an identity matrix has the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & 0 & 0 & \cdots & 0 \\
+ 0 & 1 & 0 & \cdots & 0 \\
+ 0 & 0 & 1 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & 0 \\
+ 0 & 0 & 0 & 0 & 1 \\
+ \end{array}\right)\f]
+
+// The following example demonstrates the use of the function:
+
+ \code
+ blaze::CompressedMatrix<int,blaze::rowMajor> A, B;
+ // ... Initialization
+ if( isIdentity( A ) ) { ... }
+ \endcode
+
+// It is also possible to check if a matrix expression results in an identity matrix:
+
+ \code
+ if( isIdentity( A * B ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary matrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+bool isIdentity( const SparseMatrix<MT,SO>& sm )
+{
+ typedef ResultType_<MT> RT;
+ typedef ReturnType_<MT> RN;
+ typedef CompositeType_<MT> CT;
+ typedef If_< IsExpression<RN>, const RT, CT > Tmp;
+ typedef ConstIterator_< RemoveReference_<Tmp> > ConstIterator;
+
+ if( IsIdentity<MT>::value )
+ return true;
+
+ if( !isSquare( ~sm ) )
+ return false;
+
+ Tmp A( ~sm ); // Evaluation of the sparse matrix operand
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<A.rows(); ++i )
+ {
+ bool hasDiagonalElement( false );
+
+ for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
+ {
+ if( element->index() == i ) {
+ if( !isOne( element->value() ) )
+ return false;
+ hasDiagonalElement = true;
+ }
+ else if( !isZero( element->value() ) ) {
+ return false;
+ }
+ }
+
+ if( !hasDiagonalElement ) {
+ return false;
+ }
+ }
+ }
+ else {
+ for( size_t j=0UL; j<A.columns(); ++j )
+ {
+ bool hasDiagonalElement( false );
+
+ for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
+ {
+ if( element->index() == j ) {
+ if( !isOne( element->value() ) )
+ return false;
+ hasDiagonalElement = true;
+ }
+ else if( !isZero( element->value() ) ) {
+ return false;
+ }
+ }
+
+ if( !hasDiagonalElement ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the smallest element of the sparse matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The given sparse matrix.
+// \return The smallest sparse matrix element.
+//
+// This function returns the smallest element of the given sparse matrix. This function can
+// only be used for element types that support the smaller-than relationship. In case the
+// matrix currently has either 0 rows or 0 columns, the returned value is the default value
+// (e.g. 0 in case of fundamental data types).
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+const ElementType_<MT> min( const SparseMatrix<MT,SO>& sm )
+{
+ using blaze::min;
+
+ typedef ElementType_<MT> ET;
+ typedef CompositeType_<MT> CT;
+ typedef ConstIterator_< RemoveReference_<CT> > ConstIterator;
+
+ CT A( ~sm ); // Evaluation of the sparse matrix operand
+
+ const size_t nonzeros( A.nonZeros() );
+
+ if( nonzeros == 0UL ) {
+ return ET();
+ }
+
+ ET minimum = ET();
+ if( nonzeros == A.rows() * A.columns() ) {
+ minimum = A.begin( 0UL )->value();
+ }
+
+ const size_t index( ( SO == rowMajor )?( A.rows() ):( A.columns() ) );
+
+ for( size_t i=0UL; i<index; ++i ) {
+ const ConstIterator end( A.end( i ) );
+ ConstIterator element( A.begin( i ) );
+ for( ; element!=end; ++element )
+ minimum = min( minimum, element->value() );
+ }
+
+ return minimum;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the largest element of the sparse matrix.
+// \ingroup sparse_matrix
+//
+// \param sm The given sparse matrix.
+// \return The largest sparse matrix element.
+//
+// This function returns the largest element of the given sparse matrix. This function can
+// only be used for element types that support the smaller-than relationship. In case the
+// matrix currently has either 0 rows or 0 columns, the returned value is the default value
+// (e.g. 0 in case of fundamental data types).
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO > // Storage order
+const ElementType_<MT> max( const SparseMatrix<MT,SO>& sm )
+{
+ using blaze::max;
+
+ typedef ElementType_<MT> ET;
+ typedef CompositeType_<MT> CT;
+ typedef ConstIterator_< RemoveReference_<CT> > ConstIterator;
+
+ CT A( ~sm ); // Evaluation of the sparse matrix operand
+
+ const size_t nonzeros( A.nonZeros() );
+
+ if( nonzeros == 0UL ) {
+ return ET();
+ }
+
+ ET maximum = ET();
+ if( nonzeros == A.rows() * A.columns() ) {
+ maximum = A.begin( 0UL )->value();
+ }
+
+ const size_t index( ( SO == rowMajor )?( A.rows() ):( A.columns() ) );
+
+ for( size_t i=0UL; i<index; ++i ) {
+ const ConstIterator end( A.end( i ) );
+ ConstIterator element( A.begin( i ) );
+ for( ; element!=end; ++element )
+ maximum = max( maximum, element->value() );
+ }
+
+ return maximum;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/SparseVector.h b/src/cpu/blaze/math/sparse/SparseVector.h
new file mode 100644
index 00000000..4dcd1388
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/SparseVector.h
@@ -0,0 +1,488 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/SparseVector.h
+// \brief Header file for utility functions for sparse vectors
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_SPARSEVECTOR_H_
+#define _BLAZE_MATH_SPARSE_SPARSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cmath>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/Equal.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/Sqrt.h>
+#include <blaze/math/shims/Square.h>
+#include <blaze/math/TransposeFlag.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SparseVector operators */
+//@{
+template< typename T1, bool TF1, typename T2, bool TF2 >
+inline bool operator==( const SparseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs );
+
+template< typename T1, bool TF1, typename T2, bool TF2 >
+inline bool operator!=( const SparseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality operator for the comparison of two sparse vectors.
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the comparison.
+// \param rhs The right-hand side sparse vector for the comparison.
+// \return \a true if the two sparse vectors are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , bool TF1 // Transpose flag of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+inline bool operator==( const SparseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs )
+{
+ typedef CompositeType_<T1> CT1;
+ typedef CompositeType_<T2> CT2;
+ typedef ConstIterator_< RemoveReference_<CT1> > LhsConstIterator;
+ typedef ConstIterator_< RemoveReference_<CT2> > RhsConstIterator;
+
+ // Early exit in case the vector sizes don't match
+ if( (~lhs).size() != (~rhs).size() ) return false;
+
+ // Evaluation of the two sparse vector operands
+ CT1 a( ~lhs );
+ CT2 b( ~rhs );
+
+ // In order to compare the two vectors, the data values of the lower-order data
+ // type are converted to the higher-order data type within the equal function.
+ const LhsConstIterator lend( a.end() );
+ const RhsConstIterator rend( b.end() );
+
+ LhsConstIterator lelem( a.begin() );
+ RhsConstIterator relem( b.begin() );
+
+ while( lelem != lend && relem != rend )
+ {
+ if( isDefault( lelem->value() ) ) { ++lelem; continue; }
+ if( isDefault( relem->value() ) ) { ++relem; continue; }
+
+ if( lelem->index() != relem->index() || !equal( lelem->value(), relem->value() ) ) {
+ return false;
+ }
+ else {
+ ++lelem;
+ ++relem;
+ }
+ }
+
+ while( lelem != lend ) {
+ if( !isDefault( lelem->value() ) )
+ return false;
+ ++lelem;
+ }
+
+ while( relem != rend ) {
+ if( !isDefault( relem->value() ) )
+ return false;
+ ++relem;
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality operator for the comparison of two sparse vectors.
+// \ingroup sparse_vector
+//
+// \param lhs The left-hand side sparse vector for the comparison.
+// \param rhs The right-hand side sparse vector for the comparison.
+// \return \a true if the two vectors are not equal, \a false if they are equal.
+*/
+template< typename T1 // Type of the left-hand side sparse vector
+ , bool TF1 // Transpose flag of the left-hand side sparse vector
+ , typename T2 // Type of the right-hand side sparse vector
+ , bool TF2 > // Transpose flag of the right-hand side sparse vector
+inline bool operator!=( const SparseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs )
+{
+ return !( lhs == rhs );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name SparseVector functions */
+//@{
+template< typename VT, bool TF >
+bool isnan( const SparseVector<VT,TF>& sv );
+
+template< typename VT, bool TF >
+bool isUniform( const SparseVector<VT,TF>& dv );
+
+template< typename VT, bool TF >
+const ElementType_<VT> sqrLength( const SparseVector<VT,TF>& sv );
+
+template< typename VT, bool TF >
+inline auto length( const SparseVector<VT,TF>& sv ) -> decltype( sqrt( sqrLength( ~sv ) ) );
+
+template< typename VT, bool TF >
+const ElementType_<VT> min( const SparseVector<VT,TF>& sv );
+
+template< typename VT, bool TF >
+const ElementType_<VT> max( const SparseVector<VT,TF>& sv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks the given sparse vector for not-a-number elements.
+// \ingroup sparse_vector
+//
+// \param sv The sparse vector to be checked for not-a-number elements.
+// \return \a true if at least one element of the vector is not-a-number, \a false otherwise.
+//
+// This function checks the N-dimensional sparse vector for not-a-number (NaN) elements. If
+// at least one element of the vector is not-a-number, the function returns \a true, otherwise
+// it returns \a false.
+
+ \code
+ blaze::CompressedVector<double> a;
+ // ... Resizing and initialization
+ if( isnan( a ) ) { ... }
+ \endcode
+
+// Note that this function only works for vectors with floating point elements. The attempt to
+// use it for a vector with a non-floating point element type results in a compile time error.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline bool isnan( const SparseVector<VT,TF>& sv )
+{
+ typedef CompositeType_<VT> CT;
+ typedef ConstIterator_< RemoveReference_<CT> > ConstIterator;
+
+ CT a( ~sv ); // Evaluation of the sparse vector operand
+
+ const ConstIterator end( a.end() );
+ for( ConstIterator element=a.begin(); element!=end; ++element ) {
+ if( isnan( element->value() ) ) return true;
+ }
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given sparse vector is a uniform vector.
+// \ingroup sparse_vector
+//
+// \param sv The sparse vector to be checked.
+// \return \a true if the vector is a uniform vector, \a false if not.
+//
+// This function checks if the given sparse vector is a uniform vector. The vector is considered
+// to be uniform if all its elements are identical. The following code example demonstrates the
+// use of the function:
+
+ \code
+ blaze::CompressedVector<int,blaze::columnVector> a, b;
+ // ... Initialization
+ if( isUniform( a ) ) { ... }
+ \endcode
+
+// It is also possible to check if a vector expression results in a uniform vector:
+
+ \code
+ if( isUniform( a + b ) ) { ... }
+ \endcode
+
+// However, note that this might require the complete evaluation of the expression, including
+// the generation of a temporary vector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+bool isUniform( const SparseVector<VT,TF>& sv )
+{
+ typedef CompositeType_<VT> CT;
+ typedef ConstReference_< RemoveReference_<CT> > ConstReference;
+ typedef ConstIterator_< RemoveReference_<CT> > ConstIterator;
+
+ if( (~sv).size() < 2UL )
+ return true;
+
+ CT a( ~sv ); // Evaluation of the sparse vector operand
+
+ if( (~sv).nonZeros() != (~sv).size() )
+ {
+ for( ConstIterator element=(~sv).begin(); element!=(~sv).end(); ++element ) {
+ if( !isDefault( element->value() ) )
+ return false;
+ }
+ }
+ else
+ {
+ ConstReference cmp( (~sv)[0] );
+ ConstIterator element( (~sv).begin() );
+
+ ++element;
+
+ for( ; element!=(~sv).end(); ++element ) {
+ if( element->value() != cmp )
+ return false;
+ }
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Calculation of the sparse vector square length \f$|\vec{a}|^2\f$.
+// \ingroup sparse_vector
+//
+// \param sv The given sparse vector.
+// \return The square length of the vector.
+//
+// This function calculates the actual square length of the sparse vector.
+//
+// \note This operation is only defined for numeric data types. In case the element type is
+// not a numeric data type (i.e. a user defined data type or boolean) the attempt to use the
+// sqrLength() function results in a compile time error!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+const ElementType_<VT> sqrLength( const SparseVector<VT,TF>& sv )
+{
+ typedef ElementType_<VT> ElementType;
+ typedef ConstIterator_<VT> ConstIterator;
+
+ BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ElementType );
+
+ ElementType sum( 0 );
+ for( ConstIterator element=(~sv).begin(); element!=(~sv).end(); ++element )
+ sum += sq( element->value() );
+ return sum;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Calculation of the sparse vector length \f$|\vec{a}|\f$.
+// \ingroup sparse_vector
+//
+// \param sv The given sparse vector.
+// \return The length of the sparse vector.
+//
+// This function calculates the actual length of the sparse vector. The return type of the
+// length() function depends on the actual element type of the vector instance:
+//
+// <table border="0" cellspacing="0" cellpadding="1">
+// <tr>
+// <td width="250px"> \b Type </td>
+// <td width="100px"> \b LengthType </td>
+// </tr>
+// <tr>
+// <td>float</td>
+// <td>float</td>
+// </tr>
+// <tr>
+// <td>integral data types and double</td>
+// <td>double</td>
+// </tr>
+// <tr>
+// <td>long double</td>
+// <td>long double</td>
+// </tr>
+// <tr>
+// <td>complex<T></td>
+// <td>complex<T></td>
+// </tr>
+// </table>
+//
+// \note This operation is only defined for numeric data types. In case the element type is
+// not a numeric data type (i.e. a user defined data type or boolean) the attempt to use the
+// length() function results in a compile time error!
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+inline auto length( const SparseVector<VT,TF>& sv ) -> decltype( sqrt( sqrLength( ~sv ) ) )
+{
+ return sqrt( sqrLength( ~sv ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the smallest element of the sparse vector.
+// \ingroup sparse_vector
+//
+// \param sv The given sparse vector.
+// \return The smallest sparse vector element.
+//
+// This function returns the smallest element of the given sparse vector. This function can
+// only be used for element types that support the smaller-than relationship. In case the
+// vector currently has a size of 0, the returned value is the default value (e.g. 0 in case
+// of fundamental data types).
+//
+// \note In case the sparse vector is not completely filled, the zero elements are also
+// taken into account. Example: the following compressed vector has only 2 non-zero elements.
+// However, the minimum of this vector is 0:
+
+ \f[
+ \left(\begin{array}{*{4}{c}}
+ 1 & 0 & 3 & 0 \\
+ \end{array}\right)
+ \f]
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+const ElementType_<VT> min( const SparseVector<VT,TF>& sv )
+{
+ using blaze::min;
+
+ typedef ElementType_<VT> ET;
+ typedef CompositeType_<VT> CT;
+ typedef ConstIterator_< RemoveReference_<CT> > ConstIterator;
+
+ CT a( ~sv ); // Evaluation of the sparse vector operand
+
+ const ConstIterator end( a.end() );
+ ConstIterator element( a.begin() );
+
+ if( element == end ) {
+ return ET();
+ }
+ else if( a.nonZeros() == a.size() ) {
+ ET minimum( element->value() );
+ ++element;
+ for( ; element!=end; ++element )
+ minimum = min( minimum, element->value() );
+ return minimum;
+ }
+ else {
+ ET minimum = ET();
+ for( ; element!=end; ++element )
+ minimum = min( minimum, element->value() );
+ return minimum;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the largest element of the sparse vector.
+// \ingroup sparse_vector
+//
+// \param sv The given sparse vector.
+// \return The largest sparse vector element.
+//
+// This function returns the largest element of the given sparse vector. This function can
+// only be used for element types that support the smaller-than relationship. In case the
+// vector currently has a size of 0, the returned value is the default value (e.g. 0 in case
+// of fundamental data types).
+//
+// \note In case the compressed vector is not completely filled, the zero elements are also
+// taken into account. Example: the following compressed vector has only 2 non-zero elements.
+// However, the maximum of this vector is 0:
+
+ \f[
+ \left(\begin{array}{*{4}{c}}
+ -1 & 0 & -3 & 0 \\
+ \end{array}\right)
+ \f]
+*/
+template< typename VT // Type of the sparse vector
+ , bool TF > // Transpose flag
+const ElementType_<VT> max( const SparseVector<VT,TF>& sv )
+{
+ using blaze::max;
+
+ typedef ElementType_<VT> ET;
+ typedef CompositeType_<VT> CT;
+ typedef ConstIterator_< RemoveReference_<CT> > ConstIterator;
+
+ CT a( ~sv ); // Evaluation of the sparse vector operand
+
+ const ConstIterator end( a.end() );
+ ConstIterator element( a.begin() );
+
+ if( element == end ) {
+ return ET();
+ }
+ else if( a.nonZeros() == a.size() ) {
+ ET maximum( element->value() );
+ ++element;
+ for( ; element!=end; ++element )
+ maximum = max( maximum, element->value() );
+ return maximum;
+ }
+ else {
+ ET maximum = ET();
+ for( ; element!=end; ++element )
+ maximum = max( maximum, element->value() );
+ return maximum;
+ }
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/ValueIndexPair.h b/src/cpu/blaze/math/sparse/ValueIndexPair.h
new file mode 100644
index 00000000..29820f1c
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/ValueIndexPair.h
@@ -0,0 +1,337 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/ValueIndexPair.h
+// \brief Header file for the ValueIndexPair class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_VALUEINDEXPAIR_H_
+#define _BLAZE_MATH_SPARSE_VALUEINDEXPAIR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/typetraits/IsSparseElement.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Index-value-pair for sparse vectors and matrices.
+// \ingroup math
+//
+// The ValueIndexPair class represents a single index-value-pair of a sparse vector or sparse
+// matrix.
+*/
+template< typename Type > // Type of the value element
+class ValueIndexPair : private SparseElement
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef Type ValueType; //!< The value type of the value-index-pair.
+ typedef size_t IndexType; //!< The index type of the value-index-pair.
+ typedef Type& Reference; //!< Reference return type.
+ typedef const Type& ConstReference; //!< Reference-to-const return type.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ inline ValueIndexPair();
+ inline ValueIndexPair( const Type& v, size_t i );
+ // No explicitly declared copy constructor.
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Operators***********************************************************************************
+ /*!\name Operators */
+ //@{
+ // No explicitly declared copy assignment operator.
+
+ template< typename Other >
+ inline EnableIf_< IsSparseElement<Other>, ValueIndexPair& > operator=( const Other& rhs );
+
+ template< typename Other >
+ inline DisableIf_< IsSparseElement<Other>, ValueIndexPair& > operator=( const Other& v );
+
+ template< typename Other > inline ValueIndexPair& operator+=( const Other& v );
+ template< typename Other > inline ValueIndexPair& operator-=( const Other& v );
+ template< typename Other > inline ValueIndexPair& operator*=( const Other& v );
+ template< typename Other > inline ValueIndexPair& operator/=( const Other& v );
+ //@}
+ //**********************************************************************************************
+
+ //**Acess functions*****************************************************************************
+ /*!\name Access functions */
+ //@{
+ inline Reference value();
+ inline ConstReference value() const;
+ inline IndexType index() const;
+ //@}
+ //**********************************************************************************************
+
+ protected:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Type value_; //!< Value of the value-index-pair.
+ size_t index_; //!< Index of the value-index-pair.
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename Other > friend class ValueIndexPair;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default constructor for value-index-pairs.
+*/
+template< typename Type > // Type of the value element
+inline ValueIndexPair<Type>::ValueIndexPair()
+ : value_() // Value of the value-index-pair
+ , index_() // Index of the value-index-pair
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for a direct initialization of value-index-pairs.
+//
+// \param v The value of the value-index-pair.
+// \param i The index of the value-index-pair.
+*/
+template< typename Type > // Type of the value element
+inline ValueIndexPair<Type>::ValueIndexPair( const Type& v, size_t i )
+ : value_( v ) // Value of the value-index-pair
+ , index_( i ) // Index of the value-index-pair
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different value-index-pair types.
+//
+// \param rhs Value-index-pair to be copied.
+// \return Reference to the assigned value-index-pair.
+//
+// This assignment operator enables the assignment of other value-index-pair types. The given
+// \a Other data type qualifies as value-index-pair type in case it provides a value() and an
+// index() member function.
+*/
+template< typename Type > // Type of the value element
+template< typename Other > // Data type of the right-hand side value-index-pair
+inline EnableIf_< IsSparseElement<Other>, ValueIndexPair<Type>& >
+ ValueIndexPair<Type>::operator=( const Other& rhs )
+{
+ value_ = rhs.value();
+ index_ = rhs.index();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the value of the value-index-pair.
+//
+// \param v The new value-index-pair value.
+// \return Reference to the assigned value-index-pair.
+*/
+template< typename Type > // Type of the value element
+template< typename Other > // Data type of the right-hand side value
+inline DisableIf_< IsSparseElement<Other>, ValueIndexPair<Type>& >
+ ValueIndexPair<Type>::operator=( const Other& v )
+{
+ value_ = v;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the value of the value-index-pair.
+//
+// \param v The right-hand side value to be added to the value-index-pair value.
+// \return Reference to the assigned value-index-pair.
+*/
+template< typename Type > // Type of the value element
+template< typename Other > // Data type of the right-hand side value
+inline ValueIndexPair<Type>& ValueIndexPair<Type>::operator+=( const Other& v )
+{
+ value_ += v;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the value of the value-index-pair.
+//
+// \param v The right-hand side value to be subtracted from the value-index-pair value.
+// \return Reference to the assigned value-index-pair.
+*/
+template< typename Type > // Type of the value element
+template< typename Other > // Data type of the right-hand side value
+inline ValueIndexPair<Type>& ValueIndexPair<Type>::operator-=( const Other& v )
+{
+ value_ -= v;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the value of the value-index-pair.
+//
+// \param v The right-hand side value for the multiplication.
+// \return Reference to the assigned value-index-pair.
+*/
+template< typename Type > // Type of the value element
+template< typename Other > // Data type of the right-hand side value
+inline ValueIndexPair<Type>& ValueIndexPair<Type>::operator*=( const Other& v )
+{
+ value_ *= v;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the value of the value-index-pair.
+//
+// \param v The right-hand side value for the division
+// \return Reference to the assigned value-index-pair.
+*/
+template< typename Type > // Type of the value element
+template< typename Other > // Data type of the right-hand side value
+inline ValueIndexPair<Type>& ValueIndexPair<Type>::operator/=( const Other& v )
+{
+ value_ /= v;
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access to the current value of the value-index-pair.
+//
+// \return The current value of the value-index-pair.
+*/
+template< typename Type > // Type of the value element
+inline typename ValueIndexPair<Type>::Reference ValueIndexPair<Type>::value()
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the current value of the value-index-pair.
+//
+// \return The current value of the value-index-pair.
+*/
+template< typename Type > // Type of the value element
+inline typename ValueIndexPair<Type>::ConstReference ValueIndexPair<Type>::value() const
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Access to the current index of the value-index-pair.
+//
+// \return The current index of the value-index-pair.
+*/
+template< typename Type > // Type of the value element
+inline typename ValueIndexPair<Type>::IndexType ValueIndexPair<Type>::index() const
+{
+ return index_;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/sparse/VectorAccessProxy.h b/src/cpu/blaze/math/sparse/VectorAccessProxy.h
new file mode 100644
index 00000000..1f711663
--- /dev/null
+++ b/src/cpu/blaze/math/sparse/VectorAccessProxy.h
@@ -0,0 +1,673 @@
+//=================================================================================================
+/*!
+// \file blaze/math/sparse/VectorAccessProxy.h
+// \brief Header file for the VectorAccessProxy class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_SPARSE_VECTORACCESSPROXY_H_
+#define _BLAZE_MATH_SPARSE_VECTORACCESSPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/proxy/Proxy.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/IsNaN.h>
+#include <blaze/math/shims/IsOne.h>
+#include <blaze/math/shims/IsReal.h>
+#include <blaze/math/shims/IsZero.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access proxy for sparse, N-dimensional vectors.
+// \ingroup sparse_vector
+//
+// The VectorAccessProxy provides safe access to the elements of a non-const sparse vector.\n
+// The proxied access to the elements of a sparse vector is necessary since it may be possible
+// that several insertion operations happen in the same statement. The following code illustrates
+// this with two examples by means of the CompressedVector class:
+
+ \code
+ blaze::CompressedVector<double> a( 5 );
+
+ // Standard usage of the subscript operator to initialize a vector element.
+ // Only a single sparse vector element is accessed!
+ a[0] = 1.0;
+
+ // Initialization of a vector element via another vector element.
+ // Two sparse vector accesses in one statement!
+ a[1] = a[0];
+
+ // Multiple accesses to elements of the sparse vector in one statement!
+ const double result = a[0] + a[2] + a[4];
+ \endcode
+
+// The problem (especially with the last statement) is that several insertion operations might
+// take place due to the access via the subscript operator. If the subscript operator would
+// return a direct reference to one of the accessed elements, this reference might be invalidated
+// during the evaluation of a subsequent subscript operator, which results in undefined behavior.
+// This class provides the necessary functionality to guarantee a safe access to the sparse vector
+// elements while preserving the intuitive use of the subscript operator.
+//
+*/
+template< typename VT > // Type of the sparse vector
+class VectorAccessProxy : public Proxy< VectorAccessProxy<VT>, ElementType_<VT> >
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef ElementType_<VT> RepresentedType; //!< Type of the represented sparse vector element.
+ typedef RepresentedType& RawReference; //!< Raw reference to the represented element.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline VectorAccessProxy( VT& sv, size_t i );
+ inline VectorAccessProxy( const VectorAccessProxy& vap );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~VectorAccessProxy();
+ //@}
+ //**********************************************************************************************
+
+ //**Operators***********************************************************************************
+ /*!\name Operators */
+ //@{
+ inline const VectorAccessProxy& operator=( const VectorAccessProxy& vap ) const;
+
+ template< typename T >
+ inline const VectorAccessProxy& operator=( initializer_list<T> list ) const;
+
+ template< typename T >
+ inline const VectorAccessProxy& operator=( initializer_list< initializer_list<T> > list ) const;
+
+ template< typename T > inline const VectorAccessProxy& operator= ( const T& value ) const;
+ template< typename T > inline const VectorAccessProxy& operator+=( const T& value ) const;
+ template< typename T > inline const VectorAccessProxy& operator-=( const T& value ) const;
+ template< typename T > inline const VectorAccessProxy& operator*=( const T& value ) const;
+ template< typename T > inline const VectorAccessProxy& operator/=( const T& value ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline RawReference get() const noexcept;
+ inline bool isRestricted() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator RawReference() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ VT& sv_; //!< Reference to the accessed sparse vector.
+ size_t i_; //!< Index of the accessed sparse vector element.
+ //@}
+ //**********************************************************************************************
+
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ void* operator&() const; //!< Address operator (private & undefined)
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( VT );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for a VectorAccessProxy.
+//
+// \param sv Reference to the accessed sparse vector.
+// \param i The index of the accessed sparse vector element.
+*/
+template< typename VT > // Type of the sparse vector
+inline VectorAccessProxy<VT>::VectorAccessProxy( VT& sv, size_t i )
+ : sv_( sv ) // Reference to the accessed sparse vector
+ , i_ ( i ) // Index of the accessed sparse vector element
+{
+ const Iterator_<VT> element( sv_.find( i_ ) );
+ if( element == sv_.end() )
+ sv_.insert( i_, RepresentedType() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for VectorAccessProxy.
+//
+// \param vap Sparse vector access proxy to be copied.
+*/
+template< typename VT > // Type of the sparse vector
+inline VectorAccessProxy<VT>::VectorAccessProxy( const VectorAccessProxy& vap )
+ : sv_( vap.sv_ ) // Reference to the accessed sparse vector
+ , i_ ( vap.i_ ) // Index of the accessed sparse vector element
+{
+ BLAZE_INTERNAL_ASSERT( sv_.find( i_ ) != sv_.end(), "Missing vector element detected" );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The destructor for VectorAccessProxy.
+*/
+template< typename VT > // Type of the sparse vector
+inline VectorAccessProxy<VT>::~VectorAccessProxy()
+{
+ const Iterator_<VT> element( sv_.find( i_ ) );
+ if( element != sv_.end() && isDefault( element->value() ) )
+ sv_.erase( element );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for VectorAccessProxy.
+//
+// \param vap Sparse vector access proxy to be copied.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse vector
+inline const VectorAccessProxy<VT>& VectorAccessProxy<VT>::operator=( const VectorAccessProxy& vap ) const
+{
+ get() = vap.get();
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed sparse vector element.
+//
+// \param list The list to be assigned to the sparse vector element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse vector
+template< typename T > // Type of the right-hand side elements
+inline const VectorAccessProxy<VT>&
+ VectorAccessProxy<VT>::operator=( initializer_list<T> list ) const
+{
+ get() = list;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initializer list assignment to the accessed sparse vector element.
+//
+// \param list The list to be assigned to the sparse vector element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse vector
+template< typename T > // Type of the right-hand side elements
+inline const VectorAccessProxy<VT>&
+ VectorAccessProxy<VT>::operator=( initializer_list< initializer_list<T> > list ) const
+{
+ get() = list;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment to the accessed sparse vector element.
+//
+// \param value The new value of the sparse vector element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse vector
+template< typename T > // Type of the right-hand side value
+inline const VectorAccessProxy<VT>& VectorAccessProxy<VT>::operator=( const T& value ) const
+{
+ get() = value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Addition assignment to the accessed sparse vector element.
+//
+// \param value The right-hand side value to be added to the sparse vector element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse vector
+template< typename T > // Type of the right-hand side value
+inline const VectorAccessProxy<VT>& VectorAccessProxy<VT>::operator+=( const T& value ) const
+{
+ get() += value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subtraction assignment to the accessed sparse vector element.
+//
+// \param value The right-hand side value to be subtracted from the sparse vector element.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse vector
+template< typename T > // Type of the right-hand side value
+inline const VectorAccessProxy<VT>& VectorAccessProxy<VT>::operator-=( const T& value ) const
+{
+ get() -= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Multiplication assignment to the accessed sparse vector element.
+//
+// \param value The right-hand side value for the multiplication.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse vector
+template< typename T > // Type of the right-hand side value
+inline const VectorAccessProxy<VT>& VectorAccessProxy<VT>::operator*=( const T& value ) const
+{
+ get() *= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Division assignment to the accessed sparse vector element.
+//
+// \param value The right-hand side value for the division.
+// \return Reference to the assigned access proxy.
+*/
+template< typename VT > // Type of the sparse vector
+template< typename T > // Type of the right-hand side value
+inline const VectorAccessProxy<VT>& VectorAccessProxy<VT>::operator/=( const T& value ) const
+{
+ get() /= value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returning the value of the accessed sparse vector element.
+//
+// \return Direct/raw reference to the accessed sparse vector element.
+*/
+template< typename VT > // Type of the sparse vector
+inline typename VectorAccessProxy<VT>::RawReference VectorAccessProxy<VT>::get() const noexcept
+{
+ const Iterator_<VT> element( sv_.find( i_ ) );
+ BLAZE_INTERNAL_ASSERT( element != sv_.end(), "Missing vector element detected" );
+ return element->value();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the proxy represents a restricted sparse vector element..
+//
+// \return \a true in case access to the sparse vector element is restricted, \a false if not.
+*/
+template< typename VT > // Type of the sparse vector
+inline bool VectorAccessProxy<VT>::isRestricted() const noexcept
+{
+ return false;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the accessed sparse vector element.
+//
+// \return Direct/raw reference to the accessed sparse vector element.
+*/
+template< typename VT > // Type of the sparse vector
+inline VectorAccessProxy<VT>::operator RawReference() const noexcept
+{
+ return get();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name VectorAccessProxy global functions */
+//@{
+template< typename VT >
+inline void reset( const VectorAccessProxy<VT>& proxy );
+
+template< typename VT >
+inline void clear( const VectorAccessProxy<VT>& proxy );
+
+template< typename VT >
+inline bool isDefault( const VectorAccessProxy<VT>& proxy );
+
+template< typename VT >
+inline bool isReal( const VectorAccessProxy<VT>& proxy );
+
+template< typename VT >
+inline bool isZero( const VectorAccessProxy<VT>& proxy );
+
+template< typename VT >
+inline bool isOne( const VectorAccessProxy<VT>& proxy );
+
+template< typename VT >
+inline bool isnan( const VectorAccessProxy<VT>& proxy );
+
+template< typename VT >
+inline void swap( const VectorAccessProxy<VT>& a, const VectorAccessProxy<VT>& b ) noexcept;
+
+template< typename VT, typename T >
+inline void swap( const VectorAccessProxy<VT>& a, T& b ) noexcept;
+
+template< typename T, typename VT >
+inline void swap( T& a, const VectorAccessProxy<VT>& v ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the represented element to the default initial values.
+// \ingroup sparse_vector
+//
+// \param proxy The given access proxy.
+// \return void
+*/
+template< typename VT >
+inline void reset( const VectorAccessProxy<VT>& proxy )
+{
+ using blaze::reset;
+
+ reset( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the represented element.
+// \ingroup sparse_vector
+//
+// \param proxy The given access proxy.
+// \return void
+*/
+template< typename VT >
+inline void clear( const VectorAccessProxy<VT>& proxy )
+{
+ using blaze::clear;
+
+ clear( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is in default state.
+// \ingroup sparse_vector
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in default state, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is in default state.
+// In case it is in default state, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename VT >
+inline bool isDefault( const VectorAccessProxy<VT>& proxy )
+{
+ using blaze::isDefault;
+
+ return isDefault( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the vector element represents a real number.
+// \ingroup sparse_vector
+//
+// \param proxy The given access proxy.
+// \return \a true in case the vector element represents a real number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the a
+// real number. In case the element is of built-in type, the function returns \a true. In case
+// the element is of complex type, the function returns \a true if the imaginary part is equal
+// to 0. Otherwise it returns \a false.
+*/
+template< typename VT >
+inline bool isReal( const VectorAccessProxy<VT>& proxy )
+{
+ using blaze::isReal;
+
+ return isReal( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 0.
+// \ingroup sparse_vector
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 0, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 0. In case it is 0, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename VT >
+inline bool isZero( const VectorAccessProxy<VT>& proxy )
+{
+ using blaze::isZero;
+
+ return isZero( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is 1.
+// \ingroup sparse_vector
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is 1, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy represents the numeric
+// value 1. In case it is 1, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename VT >
+inline bool isOne( const VectorAccessProxy<VT>& proxy )
+{
+ using blaze::isOne;
+
+ return isOne( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the represented element is not a number.
+// \ingroup sparse_vector
+//
+// \param proxy The given access proxy.
+// \return \a true in case the represented element is in not a number, \a false otherwise.
+//
+// This function checks whether the element represented by the access proxy is not a number (NaN).
+// In case it is not a number, the function returns \a true, otherwise it returns \a false.
+*/
+template< typename VT >
+inline bool isnan( const VectorAccessProxy<VT>& proxy )
+{
+ using blaze::isnan;
+
+ return isnan( proxy.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two access proxies.
+// \ingroup sparse_vector
+//
+// \param a The first access proxy to be swapped.
+// \param b The second access proxy to be swapped.
+// \return void
+*/
+template< typename VT >
+inline void swap( const VectorAccessProxy<VT>& a, const VectorAccessProxy<VT>& b ) noexcept
+{
+ using std::swap;
+
+ swap( a.get(), b.get() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of an access proxy with another element.
+// \ingroup sparse_vector
+//
+// \param a The access proxy to be swapped.
+// \param b The other element to be swapped.
+// \return void
+*/
+template< typename VT, typename T >
+inline void swap( const VectorAccessProxy<VT>& a, T& b ) noexcept
+{
+ using std::swap;
+
+ swap( a.get(), b );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of an access proxy with another element.
+// \ingroup sparse_vector
+//
+// \param a The other element to be swapped.
+// \param b The access proxy to be swapped.
+// \return void
+*/
+template< typename T, typename VT >
+inline void swap( T& a, const VectorAccessProxy<VT>& b ) noexcept
+{
+ using std::swap;
+
+ swap( a, b.get() );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/AddExprTrait.h b/src/cpu/blaze/math/traits/AddExprTrait.h
new file mode 100644
index 00000000..6ca7b84f
--- /dev/null
+++ b/src/cpu/blaze/math/traits/AddExprTrait.h
@@ -0,0 +1,224 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/AddExprTrait.h
+// \brief Header file for the AddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_ADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_ADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/DMatDMatAddExprTrait.h>
+#include <blaze/math/traits/DMatSMatAddExprTrait.h>
+#include <blaze/math/traits/DMatTDMatAddExprTrait.h>
+#include <blaze/math/traits/DMatTSMatAddExprTrait.h>
+#include <blaze/math/traits/DVecDVecAddExprTrait.h>
+#include <blaze/math/traits/DVecSVecAddExprTrait.h>
+#include <blaze/math/traits/SMatDMatAddExprTrait.h>
+#include <blaze/math/traits/SMatSMatAddExprTrait.h>
+#include <blaze/math/traits/SMatTDMatAddExprTrait.h>
+#include <blaze/math/traits/SMatTSMatAddExprTrait.h>
+#include <blaze/math/traits/SVecDVecAddExprTrait.h>
+#include <blaze/math/traits/SVecSVecAddExprTrait.h>
+#include <blaze/math/traits/TDMatDMatAddExprTrait.h>
+#include <blaze/math/traits/TDMatSMatAddExprTrait.h>
+#include <blaze/math/traits/TDMatTDMatAddExprTrait.h>
+#include <blaze/math/traits/TDMatTSMatAddExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecAddExprTrait.h>
+#include <blaze/math/traits/TDVecTSVecAddExprTrait.h>
+#include <blaze/math/traits/TSMatDMatAddExprTrait.h>
+#include <blaze/math/traits/TSMatSMatAddExprTrait.h>
+#include <blaze/math/traits/TSMatTDMatAddExprTrait.h>
+#include <blaze/math/traits/TSMatTSMatAddExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecAddExprTrait.h>
+#include <blaze/math/traits/TSVecTSVecAddExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of an addition expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of an addition expression
+// between scalars, vectors, and matrices. Given the two types \a T1 and \a T2, which must
+// either be scalar, vector, or matrix types, the nested type \a Type corresponds to the
+// resulting return type. In case the types of \a T1 or \a T2 don't fit or if the two types
+// cannot be added, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename T1 // Type of the left-hand side addition operand
+ , typename T2 > // Type of the right-hand side addition operand
+struct AddExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T1>
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T1>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsRowMajorMatrix<T2>
+ , DMatDMatAddExprTrait<T1,T2>
+ , DMatTDMatAddExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TDMatDMatAddExprTrait<T1,T2>
+ , TDMatTDMatAddExprTrait<T1,T2> > >
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsRowMajorMatrix<T2>
+ , DMatSMatAddExprTrait<T1,T2>
+ , DMatTSMatAddExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TDMatSMatAddExprTrait<T1,T2>
+ , TDMatTSMatAddExprTrait<T1,T2> > > >
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsRowMajorMatrix<T2>
+ , SMatDMatAddExprTrait<T1,T2>
+ , SMatTDMatAddExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TSMatDMatAddExprTrait<T1,T2>
+ , TSMatTDMatAddExprTrait<T1,T2> > >
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsRowMajorMatrix<T2>
+ , SMatSMatAddExprTrait<T1,T2>
+ , SMatTSMatAddExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TSMatSMatAddExprTrait<T1,T2>
+ , TSMatTSMatAddExprTrait<T1,T2> > > > >
+ , Failure >
+ , If_< IsVector<T1>
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T1>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T1>
+ , If_< IsRowVector<T2>
+ , TDVecTDVecAddExprTrait<T1,T2>
+ , Failure >
+ , If_< IsRowVector<T2>
+ , Failure
+ , DVecDVecAddExprTrait<T1,T2> > >
+ , If_< IsRowVector<T1>
+ , If_< IsRowVector<T2>
+ , TDVecTSVecAddExprTrait<T1,T2>
+ , Failure >
+ , If_< IsRowVector<T2>
+ , Failure
+ , DVecSVecAddExprTrait<T1,T2> > > >
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T1>
+ , If_< IsRowVector<T2>
+ , TSVecTDVecAddExprTrait<T1,T2>
+ , Failure >
+ , If_< IsRowVector<T2>
+ , Failure
+ , SVecDVecAddExprTrait<T1,T2> > >
+ , If_< IsRowVector<T1>
+ , If_< IsRowVector<T2>
+ , TSVecTSVecAddExprTrait<T1,T2>
+ , Failure >
+ , If_< IsRowVector<T2>
+ , Failure
+ , SVecSVecAddExprTrait<T1,T2> > > > >
+ , Failure >
+ , If_< IsNumeric<T1>
+ , If_< IsNumeric<T2>
+ , AddTrait<T1,T2>
+ , Failure >
+ , Failure > > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , AddExprTrait< Decay_<T1>, Decay_<T2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the AddExprTrait class template.
+// \ingroup math_traits
+//
+// The AddExprTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the AddExprTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename AddExprTrait<T1,T2>::Type;
+ using Type2 = AddExprTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side addition operand
+ , typename T2 > // Type of the right-hand side addition operand
+using AddExprTrait_ = typename AddExprTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/AddTrait.h b/src/cpu/blaze/math/traits/AddTrait.h
new file mode 100644
index 00000000..a18ff3ac
--- /dev/null
+++ b/src/cpu/blaze/math/traits/AddTrait.h
@@ -0,0 +1,236 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/AddTrait.h
+// \brief Header file for the addition trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_ADDTRAIT_H_
+#define _BLAZE_MATH_TRAITS_ADDTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/CommonType.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the AddTrait class.
+// \ingroup math_traits
+//
+// \section addtrait_general General
+//
+// The AddTrait class template offers the possibility to select the resulting data type of a
+// generic addition operation between the two given types \a T1 and \a T2. AddTrait defines
+// the nested type \a Type, which represents the resulting data type of the addition. In case
+// the two types \a T1 and \a T2 cannot be added, a compilation error is created. Note that
+// \c const and \c volatile qualifiers and reference modifiers are generally ignored.
+//
+// Per default, AddTrait supports all built-in data types. Additionally, the Blaze library
+// provides appropriate specializations for the following user-defined arithmetic types:
+//
+// <ul>
+// <li>std::complex</li>
+// <li>blaze::StaticVector</li>
+// <li>blaze::HybridVector</li>
+// <li>blaze::DynamicVector</li>
+// <li>blaze::CustomVector</li>
+// <li>blaze::CompressedVector</li>
+// <li>blaze::StaticMatrix</li>
+// <li>blaze::HybridMatrix</li>
+// <li>blaze::DynamicMatrix</li>
+// <li>blaze::CustomMatrix</li>
+// <li>blaze::CompressedMatrix</li>
+// <li>blaze::SymmetricMatrix</li>
+// <li>blaze::HermitianMatrix</li>
+// <li>blaze::LowerMatrix</li>
+// <li>blaze::UniLowerMatrix</li>
+// <li>blaze::StrictlyLowerMatrix</li>
+// <li>blaze::UpperMatrix</li>
+// <li>blaze::UniUpperMatrix</li>
+// <li>blaze::StrictlyUpperMatrix</li>
+// <li>blaze::DiagonalMatrix</li>
+// </ul>
+//
+//
+// \n \section addtrait_specializations Creating custom specializations
+//
+// AddTrait is guaranteed to work for all data types that provide an addition operator (i.e.
+// \c operator+). In order to add support for user-defined data types that either don't provide
+// an addition operator or whose addition operator returns a proxy object instead of a concrete
+// type (as it is for instance common in expression template libraries) it is possible to
+// specialize the AddTrait template. The following example shows the according specialization
+// for the addition between two dynamic column vectors:
+
+ \code
+ template< typename T1, typename T2 >
+ struct AddTrait< DynamicVector<T1,columnVector>, DynamicVector<T2,columnVector> >
+ {
+ typedef DynamicVector< typename AddTrait<T1,T2>::Type, columnVector > Type;
+ };
+ \endcode
+
+// \n \section addtrait_examples Examples
+//
+// The following example demonstrates the use of the AddTrait template, where depending on
+// the two given data types the resulting data type is selected:
+
+ \code
+ template< typename T1, typename T2 > // The two generic types
+ typename AddTrait<T1,T2>::Type // The resulting generic return type
+ add( const T1& t1, const T2& t2 ) //
+ { // The function 'add' returns the sum
+ return t1 + t2; // of the two given values
+ } //
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct AddTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type1 = Decay_<T1>;
+ using Type2 = Decay_<T2>;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct AddType { using Type = decltype( std::declval<Type1>() + std::declval<Type2>() ); };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , AddTrait<Type1,Type2>
+ , AddType >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the AddTrait class template for a complex and a built-in type.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct AddTrait< complex<T1>, T2, EnableIf_< IsBuiltin<T2> > >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< complex<T1> , T2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the AddTrait class template for a built-in and a complex type.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct AddTrait< T1, complex<T2>, EnableIf_< IsBuiltin<T1> > >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< T1, complex<T2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the AddTrait class template for two complex types.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct AddTrait< complex<T1>, complex<T2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< complex<T1>, complex<T2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the AddTrait class template.
+// \ingroup math_traits
+//
+// The AddTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the AddTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename AddTrait<T1,T2>::Type;
+ using Type2 = AddTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1, typename T2 >
+using AddTrait_ = typename AddTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/CTransExprTrait.h b/src/cpu/blaze/math/traits/CTransExprTrait.h
new file mode 100644
index 00000000..80bb2f58
--- /dev/null
+++ b/src/cpu/blaze/math/traits/CTransExprTrait.h
@@ -0,0 +1,148 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/CTransExprTrait.h
+// \brief Header file for the CTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_CTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_CTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DMatCTransExprTrait.h>
+#include <blaze/math/traits/DVecCTransExprTrait.h>
+#include <blaze/math/traits/SMatCTransExprTrait.h>
+#include <blaze/math/traits/SVecCTransExprTrait.h>
+#include <blaze/math/traits/TDMatCTransExprTrait.h>
+#include <blaze/math/traits/TDVecCTransExprTrait.h>
+#include <blaze/math/traits/TSMatCTransExprTrait.h>
+#include <blaze/math/traits/TSVecCTransExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of a conjugate transpose expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a conjugate transpose
+// expression. Given the type \a T, which must either be a vector or matrix type, the nested
+// type \a Type corresponds to the resulting return type. In case the type of \a T doesn't fit
+// or if no conjugate transpose operation exists for the type, the resulting data type \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename T > // Type of the conjugate transpose operand
+struct CTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T>
+ , If_< IsDenseMatrix<T>
+ , If_< IsRowMajorMatrix<T>
+ , DMatCTransExprTrait<T>
+ , TDMatCTransExprTrait<T> >
+ , If_< IsRowMajorMatrix<T>
+ , SMatCTransExprTrait<T>
+ , TSMatCTransExprTrait<T> > >
+ , If_< IsVector<T>
+ , If_< IsDenseVector<T>
+ , If_< IsRowVector<T>
+ , TDVecCTransExprTrait<T>
+ , DVecCTransExprTrait<T> >
+ , If_< IsRowVector<T>
+ , TSVecCTransExprTrait<T>
+ , SVecCTransExprTrait<T> > >
+ , Failure > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , CTransExprTrait< Decay_<T> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the CTransExprTrait class template.
+// \ingroup math_traits
+//
+// The CTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the CTransExprTrait class template. For instance, given the type \a T the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename CTransExprTrait<T>::Type;
+ using Type2 = CTransExprTrait_<T>;
+ \endcode
+*/
+template< typename T > // Type of the conjugate transpose operand
+using CTransExprTrait_ = typename CTransExprTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/ColumnExprTrait.h b/src/cpu/blaze/math/traits/ColumnExprTrait.h
new file mode 100644
index 00000000..25b9c8cc
--- /dev/null
+++ b/src/cpu/blaze/math/traits/ColumnExprTrait.h
@@ -0,0 +1,138 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/ColumnExprTrait.h
+// \brief Header file for the ColumnExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_COLUMNEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_COLUMNEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/views/Forward.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type type of a column operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a column operation. Given the
+// dense or sparse matrix type \a MT, the nested type \a Type corresponds to the resulting return
+// type. In case the given type is neither a dense nor a sparse matrix type, the resulting data
+// type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the matrix operand
+struct ColumnExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Result*******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T >
+ struct Result {
+ using Type = Column<T,IsColumnMajorMatrix<T>::value,IsDenseMatrix<T>::value,IsSymmetric<T>::value>;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = RemoveReference_<MT>;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsComputation<Tmp>, IsTransExpr<Tmp> >
+ , If_< Or< IsConst<Tmp>, IsVolatile<Tmp> >
+ , ColumnExprTrait< RemoveCV_<Tmp> >
+ , Failure >
+ , If_< IsMatrix<Tmp>
+ , Result<Tmp>
+ , Failure >
+ >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the ColumnExprTrait type trait.
+// \ingroup math_traits
+//
+// The ColumnExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the ColumnExprTrait class template. For instance, given the matrix type \a MT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename ColumnExprTrait<MT>::Type;
+ using Type2 = ColumnExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the matrix operand
+using ColumnExprTrait_ = typename ColumnExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/ColumnTrait.h b/src/cpu/blaze/math/traits/ColumnTrait.h
new file mode 100644
index 00000000..e7872b98
--- /dev/null
+++ b/src/cpu/blaze/math/traits/ColumnTrait.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/ColumnTrait.h
+// \brief Header file for the column trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_COLUMNTRAIT_H_
+#define _BLAZE_MATH_TRAITS_COLUMNTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the ColumnTrait class.
+// \ingroup math_traits
+//
+// \section columntrait_general General
+//
+// The ColumnTrait class template offers the possibility to select the resulting data type when
+// creating a view on a specific column of a dense or sparse matrix. ColumnTrait defines the nested
+// type \a Type, which represents the resulting data type of the column operation. In case the
+// given data type is not a dense or sparse matrix type, the resulting data type \a Type is
+// set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and reference modifiers
+// are generally ignored.
+//
+// Per default, the ColumnTrait template only supports the following matrix types:
+//
+// <ul>
+// <li>blaze::StaticMatrix</li>
+// <li>blaze::HybridMatrix</li>
+// <li>blaze::DynamicMatrix</li>
+// <li>blaze::CustomMatrix</li>
+// <li>blaze::CompressedMatrix</li>
+// <li>blaze::Submatrix</li>
+// </ul>
+//
+//
+// \section columntrait_specializations Creating custom specializations
+//
+// It is possible to specialize the ColumnTrait template for additional user-defined matrix types.
+// The following example shows the according specialization for the DynamicMatrix class template:
+
+ \code
+ template< typename T1, bool SO >
+ struct ColumnTrait< DynamicMatrix<T1,SO> >
+ {
+ typedef DynamicVector<T1,true> Type;
+ };
+ \endcode
+
+// \n \section columntrait_examples Examples
+//
+// The following example demonstrates the use of the ColumnTrait template, where depending on
+// the given matrix type the resulting column type is selected:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of the column type of a column-major dynamic matrix
+ typedef blaze::DynamicMatrix<int,columnMajor> MatrixType1;
+ typedef typename ColumnTrait<MatrixType1>::Type ColumnType1;
+
+ // Definition of the column type of the row-major static matrix
+ typedef blaze::StaticMatrix<int,3UL,3UL,rowMajor> MatrixType2;
+ typedef typename ColumnTrait<MatrixType2>::Type ColumnType2;
+ \endcode
+*/
+template< typename MT > // Type of the matrix
+struct ColumnTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , ColumnTrait< Decay_<MT> >
+ , Failure >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the ColumnTrait type trait.
+// \ingroup math_traits
+//
+// The ColumnTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the ColumnTrait class template. For instance, given the matrix type \a MT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename ColumnTrait<MT>::Type;
+ using Type2 = ColumnTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the matrix
+using ColumnTrait_ = typename ColumnTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/CrossExprTrait.h b/src/cpu/blaze/math/traits/CrossExprTrait.h
new file mode 100644
index 00000000..9fb6e8db
--- /dev/null
+++ b/src/cpu/blaze/math/traits/CrossExprTrait.h
@@ -0,0 +1,155 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/CrossExprTrait.h
+// \brief Header file for the CrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_CROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_CROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DVecDVecCrossExprTrait.h>
+#include <blaze/math/traits/DVecSVecCrossExprTrait.h>
+#include <blaze/math/traits/SVecDVecCrossExprTrait.h>
+#include <blaze/math/traits/SVecSVecCrossExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecCrossExprTrait.h>
+#include <blaze/math/traits/TDVecTSVecCrossExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecCrossExprTrait.h>
+#include <blaze/math/traits/TSVecTSVecCrossExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of a cross product expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a cross product expression.
+// Given the two types \a T1 and \a T2, which must be dense or sparse column vectors, the nested
+// type \a Type corresponds to the resulting return type. In case the types of \a T1 or \a T2
+// don't fit or if the two types cannot be used in a cross product, the resulting data type
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename T1 // Type of the left-hand side cross product operand
+ , typename T2 > // Type of the right-hand side cross product operand
+struct CrossExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsVector<T1>
+ , If_< IsVector<T2>
+ , If_< IsColumnVector<T1>
+ , If_< IsColumnVector<T2>
+ , If_< IsDenseVector<T1>
+ , If_< IsDenseVector<T2>
+ , DVecDVecCrossExprTrait<T1,T2>
+ , DVecSVecCrossExprTrait<T1,T2> >
+ , If_< IsDenseVector<T2>
+ , SVecDVecCrossExprTrait<T1,T2>
+ , SVecSVecCrossExprTrait<T1,T2> > >
+ , Failure >
+ , If_< IsRowVector<T2>
+ , If_< IsDenseVector<T1>
+ , If_< IsDenseVector<T2>
+ , TDVecTDVecCrossExprTrait<T1,T2>
+ , TDVecTSVecCrossExprTrait<T1,T2> >
+ , If_< IsDenseVector<T2>
+ , TSVecTDVecCrossExprTrait<T1,T2>
+ , TSVecTSVecCrossExprTrait<T1,T2> > >
+ , Failure > >
+ , Failure >
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , CrossExprTrait< Decay_<T1>, Decay_<T2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the CrossExprTrait class template.
+// \ingroup math_traits
+//
+// The CrossExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the CrossExprTrait class template. For instance, given the types \a T1 and \a T2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename CrossExprTrait<T1,T2>::Type;
+ using Type2 = CrossExprTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side cross product operand
+ , typename T2 > // Type of the right-hand side cross product operand
+using CrossExprTrait_ = typename CrossExprTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/CrossTrait.h b/src/cpu/blaze/math/traits/CrossTrait.h
new file mode 100644
index 00000000..7356cd91
--- /dev/null
+++ b/src/cpu/blaze/math/traits/CrossTrait.h
@@ -0,0 +1,140 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/CrossTrait.h
+// \brief Header file for the cross product trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_CROSSTRAIT_H_
+#define _BLAZE_MATH_TRAITS_CROSSTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the CrossTrait class.
+// \ingroup math_traits
+//
+// \section crosstrait_general General
+//
+// The CrossTrait class template offers the possibility to select the resulting data type of
+// a generic cross product operation between the two given types \a T1 and \a T2. CrossTrait
+// defines the nested type \a Type, which represents the resulting data type of the cross
+// product. In case \a T1 and \a T2 cannot be combined in a cross product, the resulting data
+// type \a Type is set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and
+// reference modifiers are generally ignored.
+//
+// Since the cross product is only defined for 3-dimensional vectors, the CrossTrait template
+// only supports the following vector types:
+//
+// <ul>
+// <li>blaze::StaticVector</li>
+// <li>blaze::DynamicVector</li>
+// <li>blaze::CompressedVector</li>
+// </ul>
+//
+//
+// \n \section crosstrait_specializations Creating custom specializations
+//
+// It is possible to specialize the CrossTrait template for additional user-defined data types.
+// The following example shows the according specialization for the cross product between two
+// static column vectors:
+
+ \code
+ template< typename T1, typename T2 >
+ struct CrossTrait< StaticVector<T1,3UL,false>, StaticVector<T2,3UL,false> >
+ {
+ typedef StaticVector< typename SubTrait< typename MultTrait<T1,T2>::Type
+ , typename MultTrait<T1,T2>::Type >::Type, 3UL, false > Type;
+ };
+ \endcode
+
+// \n \section crosstrait_examples Examples
+//
+// The following example demonstrates the use of the CrossTrait template, where depending on
+// the two given data types the resulting data type is selected:
+
+ \code
+ template< typename T1, typename T2 > // The two generic types
+ typename CrossTrait<T1,T2>::Type // The resulting generic return type
+ cross( T1 t1, T2 t2 ) //
+ { // The function 'cross' returns the cross
+ return t1 % t2; // product of the two given values
+ } //
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+struct CrossTrait
+{
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = INVALID_TYPE;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the CrossTrait class template.
+// \ingroup math_traits
+//
+// The CrossTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the CrossTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename CrossTrait<T1,T2>::Type;
+ using Type2 = CrossTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1, typename T2 >
+using CrossTrait_ = typename CrossTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatCTransExprTrait.h b/src/cpu/blaze/math/traits/DMatCTransExprTrait.h
new file mode 100644
index 00000000..9ec773c9
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatCTransExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatCTransExprTrait.h
+// \brief Header file for the DMatCTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATCTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATCTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/traits/DMatForEachExprTrait.h>
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix conjugate transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix conjugate transpose operation. Given the row-major dense matrix type \a MT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a MT is not
+// a row-major dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct DMatCTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef If_< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatTransExprTrait< DMatForEachExprTrait_<MT,Conj> >
+ , Failure > Tmp;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , DMatCTransExprTrait< Decay_<MT> >
+ , Tmp >::Type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatCTransExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatCTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DMatCTransExprTrait class template. For instance, given the row-major dense
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DMatCTransExprTrait<MT>::Type;
+ using Type2 = DMatCTransExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using DMatCTransExprTrait_ = typename DMatCTransExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatDMatAddExprTrait.h b/src/cpu/blaze/math/traits/DMatDMatAddExprTrait.h
new file mode 100644
index 00000000..879b81d7
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatDMatAddExprTrait.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatDMatAddExprTrait.h
+// \brief Header file for the DMatDMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATDMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATDMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/dense matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/dense matrix addition. Given the two row-major dense matrix types \a MT1 and \a MT2,
+// the nested type \a Type corresponds to the resulting expression type. In case either \a MT1
+// or \a MT2 is not a row-major dense matrix, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct DMatDMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef If< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , DMatDMatAddExpr<MT1,MT2,false>
+ , INVALID_TYPE > Tmp;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatDMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatDMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatDMatAddExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatDMatAddExprTrait class template. For instance, given the row-major
+// dense matrix types \a MT1 and \a MT2 the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DMatDMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatDMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using DMatDMatAddExprTrait_ = typename DMatDMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatDMatMultExprTrait.h b/src/cpu/blaze/math/traits/DMatDMatMultExprTrait.h
new file mode 100644
index 00000000..fb6148f5
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatDMatMultExprTrait.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatDMatMultExprTrait.h
+// \brief Header file for the DMatDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/dense matrix multiplication. Given the two row-major dense matrix types \a MT1 and
+// \a MT2, the nested type \a Type corresponds to the resulting expression type. In case either
+// \a MT1 or \a MT2 is not a row-major dense matrix, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct DMatDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , DMatDMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatDMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatDMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatDMatMultExprTrait class template. For instance, given the row-major
+// dense matrix types \a MT1 and \a MT2 the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DMatDMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatDMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using DMatDMatMultExprTrait_ = typename DMatDMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatDMatSubExprTrait.h b/src/cpu/blaze/math/traits/DMatDMatSubExprTrait.h
new file mode 100644
index 00000000..8dbfeec2
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatDMatSubExprTrait.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatDMatSubExprTrait.h
+// \brief Header file for the DMatDMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATDMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATDMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/dense matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/dense matrix subtraction. Given the two row-major dense matrix types \a MT1 and
+// \a MT2, the nested type \a Type corresponds to the resulting expression type. In case either
+// \a MT1 or \a MT2 is not a row-major dense matrix, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct DMatDMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , DMatDMatSubExpr<MT1,MT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatDMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatDMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatDMatSubExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatDMatSubExprTrait class template. For instance, given the row-major
+// dense matrix types \a MT1 and \a MT2 the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DMatDMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatDMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using DMatDMatSubExprTrait_ = typename DMatDMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatDVecMultExprTrait.h b/src/cpu/blaze/math/traits/DMatDVecMultExprTrait.h
new file mode 100644
index 00000000..0fedb150
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatDVecMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatDVecMultExprTrait.h
+// \brief Header file for the DMatDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/dense vector multiplication. Given the row-major dense matrix type \a MT and the
+// non-transpose dense vector type \a VT, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT is not a row-major dense matrix type or \a VT is not
+// a non-transpose dense vector type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side row-major dense matrix
+ , typename VT > // Type of the right-hand side non-transpose dense vector
+struct DMatDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , DMatDVecMultExpr<MT,VT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , DMatDVecMultExprTrait< Decay_<MT>, Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatDVecMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatDVecMultExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT and the non-transpose dense vector type \a VT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatDVecMultExprTrait<MT,VT>::Type;
+ using Type2 = DMatDVecMultExprTrait_<MT,VT>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side row-major dense matrix
+ , typename VT > // Type of the right-hand side non-transpose dense vector
+using DMatDVecMultExprTrait_ = typename DMatDVecMultExprTrait<MT,VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatEvalExprTrait.h b/src/cpu/blaze/math/traits/DMatEvalExprTrait.h
new file mode 100644
index 00000000..908c5e25
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatEvalExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatEvalExprTrait.h
+// \brief Header file for the DMatEvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATEVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATEVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix evaluation operation. Given the row-major dense matrix type \a MT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a MT is not a
+// row-major dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct DMatEvalExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatEvalExpr<MT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , DMatEvalExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatEvalExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatEvalExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DMatEvalExprTrait class template. For instance, given the row-major dense matrix
+// type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DMatEvalExprTrait<MT>::Type;
+ using Type2 = DMatEvalExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using DMatEvalExprTrait_ = typename DMatEvalExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatForEachExprTrait.h b/src/cpu/blaze/math/traits/DMatForEachExprTrait.h
new file mode 100644
index 00000000..d2214d8a
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatForEachExprTrait.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatForEachExprTrait.h
+// \brief Header file for the DMatForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATFOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATFOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix custom operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense matrix
+// custom operation. Given the row-major dense matrix type \a MT and the custom operation type
+// \a OP, the nested type \a Type corresponds to the resulting expression type. In case \a MT is
+// not a row-major dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the dense matrix
+ , typename OP > // Type of the custom operation
+struct DMatForEachExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef If< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatForEachExpr<MT,OP,false>
+ , INVALID_TYPE > Tmp;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , DMatForEachExprTrait< Decay_<MT>, OP >
+ , Tmp >::Type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatForEachExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatForEachExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT and the custom operation type \a OP the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename DMatForEachExprTrait<MT,OP>::Type;
+ using Type2 = DMatForEachExprTrait_<MT,OP>;
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , typename OP > // Type of the custom operation
+using DMatForEachExprTrait_ = typename DMatForEachExprTrait<MT,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatInvExprTrait.h b/src/cpu/blaze/math/traits/DMatInvExprTrait.h
new file mode 100644
index 00000000..016ad2f7
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatInvExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatInvExprTrait.h
+// \brief Header file for the DMatInvExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATINVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATINVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix inversion operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix inversion operation. Given the row-major dense matrix type \a MT, the nested type
+// \a Type corresponds to the resulting expression type. In case \a MT is not a row-major
+// dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct DMatInvExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatInvExpr<MT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , DMatInvExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatInvExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatInvExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DMatInvExprTrait class template. For instance, given the row-major dense matrix
+// type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DMatInvExprTrait<MT>::Type;
+ using Type2 = DMatInvExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using DMatInvExprTrait_ = typename DMatInvExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatSMatAddExprTrait.h b/src/cpu/blaze/math/traits/DMatSMatAddExprTrait.h
new file mode 100644
index 00000000..4c9ec4fc
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatSMatAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatSMatAddExprTrait.h
+// \brief Header file for the DMatSMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATSMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATSMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/sparse matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/sparse matrix addition. Given the row-major dense matrix type \a MT1 and the row-major
+// sparse matrix type \a MT2, the nested type \a Type corresponds to the resulting expression
+// type. In case either \a MT1 is not a row-major dense matrix type or \a MT2 is not a row-major
+// sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct DMatSMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , DMatSMatAddExpr<MT1,MT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatSMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatSMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatSMatAddExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatSMatAddExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the row-major sparse matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatSMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatSMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using DMatSMatAddExprTrait_ = typename DMatSMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatSMatMultExprTrait.h b/src/cpu/blaze/math/traits/DMatSMatMultExprTrait.h
new file mode 100644
index 00000000..52ae45c2
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatSMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatSMatMultExprTrait.h
+// \brief Header file for the DMatSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/sparse matrix multiplication. Given the row-major dense matrix type \a MT1 and
+// the row-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major dense matrix type or
+// \a MT2 is not a row-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct DMatSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , DMatSMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatSMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatSMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatSMatMultExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the row-major sparse matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatSMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatSMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using DMatSMatMultExprTrait_ = typename DMatSMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatSMatSubExprTrait.h b/src/cpu/blaze/math/traits/DMatSMatSubExprTrait.h
new file mode 100644
index 00000000..a7fe5282
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatSMatSubExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatSMatSubExprTrait.h
+// \brief Header file for the DMatSMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATSMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATSMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/sparse matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/sparse matrix subtraction. Given the row-major dense matrix type \a MT1 and the
+// row-major sparse matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a row-major dense matrix type or \a MT2 is
+// not a row-major sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct DMatSMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , DMatSMatSubExpr<MT1,MT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatSMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatSMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatSMatSubExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatSMatSubExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the row-major sparse matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatSMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatSMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using DMatSMatSubExprTrait_ = typename DMatSMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatSVecMultExprTrait.h b/src/cpu/blaze/math/traits/DMatSVecMultExprTrait.h
new file mode 100644
index 00000000..b5382619
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatSVecMultExprTrait.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatSVecMultExprTrait.h
+// \brief Header file for the DMatSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/sparse vector multiplication. Given the row-major dense matrix type \a MT and the
+// non-transpose sparse vector type \a VT, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT is not a row-major dense matrix type or \a VT is not
+// a non-transpose sparse vector type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side row-major dense matrix
+ , typename VT > // Type of the right-hand side non-transpose sparse vector
+struct DMatSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT> , IsRowMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , If_< IsSymmetric<MT>
+ , TDMatSVecMultExpr< DMatTransExprTrait_<MT>, VT >
+ , DMatSVecMultExpr<MT,VT> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , DMatSVecMultExprTrait< Decay_<MT>, Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatSVecMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatSVecMultExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT and the non-transpose sparse vector type \a VT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatSVecMultExprTrait<MT,VT>::Type;
+ using Type2 = DMatSVecMultExprTrait_<MT,VT>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side row-major dense matrix
+ , typename VT > // Type of the right-hand side non-transpose sparse vector
+using DMatSVecMultExprTrait_ = typename DMatSVecMultExprTrait<MT,VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatScalarDivExprTrait.h b/src/cpu/blaze/math/traits/DMatScalarDivExprTrait.h
new file mode 100644
index 00000000..5e6381a4
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatScalarDivExprTrait.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatScalarDivExprTrait.h
+// \brief Header file for the DMatScalarDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATSCALARDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATSCALARDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the DMatScalarDivExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST
+ , bool Condition >
+struct DMatScalarDivExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<MT> >, IsBuiltin<ST> >
+ , DivTrait_< UnderlyingBuiltin_<MT>, ST >
+ , DivTrait_< UnderlyingNumeric_<MT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< IsInvertible<ScalarType>
+ , DMatScalarMultExpr<MT,ScalarType,false>
+ , DMatScalarDivExpr<MT,ScalarType,false> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the DMatScalarDivExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST >
+struct DMatScalarDivExprTraitHelper<MT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/scalar division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/scalar division. Given the row-major dense matrix type \a MT and the scalar type
+// \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a MT is not a row-major dense matrix type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar
+struct DMatScalarDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , DMatScalarDivExprTrait< Decay_<MT>, Decay_<ST> >
+ , DMatScalarDivExprTraitHelper<MT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatScalarDivExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatScalarDivExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatScalarDivExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT and the scalar type \a ST the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename DMatScalarDivExprTrait<MT,ST>::Type;
+ using Type2 = DMatScalarDivExprTrait_<MT,ST>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar
+using DMatScalarDivExprTrait_ = typename DMatScalarDivExprTrait<MT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatScalarMultExprTrait.h b/src/cpu/blaze/math/traits/DMatScalarMultExprTrait.h
new file mode 100644
index 00000000..61a836ba
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatScalarMultExprTrait.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatScalarMultExprTrait.h
+// \brief Header file for the DMatScalarMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATSCALARMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATSCALARMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the DMatScalarMultExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST
+ , bool Condition >
+struct DMatScalarMultExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<MT> >, IsBuiltin<ST> >
+ , MultTrait_< UnderlyingBuiltin_<MT>, ST >
+ , MultTrait_< UnderlyingNumeric_<MT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = DMatScalarMultExpr<MT,ScalarType,false>;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the DMatScalarMultExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST >
+struct DMatScalarMultExprTraitHelper<MT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/scalar multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/scalar multiplication. Given the row-major dense matrix type \a MT and the scalar
+// type \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a MT is not a row-major dense matrix type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar
+struct DMatScalarMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , DMatScalarMultExprTrait< Decay_<MT>, Decay_<ST> >
+ , DMatScalarMultExprTraitHelper<MT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatScalarMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatScalarMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatScalarMultExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT and the scalar type \a ST the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename DMatScalarMultExprTrait<MT,ST>::Type;
+ using Type2 = DMatScalarMultExprTrait_<MT,ST>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar
+using DMatScalarMultExprTrait_ = typename DMatScalarMultExprTrait<MT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatSerialExprTrait.h b/src/cpu/blaze/math/traits/DMatSerialExprTrait.h
new file mode 100644
index 00000000..502663d1
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatSerialExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatSerialExprTrait.h
+// \brief Header file for the DMatSerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATSERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATSERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix serial evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix serial evaluation operation. Given the row-major dense matrix type \a MT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a MT is not a row-major
+// dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct DMatSerialExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatSerialExpr<MT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , DMatSerialExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatSerialExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatSerialExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DMatSerialExprTrait class template. For instance, given the row-major dense matrix
+// type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DMatSerialExprTrait<MT>::Type;
+ using Type2 = DMatSerialExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using DMatSerialExprTrait_ = typename DMatSerialExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatTDMatAddExprTrait.h b/src/cpu/blaze/math/traits/DMatTDMatAddExprTrait.h
new file mode 100644
index 00000000..38e35cfd
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatTDMatAddExprTrait.h
@@ -0,0 +1,131 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatTDMatAddExprTrait.h
+// \brief Header file for the DMatTDMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATTDMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATTDMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/transpose dense matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/transpose dense matrix addition. Given the row-major dense matrix type \a MT1 and
+// the column-major dense matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major dense matrix type or
+// \a MT2 is not a column-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct DMatTDMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , If_< IsSymmetric<MT2>
+ , DMatDMatAddExpr< MT1, TDMatTransExprTrait_<MT2>, false >
+ , If_< IsSymmetric<MT1>
+ , DMatDMatAddExpr< DMatTransExprTrait_<MT1>, MT2, true >
+ , DMatTDMatAddExpr<MT1,MT2> > >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatTDMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatTDMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatTDMatAddExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatTDMatAddExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the column-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatTDMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatTDMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using DMatTDMatAddExprTrait_ = typename DMatTDMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatTDMatMultExprTrait.h b/src/cpu/blaze/math/traits/DMatTDMatMultExprTrait.h
new file mode 100644
index 00000000..88f2a404
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatTDMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatTDMatMultExprTrait.h
+// \brief Header file for the DMatTDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATTDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATTDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/transpose dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/transpose dense matrix multiplication. Given the row-major dense matrix type \a MT1
+// and the column-major dense matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major dense matrix type or
+// \a MT2 is not a column-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct DMatTDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , DMatTDMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatTDMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatTDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatTDMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatTDMatMultExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the column-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatTDMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatTDMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using DMatTDMatMultExprTrait_ = typename DMatTDMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatTDMatSubExprTrait.h b/src/cpu/blaze/math/traits/DMatTDMatSubExprTrait.h
new file mode 100644
index 00000000..e9ddf3ab
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatTDMatSubExprTrait.h
@@ -0,0 +1,131 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatTDMatSubExprTrait.h
+// \brief Header file for the DMatTDMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATTDMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATTDMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/transpose dense matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/transpose dense matrix subtraction. Given the row-major dense matrix type \a MT1
+// and the column-major dense matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major dense matrix type or
+// \a MT2 is not a column-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct DMatTDMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , If_< IsSymmetric<MT2>
+ , DMatDMatSubExpr< MT1, TDMatTransExprTrait_<MT2>, false >
+ , If_< IsSymmetric<MT1>
+ , DMatDMatSubExpr< DMatTransExprTrait_<MT1>, MT2, true >
+ , DMatTDMatSubExpr<MT1,MT2> > >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatTDMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatTDMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatTDMatSubExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatTDMatSubExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the column-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatTDMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatTDMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using DMatTDMatSubExprTrait_ = typename DMatTDMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatTSMatAddExprTrait.h b/src/cpu/blaze/math/traits/DMatTSMatAddExprTrait.h
new file mode 100644
index 00000000..d267b3ae
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatTSMatAddExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatTSMatAddExprTrait.h
+// \brief Header file for the DMatTSMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATTSMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATTSMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/transpose sparse matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix/transpose sparse matrix addition. Given the row-major dense matrix type \a MT1 and
+// the column-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major dense matrix type or
+// \a MT2 is not a column-major sparse matrix type, the resulting data type \a Type is set
+// to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct DMatTSMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , DMatTSMatAddExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatTSMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatTSMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatTSMatAddExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatTSMatAddExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the column-major sparse matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatTSMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatTSMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using DMatTSMatAddExprTrait_ = typename DMatTSMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatTSMatMultExprTrait.h b/src/cpu/blaze/math/traits/DMatTSMatMultExprTrait.h
new file mode 100644
index 00000000..4fdecf94
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatTSMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatTSMatMultExprTrait.h
+// \brief Header file for the DMatTSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATTSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATTSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/transpose sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense matrix/
+// transpose sparse matrix multiplication. Given the row-major dense matrix type \a MT1 and the
+// column-major sparse matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a row-major dense matrix type or \a MT2 is not
+// a column-major sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct DMatTSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , DMatTSMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatTSMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatTSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatTSMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatTSMatMultExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the column-major sparse matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatTSMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatTSMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using DMatTSMatMultExprTrait_ = typename DMatTSMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatTSMatSubExprTrait.h b/src/cpu/blaze/math/traits/DMatTSMatSubExprTrait.h
new file mode 100644
index 00000000..6a057269
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatTSMatSubExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatTSMatSubExprTrait.h
+// \brief Header file for the DMatTSMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATTSMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATTSMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix/transpose sparse matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense matrix/
+// transpose sparse matrix subtraction. Given the row-major dense matrix type \a MT1 and the
+// column-major sparse matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a row-major dense matrix type or \a MT2 is not
+// a column-major sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct DMatTSMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , DMatTSMatSubExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , DMatTSMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatTSMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatTSMatSubExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DMatTSMatSubExprTrait class template. For instance, given the row-major
+// dense matrix type \a MT1 and the column-major sparse matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DMatTSMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = DMatTSMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using DMatTSMatSubExprTrait_ = typename DMatTSMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DMatTransExprTrait.h b/src/cpu/blaze/math/traits/DMatTransExprTrait.h
new file mode 100644
index 00000000..4f592163
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DMatTransExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DMatTransExprTrait.h
+// \brief Header file for the DMatTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DMATTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DMATTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix transpose operation. Given the row-major dense matrix type \a MT, the nested type
+// \a Type corresponds to the resulting expression type. In case \a MT is not a row-major
+// dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct DMatTransExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , DMatTransExpr<MT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , DMatTransExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DMatTransExprTrait class template.
+// \ingroup math_traits
+//
+// The DMatTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DMatTransExprTrait class template. For instance, given the row-major dense
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DMatTransExprTrait<MT>::Type;
+ using Type2 = DMatTransExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using DMatTransExprTrait_ = typename DMatTransExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecCTransExprTrait.h b/src/cpu/blaze/math/traits/DVecCTransExprTrait.h
new file mode 100644
index 00000000..88c114fd
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecCTransExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecCTransExprTrait.h
+// \brief Header file for the DVecCTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECCTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECCTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/traits/DVecForEachExprTrait.h>
+#include <blaze/math/traits/DVecTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector conjugate transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector conjugate transpose operation. Given the non-transpose dense vector type \a VT,
+// the nested type \a Type corresponds to the resulting expression type. In case \a VT is
+// not a non-transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the dense vector
+struct DVecCTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { typedef INVALID_TYPE Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecTransExprTrait< DVecForEachExprTrait_<VT,Conj> >
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , DVecCTransExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecCTransExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecCTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DVecCTransExprTrait class template. For instance, given the non-transpose dense
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecCTransExprTrait<VT>::Type;
+ using Type2 = DVecCTransExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the dense vector
+using DVecCTransExprTrait_ = typename DVecCTransExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecDVecAddExprTrait.h b/src/cpu/blaze/math/traits/DVecDVecAddExprTrait.h
new file mode 100644
index 00000000..05cec8f3
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecDVecAddExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecDVecAddExprTrait.h
+// \brief Header file for the DVecDVecAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECDVECADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECDVECADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/dense vector addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/dense vector addition. Given the two non-transpose dense vector types \a VT1 and
+// \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose dense vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct DVecDVecAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2> >
+ , DVecDVecAddExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecDVecAddExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecDVecAddExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecDVecAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecDVecAddExprTrait class template. For instance, given the
+// non-transpose dense vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename DVecDVecAddExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecDVecAddExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using DVecDVecAddExprTrait_ = typename DVecDVecAddExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecDVecCrossExprTrait.h b/src/cpu/blaze/math/traits/DVecDVecCrossExprTrait.h
new file mode 100644
index 00000000..5b9146e0
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecDVecCrossExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecDVecCrossExprTrait.h
+// \brief Header file for the DVecDVecCrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECDVECCROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECDVECCROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/dense vector cross product.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/dense vector cross product. Given the two non-transpose dense vector types \a VT1
+// and \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose dense vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct DVecDVecCrossExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2> >
+ , DVecDVecCrossExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecDVecCrossExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecDVecCrossExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecDVecCrossExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecDVecCrossExprTrait class template. For instance, given the
+// non-transpose dense vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename DVecDVecCrossExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecDVecCrossExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using DVecDVecCrossExprTrait_ = typename DVecDVecCrossExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecDVecDivExprTrait.h b/src/cpu/blaze/math/traits/DVecDVecDivExprTrait.h
new file mode 100644
index 00000000..eb8c4f2b
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecDVecDivExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecDVecDivExprTrait.h
+// \brief Header file for the DVecDVecDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECDVECDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECDVECDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/dense vector division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/dense vector division. Given the two non-transpose dense vector types \a VT1 and
+// \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose dense vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct DVecDVecDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2> >
+ , DVecDVecDivExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecDVecDivExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecDVecDivExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecDVecDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecDVecDivExprTrait class template. For instance, given the
+// non-transpose dense vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename DVecDVecDivExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecDVecDivExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using DVecDVecDivExprTrait_ = typename DVecDVecDivExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecDVecMultExprTrait.h b/src/cpu/blaze/math/traits/DVecDVecMultExprTrait.h
new file mode 100644
index 00000000..5d0eeb18
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecDVecMultExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecDVecMultExprTrait.h
+// \brief Header file for the DVecDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/dense vector multiplication. Given the two non-transpose dense vector types \a VT1
+// and \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose dense vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct DVecDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2> >
+ , DVecDVecMultExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecDVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecDVecMultExprTrait class template. For instance, given the
+// non-transpose dense vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename DVecDVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecDVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using DVecDVecMultExprTrait_ = typename DVecDVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecDVecSubExprTrait.h b/src/cpu/blaze/math/traits/DVecDVecSubExprTrait.h
new file mode 100644
index 00000000..8e84e82a
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecDVecSubExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecDVecSubExprTrait.h
+// \brief Header file for the DVecDVecSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECDVECSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECDVECSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/dense vector subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/dense vector subtraction. Given the two non-transpose dense vector types \a VT1
+// and \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose dense vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct DVecDVecSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsColumnVector<VT2> >
+ , DVecDVecSubExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecDVecSubExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecDVecSubExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecDVecSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecDVecSubExprTrait class template. For instance, given the
+// non-transpose dense vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename DVecDVecSubExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecDVecSubExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using DVecDVecSubExprTrait_ = typename DVecDVecSubExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecEvalExprTrait.h b/src/cpu/blaze/math/traits/DVecEvalExprTrait.h
new file mode 100644
index 00000000..cad86ac5
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecEvalExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecEvalExprTrait.h
+// \brief Header file for the DVecEvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECEVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECEVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector evaluation operation. Given the non-transpose dense vector type \a VT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a VT is not a
+// non-transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the dense vector
+struct DVecEvalExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecEvalExpr<VT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , DVecEvalExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecEvalExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecEvalExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DVecEvalExprTrait class template. For instance, given the non-transpose dense
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecEvalExprTrait<VT>::Type;
+ using Type2 = DVecEvalExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the dense vector
+using DVecEvalExprTrait_ = typename DVecEvalExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecForEachExprTrait.h b/src/cpu/blaze/math/traits/DVecForEachExprTrait.h
new file mode 100644
index 00000000..db87a969
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecForEachExprTrait.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecForEachExprTrait.h
+// \brief Header file for the DVecForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECFOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECFOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector custom operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense vector
+// custom operation. Given the non-transpose dense vector type \a VT and the custom operation type
+// \a OP, the nested type \a Type corresponds to the resulting expression type. In case \a VT is
+// not a non-transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the dense vector
+ , typename OP > // Type of the custom operation
+struct DVecForEachExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecForEachExpr<VT,OP,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , DVecForEachExprTrait< Decay_<VT>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecForEachExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DVecForEachExprTrait class template. For instance, given the non-transpose dense
+// vector type \a VT and the custom operation type \a OP the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename DVecForEachExprTrait<VT,OP>::Type;
+ using Type2 = DVecForEachExprTrait_<VT,OP>;
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , typename OP > // Type of the custom operation
+using DVecForEachExprTrait_ = typename DVecForEachExprTrait<VT,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecSVecAddExprTrait.h b/src/cpu/blaze/math/traits/DVecSVecAddExprTrait.h
new file mode 100644
index 00000000..e0aad74c
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecSVecAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecSVecAddExprTrait.h
+// \brief Header file for the DVecSVecAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECSVECADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECSVECADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/sparse vector addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/sparse vector addition. Given the non-transpose dense vector type \a VT1 and the
+// non-transpose sparse vector type \a VT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT1 is not a non-transpose dense vector type or \a VT2 is
+// not a non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct DVecSVecAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2> >
+ , DVecSVecAddExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecSVecAddExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecSVecAddExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecSVecAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecSVecAddExprTrait class template. For instance, given the
+// non-transpose dense vector type \a VT1 and the non-transpose sparse vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecSVecAddExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecSVecAddExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using DVecSVecAddExprTrait_ = typename DVecSVecAddExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecSVecCrossExprTrait.h b/src/cpu/blaze/math/traits/DVecSVecCrossExprTrait.h
new file mode 100644
index 00000000..98a9af5d
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecSVecCrossExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecSVecCrossExprTrait.h
+// \brief Header file for the DVecSVecCrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECSVECCROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECSVECCROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/sparse vector cross product.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/sparse vector cross product. Given the non-transpose dense vector type \a VT1 and the
+// non-transpose sparse vector type\a VT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT1 is not a non-transpose dense vector type or \a VT2 is
+// not a non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct DVecSVecCrossExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2> >
+ , DVecSVecCrossExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecSVecCrossExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecSVecCrossExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecSVecCrossExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecSVecCrossExprTrait class template. For instance, given the
+// non-transpose dense vector type \a VT1 and the non-transpose sparse vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecSVecCrossExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecSVecCrossExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using DVecSVecCrossExprTrait_ = typename DVecSVecCrossExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecSVecMultExprTrait.h b/src/cpu/blaze/math/traits/DVecSVecMultExprTrait.h
new file mode 100644
index 00000000..1cb1df1f
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecSVecMultExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecSVecMultExprTrait.h
+// \brief Header file for the DVecSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/sparse vector multiplication. Given the non-transpose dense vector type \a VT1 and the
+// non-transpose sparse vector type\a VT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT1 is not a non-transpose dense vector type or \a VT2 is
+// not a non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct DVecSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2> >
+ , DVecSVecMultExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecSVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecSVecMultExprTrait class template. For instance, given the
+// non-transpose dense vector type \a VT1 and the non-transpose sparse vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecSVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecSVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using DVecSVecMultExprTrait_ = typename DVecSVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecSVecSubExprTrait.h b/src/cpu/blaze/math/traits/DVecSVecSubExprTrait.h
new file mode 100644
index 00000000..17a2ad04
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecSVecSubExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecSVecSubExprTrait.h
+// \brief Header file for the DVecSVecSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECSVECSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECSVECSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/sparse vector subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/sparse vector subtraction. Given the non-transpose dense vector type \a VT1 and the
+// non-transpose sparse vector type\a VT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT1 is not a non-transpose dense vector type or \a VT2 is
+// not a non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct DVecSVecSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2> >
+ , DVecSVecSubExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecSVecSubExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecSVecSubExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecSVecSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecSVecSubExprTrait class template. For instance, given the
+// non-transpose dense vector type \a VT1 and the non-transpose sparse vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecSVecSubExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecSVecSubExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using DVecSVecSubExprTrait_ = typename DVecSVecSubExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecScalarDivExprTrait.h b/src/cpu/blaze/math/traits/DVecScalarDivExprTrait.h
new file mode 100644
index 00000000..fc5122cd
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecScalarDivExprTrait.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecScalarDivExprTrait.h
+// \brief Header file for the DVecScalarDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECSCALARDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECSCALARDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the DVecScalarDivExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST
+ , bool Condition >
+struct DVecScalarDivExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<VT> >, IsBuiltin<ST> >
+ , DivTrait_< UnderlyingBuiltin_<VT>, ST >
+ , DivTrait_< UnderlyingNumeric_<VT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< IsInvertible<ScalarType>
+ , DVecScalarMultExpr<VT,ScalarType,false>
+ , DVecScalarDivExpr<VT,ScalarType,false> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the DVecScalarDivExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST >
+struct DVecScalarDivExprTraitHelper<VT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/scalar division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/scalar division. Given the non-transpose dense vector type \a VT and the scalar type
+// \a ST, the nested type \a Type corresponds to the resulting expression type. In case either
+// \a VT is not a non-transpose dense vector type or \a ST is not a scalar type, the resulting
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST > // Type of the right-hand side scalar
+struct DVecScalarDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsDenseVector<VT>, IsColumnVector<VT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , DVecScalarDivExprTrait< Decay_<VT>, Decay_<ST> >
+ , DVecScalarDivExprTraitHelper<VT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecScalarDivExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecScalarDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecScalarDivExprTrait class template. For instance, given the
+// non-transpose dense vector type \a VT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DVecScalarDivExprTrait<VT,ST>::Type;
+ using Type2 = DVecScalarDivExprTrait_<VT,ST>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST > // Type of the right-hand side scalar
+using DVecScalarDivExprTrait_ = typename DVecScalarDivExprTrait<VT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecScalarMultExprTrait.h b/src/cpu/blaze/math/traits/DVecScalarMultExprTrait.h
new file mode 100644
index 00000000..211d8c67
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecScalarMultExprTrait.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecScalarMultExprTrait.h
+// \brief Header file for the DVecScalarMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECSCALARMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECSCALARMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the DVecScalarMultExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST
+ , bool Condition >
+struct DVecScalarMultExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<VT> >, IsBuiltin<ST> >
+ , MultTrait_< UnderlyingBuiltin_<VT>, ST >
+ , MultTrait_< UnderlyingNumeric_<VT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = DVecScalarMultExpr<VT,ScalarType,false>;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the DVecScalarMultExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST >
+struct DVecScalarMultExprTraitHelper<VT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/scalar multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/scalar multiplication. Given the non-transpose dense vector type \a VT and the scalar
+// type \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT is not a non-transpose dense vector type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST > // Type of the right-hand side scalar
+struct DVecScalarMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsDenseVector<VT>, IsColumnVector<VT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , DVecScalarMultExprTrait< Decay_<VT>, Decay_<ST> >
+ , DVecScalarMultExprTraitHelper<VT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecScalarMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecScalarMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecScalarMultExprTrait class template. For instance, given the
+// non-transpose dense vector type \a VT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DVecScalarMultExprTrait<VT,ST>::Type;
+ using Type2 = DVecScalarMultExprTrait_<VT,ST>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST > // Type of the right-hand side scalar
+using DVecScalarMultExprTrait_ = typename DVecScalarMultExprTrait<VT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecSerialExprTrait.h b/src/cpu/blaze/math/traits/DVecSerialExprTrait.h
new file mode 100644
index 00000000..c8cd9e77
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecSerialExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecSerialExprTrait.h
+// \brief Header file for the DVecSerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECSERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECSERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector serial evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector serial evaluation operation. Given the non-transpose dense vector type \a VT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a VT is not
+// a non-transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the dense vector
+struct DVecSerialExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecSerialExpr<VT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , DVecSerialExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecSerialExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecSerialExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DVecSerialExprTrait class template. For instance, given the non-transpose dense
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecSerialExprTrait<VT>::Type;
+ using Type2 = DVecSerialExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the dense vector
+using DVecSerialExprTrait_ = typename DVecSerialExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecTDVecMultExprTrait.h b/src/cpu/blaze/math/traits/DVecTDVecMultExprTrait.h
new file mode 100644
index 00000000..5e80d860
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecTDVecMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecTDVecMultExprTrait.h
+// \brief Header file for the DVecTDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECTDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECTDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/transpose dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/transpose dense vector multiplication (outer product). Given the non-transpose
+// dense vector type \a VT1 and the transpose dense vector type \a VT2, the nested type
+// \a Type corresponds to the resulting expression type. In case either \a VT1 is not a
+// non-transpose dense vector type or \a VT2 is not a transpose dense vector type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct DVecTDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2> >
+ , DVecTDVecMultExpr<VT1,VT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecTDVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecTDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecTDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecTDVecMultExprTrait class template. For instance, given the
+// non-transpose dense vector type \a VT1 and the transpose dense vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecTDVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecTDVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using DVecTDVecMultExprTrait_ = typename DVecTDVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecTSVecMultExprTrait.h b/src/cpu/blaze/math/traits/DVecTSVecMultExprTrait.h
new file mode 100644
index 00000000..640038a2
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecTSVecMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecTSVecMultExprTrait.h
+// \brief Header file for the DVecTSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECTSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECTSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/transpose sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/transpose sparse vector multiplication (outer product). Given the non-transpose
+// dense vector type \a VT1 and the transpose sparse vector type \a VT2, the nested type
+// \a Type corresponds to the resulting expression type. In case either \a VT1 is not a
+// non-transpose dense vector type or \a VT2 is not a transpose sparse vector type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct DVecTSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , DVecTSVecMultExpr<VT1,VT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , DVecTSVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecTSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecTSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the DVecTSVecMultExprTrait class template. For instance, given the
+// non-transpose dense vector type \a VT1 and the transpose sparse vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecTSVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = DVecTSVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using DVecTSVecMultExprTrait_ = typename DVecTSVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DVecTransExprTrait.h b/src/cpu/blaze/math/traits/DVecTransExprTrait.h
new file mode 100644
index 00000000..8af2c319
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DVecTransExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DVecTransExprTrait.h
+// \brief Header file for the DVecTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DVECTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DVECTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector transpose operation. Given the non-transpose dense vector type \a VT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a VT is not a
+// non-transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the dense vector
+struct DVecTransExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsColumnVector<VT> >
+ , DVecTransExpr<VT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , DVecTransExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DVecTransExprTrait class template.
+// \ingroup math_traits
+//
+// The DVecTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the DVecTransExprTrait class template. For instance, given the non-transpose dense
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DVecTransExprTrait<VT>::Type;
+ using Type2 = DVecTransExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the dense vector
+using DVecTransExprTrait_ = typename DVecTransExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DerestrictTrait.h b/src/cpu/blaze/math/traits/DerestrictTrait.h
new file mode 100644
index 00000000..7bb87ccb
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DerestrictTrait.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DerestrictTrait.h
+// \brief Header file for the DerestrictTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DERESTRICTTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DERESTRICTTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/AddReference.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of the derestrict function.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting return type of the derestrict
+// function. Given the vector or matrix type \a T, the nested type \a Type corresponds to the
+// resulting return type. In case \a T is neither a dense or sparse vector or matrix type,
+// the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename T > // Type of the vector or matrix
+struct DerestrictTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< Or< IsVector<T>, IsMatrix<T> >
+ , AddReference_<T>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , DerestrictTrait< Decay_<T> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DerestrictTrait type trait.
+// \ingroup math_traits
+//
+// The DerestrictTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the DerestrictTrait class template. For instance, given the type \a T
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename DerestrictTrait<T>::Type;
+ using Type2 = DerestrictTrait_<T>;
+ \endcode
+*/
+template< typename T >
+using DerestrictTrait_ = typename DerestrictTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DivExprTrait.h b/src/cpu/blaze/math/traits/DivExprTrait.h
new file mode 100644
index 00000000..069f7bb2
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DivExprTrait.h
@@ -0,0 +1,201 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DivExprTrait.h
+// \brief Header file for the DivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/DMatScalarDivExprTrait.h>
+#include <blaze/math/traits/DVecDVecDivExprTrait.h>
+#include <blaze/math/traits/DVecScalarDivExprTrait.h>
+#include <blaze/math/traits/SMatScalarDivExprTrait.h>
+#include <blaze/math/traits/SVecDVecDivExprTrait.h>
+#include <blaze/math/traits/SVecScalarDivExprTrait.h>
+#include <blaze/math/traits/TDMatScalarDivExprTrait.h>
+#include <blaze/math/traits/TDVecScalarDivExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecDivExprTrait.h>
+#include <blaze/math/traits/TSMatScalarDivExprTrait.h>
+#include <blaze/math/traits/TSVecScalarDivExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecDivExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the resulting expression type of a division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a division expression
+// between scalars, vectors, and matrices. Given the two types \a T1 and \a T2, where \a T1 must
+// either be a scalar, vector, or matrix type and \a T2 which must be a scalar type, the nested
+// type \a Type corresponds to the resulting return type. In case \a T1 or \a T2 don't fit or if
+// the two types cannot be divided, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename T1 // Type of the left-hand side division operand
+ , typename T2 > // Type of the right-hand side division operand
+struct DivExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T1>
+ , If_< IsDenseMatrix<T1>
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsNumeric<T2>
+ , DMatScalarDivExprTrait<T1,T2>
+ , Failure >
+ , If_< IsNumeric<T2>
+ , TDMatScalarDivExprTrait<T1,T2>
+ , Failure > >
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsNumeric<T2>
+ , SMatScalarDivExprTrait<T1,T2>
+ , Failure >
+ , If_< IsNumeric<T2>
+ , TSMatScalarDivExprTrait<T1,T2>
+ , Failure > > >
+ , If_< IsVector<T1>
+ , If_< IsDenseVector<T1>
+ , If_< IsRowVector<T1>
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T2>
+ , TDVecTDVecDivExprTrait<T1,T2>
+ , Failure >
+ , Failure >
+ , If_< IsNumeric<T2>
+ , TDVecScalarDivExprTrait<T1,T2>
+ , Failure > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsColumnVector<T2>
+ , DVecDVecDivExprTrait<T1,T2>
+ , Failure >
+ , Failure >
+ , If_< IsNumeric<T2>
+ , DVecScalarDivExprTrait<T1,T2>
+ , Failure > > >
+ , If_< IsRowVector<T1>
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T2>
+ , TSVecTDVecDivExprTrait<T1,T2>
+ , Failure >
+ , Failure >
+ , If_< IsNumeric<T2>
+ , TSVecScalarDivExprTrait<T1,T2>
+ , Failure > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsColumnVector<T2>
+ , SVecDVecDivExprTrait<T1,T2>
+ , Failure >
+ , Failure >
+ , If_< IsNumeric<T2>
+ , SVecScalarDivExprTrait<T1,T2>
+ , Failure > > > >
+ , If_< IsNumeric<T1>
+ , If_< IsNumeric<T2>
+ , DivTrait<T1,T2>
+ , Failure >
+ , Failure > > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , DivExprTrait< Decay_<T1>, Decay_<T2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DivExprTrait class template.
+// \ingroup math_traits
+//
+// The DivExprTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the DivExprTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename DivExprTrait<T1,T2>::Type;
+ using Type2 = DivExprTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side division operand
+ , typename T2 > // Type of the right-hand side division operand
+using DivExprTrait_ = typename DivExprTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/DivTrait.h b/src/cpu/blaze/math/traits/DivTrait.h
new file mode 100644
index 00000000..93ee3edf
--- /dev/null
+++ b/src/cpu/blaze/math/traits/DivTrait.h
@@ -0,0 +1,236 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/DivTrait.h
+// \brief Header file for the division trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_DIVTRAIT_H_
+#define _BLAZE_MATH_TRAITS_DIVTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/CommonType.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the DivTrait class.
+// \ingroup math_traits
+//
+// \section divtrait_general General
+//
+// The DivTrait class template offers the possibility to select the resulting data type of a
+// generic division operation between the two given types \a T1 and \a T2. DivTrait defines
+// the nested type \a Type, which represents the resulting data type of the division. In case
+// the two types \a T1 and \a T2 cannot be divided, a compilation error is created. Note that
+// \c const and \c volatile qualifiers and reference modifiers are generally ignored.
+//
+// Per default, DivTrait supports all built-in data types. Additionally, the Blaze library
+// provides appropriate specializations for the following user-defined arithmetic types:
+//
+// <ul>
+// <li>std::complex</li>
+// <li>blaze::StaticVector</li>
+// <li>blaze::HybridVector</li>
+// <li>blaze::DynamicVector</li>
+// <li>blaze::CustomVector</li>
+// <li>blaze::CompressedVector</li>
+// <li>blaze::StaticMatrix</li>
+// <li>blaze::HybridMatrix</li>
+// <li>blaze::DynamicMatrix</li>
+// <li>blaze::CustomMatrix</li>
+// <li>blaze::CompressedMatrix</li>
+// <li>blaze::SymmetricMatrix</li>
+// <li>blaze::HermitianMatrix</li>
+// <li>blaze::LowerMatrix</li>
+// <li>blaze::UniLowerMatrix</li>
+// <li>blaze::StrictlyLowerMatrix</li>
+// <li>blaze::UpperMatrix</li>
+// <li>blaze::UniUpperMatrix</li>
+// <li>blaze::StrictlyUpperMatrix</li>
+// <li>blaze::DiagonalMatrix</li>
+// </ul>
+//
+//
+// \n \section divtrait_specializations Creating custom specializations
+//
+// DivTrait is guaranteed to work for all data types that provide a division operator (i.e.
+// \c operator/). In order to add support for user-defined data types that either don't provide
+// a division operator or whose division operator returns a proxy object instead of a concrete
+// type (as it is for instance common in expression template libraries) it is possible to
+// specialize the DivTrait template. The following example shows the according specialization
+// for the division of a dynamic column vector by a double precision scalar value:
+
+ \code
+ template< typename T1 >
+ struct DivTrait< DynamicVector<T1,columnVector>, double >
+ {
+ typedef DynamicVector< typename DivTrait<T1,double>::Type, columnVector > Type;
+ };
+ \endcode
+
+// \n \section divtrait_examples Examples
+//
+// The following example demonstrates the use of the DivTrait template, where depending on
+// the two given data types the resulting data type is selected:
+
+ \code
+ template< typename T1, typename T2 > // The two generic types
+ typename DivTrait<T1,T2>::Type // The resulting generic return type
+ div( const T1& t1, const T2& t2 ) //
+ { // The function 'div' returns the
+ return t1 / t2; // quotient of the two given values
+ } //
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct DivTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type1 = Decay_<T1>;
+ using Type2 = Decay_<T2>;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct DivType { using Type = decltype( std::declval<Type1>() / std::declval<Type2>() ); };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , DivTrait<Type1,Type2>
+ , DivType >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the DivTrait class template for a complex and a built-in type.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct DivTrait< complex<T1>, T2, EnableIf_< IsBuiltin<T2> > >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< complex<T1> , T2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the DivTrait class template for a built-in and a complex type.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct DivTrait< T1, complex<T2>, EnableIf_< IsBuiltin<T1> > >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< T1, complex<T2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the DivTrait class template for two complex types.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct DivTrait< complex<T1>, complex<T2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< complex<T1>, complex<T2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the DivTrait class template.
+// \ingroup math_traits
+//
+// The DivTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the DivTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename DivTrait<T1,T2>::Type;
+ using Type2 = DivTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1, typename T2 >
+using DivTrait_ = typename DivTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/EvalExprTrait.h b/src/cpu/blaze/math/traits/EvalExprTrait.h
new file mode 100644
index 00000000..ef25107a
--- /dev/null
+++ b/src/cpu/blaze/math/traits/EvalExprTrait.h
@@ -0,0 +1,147 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/EvalExprTrait.h
+// \brief Header file for the EvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_EVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_EVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DMatEvalExprTrait.h>
+#include <blaze/math/traits/DVecEvalExprTrait.h>
+#include <blaze/math/traits/SMatEvalExprTrait.h>
+#include <blaze/math/traits/SVecEvalExprTrait.h>
+#include <blaze/math/traits/TDMatEvalExprTrait.h>
+#include <blaze/math/traits/TDVecEvalExprTrait.h>
+#include <blaze/math/traits/TSMatEvalExprTrait.h>
+#include <blaze/math/traits/TSVecEvalExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of an evaluation expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of an evaluation expression.
+// Given the type \a T, which must either be a vector or matrix type, the nested type \a Type
+// corresponds to the resulting return type. In case the type of \a T doesn't fit or if no
+// evaluation operation exists for the type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename T > // Type of the evaluation operand
+struct EvalExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T>
+ , If_< IsDenseMatrix<T>
+ , If_< IsRowMajorMatrix<T>
+ , DMatEvalExprTrait<T>
+ , TDMatEvalExprTrait<T> >
+ , If_< IsRowMajorMatrix<T>
+ , SMatEvalExprTrait<T>
+ , TSMatEvalExprTrait<T> > >
+ , If_< IsVector<T>
+ , If_< IsDenseVector<T>
+ , If_< IsRowVector<T>
+ , TDVecEvalExprTrait<T>
+ , DVecEvalExprTrait<T> >
+ , If_< IsRowVector<T>
+ , TSVecEvalExprTrait<T>
+ , SVecEvalExprTrait<T> > >
+ , Failure > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , EvalExprTrait< Decay_<T> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the EvalExprTrait class template.
+// \ingroup math_traits
+//
+// The EvalExprTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the EvalExprTrait class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename EvalExprTrait<T>::Type;
+ using Type2 = EvalExprTrait_<T>;
+ \endcode
+*/
+template< typename T > // Type of the evaluation operand
+using EvalExprTrait_ = typename EvalExprTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/ForEachExprTrait.h b/src/cpu/blaze/math/traits/ForEachExprTrait.h
new file mode 100644
index 00000000..27aa55a7
--- /dev/null
+++ b/src/cpu/blaze/math/traits/ForEachExprTrait.h
@@ -0,0 +1,149 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/ForEachExprTrait.h
+// \brief Header file for the ForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_FOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_FOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DMatForEachExprTrait.h>
+#include <blaze/math/traits/DVecForEachExprTrait.h>
+#include <blaze/math/traits/SMatForEachExprTrait.h>
+#include <blaze/math/traits/SVecForEachExprTrait.h>
+#include <blaze/math/traits/TDMatForEachExprTrait.h>
+#include <blaze/math/traits/TDVecForEachExprTrait.h>
+#include <blaze/math/traits/TSMatForEachExprTrait.h>
+#include <blaze/math/traits/TSVecForEachExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of a \c forEach expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a \c forEach expression.
+// Given the type \a T, which must either be a scalar, vector, or matrix type, the nested type
+// \a Type corresponds to the resulting return type. In case the type of \a T doesn't fit or
+// if no \c forEach operation exists for the type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename T // Type of the forEach operand
+ , typename OP > // Type of the custom operation
+struct ForEachExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T>
+ , If_< IsDenseMatrix<T>
+ , If_< IsRowMajorMatrix<T>
+ , DMatForEachExprTrait<T,OP>
+ , TDMatForEachExprTrait<T,OP> >
+ , If_< IsRowMajorMatrix<T>
+ , SMatForEachExprTrait<T,OP>
+ , TSMatForEachExprTrait<T,OP> > >
+ , If_< IsVector<T>
+ , If_< IsDenseVector<T>
+ , If_< IsRowVector<T>
+ , TDVecForEachExprTrait<T,OP>
+ , DVecForEachExprTrait<T,OP> >
+ , If_< IsRowVector<T>
+ , TSVecForEachExprTrait<T,OP>
+ , SVecForEachExprTrait<T,OP> > >
+ , Failure > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , ForEachExprTrait< Decay_<T>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the ForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The ForEachExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the ForEachExprTrait class template. For instance, given the data type \a T and
+// custom operation type \a OP the following two type definitions are identical:
+
+ \code
+ using Type1 = typename ForEachExprTrait<T,OP>::Type;
+ using Type2 = ForEachExprTrait_<T,OP>;
+ \endcode
+*/
+template< typename T // Type of the forEach operand
+ , typename OP > // Type of the custom operation
+using ForEachExprTrait_ = typename ForEachExprTrait<T,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/ForEachTrait.h b/src/cpu/blaze/math/traits/ForEachTrait.h
new file mode 100644
index 00000000..8e788f3a
--- /dev/null
+++ b/src/cpu/blaze/math/traits/ForEachTrait.h
@@ -0,0 +1,151 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/ForEachTrait.h
+// \brief Header file for the for-each trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_FOREACHTRAIT_H_
+#define _BLAZE_MATH_TRAITS_FOREACHTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/math/typetraits/RemoveAdaptor.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the ForEachTrait class.
+// \ingroup math_traits
+//
+// The ForEachTrait class template offers the possibility to select the resulting data type of a
+// generic \a forEach operation on the given type \a T. Given the type \a T, which must either be
+// a vector or matrix type, the nested type \a Type corresponds to the resulting data type of the
+// operation. In case the type of \a T doesn't fit or if no \a forEach operation exists for the
+// type, the resulting data type \a Type is set to \a INVALID_TYPE. Note that \a const and
+// \a volatile qualifiers and reference modifiers are generally ignored.
+*/
+template< typename T // Type of the operand
+ , typename OP > // Type of the custom operation
+struct ForEachTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct MatrixOrVector
+ {
+ template< typename U >
+ static DisableIf_< Or< IsVector<U>, IsMatrix<U> >, U > test( U&& );
+
+ template< typename U >
+ static EnableIf_< Or< IsVector<U>, IsMatrix<U> >, ResultType_<U> > test( U&& );
+
+ using RT = RemoveAdaptor_< ResultType_<T> >;
+ using RN = ReturnType_<T>;
+
+ using OT = decltype( std::declval<OP>()( std::declval<RN>() ) );
+ using ET = decltype( test( std::declval<OT>() ) );
+
+ using Type = typename RT::template Rebind<ET>::Other;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure {
+ using Type = INVALID_TYPE;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< Or< IsMatrix<T>, IsVector<T> >
+ , MatrixOrVector
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , ForEachTrait< Decay_<T>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the ForEachTrait class template.
+// \ingroup math_traits
+//
+// The ForEachTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the ForEachTrait class template. For instance, given the type \a T and the custom operation
+// type \a OP the following two type definitions are identical:
+
+ \code
+ using Type1 = typename ForEachTrait<T,OP>::Type;
+ using Type2 = ForEachTrait_<T,OP>;
+ \endcode
+*/
+template< typename T // Type of the operand
+ , typename OP > // Type of the custom operation
+using ForEachTrait_ = typename ForEachTrait<T,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/ImagTrait.h b/src/cpu/blaze/math/traits/ImagTrait.h
new file mode 100644
index 00000000..232046e3
--- /dev/null
+++ b/src/cpu/blaze/math/traits/ImagTrait.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/ImagTrait.h
+// \brief Header file for the imaginary trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_IMAGTRAIT_H_
+#define _BLAZE_MATH_TRAITS_IMAGTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the ImagTrait class.
+// \ingroup math_traits
+//
+// The ImagTrait class template offers the possibility to select the resulting data type of a
+// generic \a imag operation on the given type \a T. Given the type \a T, which must either be
+// a scalar, vector, or matrix type, the nested type \a Type corresponds to the resulting data
+// type of the operation. In case the type of \a T doesn't fit or if no \a imag operation exists
+// for the type, the resulting data type \a Type is set to \a INVALID_TYPE. Note that \a const
+// and \a volatile qualifiers and reference modifiers are generally ignored.
+*/
+template< typename T > // Type of the operand
+struct ImagTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct MatrixOrVector {
+ using RT = typename ImagTrait< ElementType_<T> >::Type;
+ using Type = typename T::template Rebind<RT>::Other;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Builtin {
+ using Type = T;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Complex {
+ using Type = typename T::value_type;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure {
+ using Type = INVALID_TYPE;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< Or< IsMatrix<T>, IsVector<T> >
+ , MatrixOrVector
+ , If_< IsBuiltin<T>
+ , Builtin
+ , If_< IsComplex<T>
+ , Complex
+ , Failure > > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , ImagTrait< Decay_<T> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the ImagTrait class template.
+// \ingroup math_traits
+//
+// The ImagTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the ImagTrait class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename ImagTrait<T>::Type;
+ using Type2 = ImagTrait_<T>;
+ \endcode
+*/
+template< typename T > // Type of the operand
+using ImagTrait_ = typename ImagTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/InvExprTrait.h b/src/cpu/blaze/math/traits/InvExprTrait.h
new file mode 100644
index 00000000..d8dd9584
--- /dev/null
+++ b/src/cpu/blaze/math/traits/InvExprTrait.h
@@ -0,0 +1,139 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/InvExprTrait.h
+// \brief Header file for the InvExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_INVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_INVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DMatInvExprTrait.h>
+#include <blaze/math/traits/TDMatInvExprTrait.h>
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/UnderlyingElement.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of an inversion expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of an inversion expression.
+// Given the type \a T, which must either a (complex) floating point type or a dense matrix type,
+// the nested type \a Type corresponds to the resulting return type. In case the type of \a T
+// doesn't fit or if no inversion operation exists for the type, the resulting data type \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename T > // Type of the inversion operand
+struct InvExprTrait
+{
+ private:
+ //**struct Scalar*******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Scalar { using Type = T; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< And< IsDenseMatrix<T>, IsBLASCompatible< UnderlyingElement_<T> > >
+ , If_< IsRowMajorMatrix<T>
+ , DMatInvExprTrait<T>
+ , TDMatInvExprTrait<T> >
+ , If_< Or< IsFloatingPoint<T>
+ , And< IsComplex<T>, IsFloatingPoint< UnderlyingElement_<T> > > >
+ , Scalar
+ , Failure > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , InvExprTrait< Decay_<T> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the InvExprTrait class template.
+// \ingroup math_traits
+//
+// The InvExprTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the InvExprTrait class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename InvExprTrait<T>::Type;
+ using Type2 = InvExprTrait_<T>;
+ \endcode
+*/
+template< typename T > // Type of the inversion operand
+using InvExprTrait_ = typename InvExprTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/MathTrait.h b/src/cpu/blaze/math/traits/MathTrait.h
new file mode 100644
index 00000000..18105414
--- /dev/null
+++ b/src/cpu/blaze/math/traits/MathTrait.h
@@ -0,0 +1,775 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/MathTrait.h
+// \brief Header file for the mathematical trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_MATHTRAIT_H_
+#define _BLAZE_MATH_TRAITS_MATHTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cstddef>
+#include <blaze/util/Complex.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the MathTrait class.
+// \ingroup math_traits
+//
+// \section mathtrait_general General
+//
+// The MathTrait class template determines the more significant, dominating data type and the
+// less significant, submissive data type of the two given data types \a T1 and \a T2. The more
+// significant data type is represented by the nested type \a HighType, the less significant
+// data type by the nested type \a LowType. For instance, in case both \a T1 and \a T2 are
+// built-in data types, \a HighType is set to the larger or signed data type and \a LowType
+// is set to the smaller or unsigned data type. In case no dominating data type can be selected,
+// \a Type is set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and reference
+// modifiers are generally ignored.
+//
+// Per default, the MathTrait template provides specializations for the following built-in data
+// types:
+//
+// <ul>
+// <li>Integral types</li>
+// <ul>
+// <li>unsigned char, signed char, char, wchar_t</li>
+// <li>unsigned short, short</li>
+// <li>unsigned int, int</li>
+// <li>unsigned long, long</li>
+// <li>std::size_t, std::ptrdiff_t (for certain 64-bit compilers)</li>
+// </ul>
+// <li>Floating point types</li>
+// <ul>
+// <li>float</li>
+// <li>double</li>
+// <li>long double</li>
+// </ul>
+// </ul>
+//
+// Additionally, the Blaze library provides specializations for the following user-defined
+// arithmetic types, wherever a more/less significant data type can be selected:
+//
+// <ul>
+// <li>std::complex</li>
+// <li>blaze::StaticVector</li>
+// <li>blaze::HybridVector</li>
+// <li>blaze::DynamicVector</li>
+// <li>blaze::CompressedVector</li>
+// <li>blaze::StaticMatrix</li>
+// <li>blaze::HybridMatrix</li>
+// <li>blaze::DynamicMatrix</li>
+// <li>blaze::CompressedMatrix</li>
+// <li>blaze::SymmetricMatrix</li>
+// <li>blaze::LowerMatrix</li>
+// <li>blaze::UniLowerMatrix</li>
+// <li>blaze::StrictlyLowerMatrix</li>
+// <li>blaze::UpperMatrix</li>
+// <li>blaze::UniUpperMatrix</li>
+// <li>blaze::StrictlyUpperMatrix</li>
+// <li>blaze::DiagonalMatrix</li>
+// </ul>
+//
+//
+// \n \section mathtrait_specializations Creating custom specializations
+//
+// It is possible to specialize the MathTrait template for additional user-defined data types.
+// The following example shows the according specialization for two dynamic column vectors:
+
+ \code
+ template< typename T1, typename T2 >
+ struct MathTrait< DynamicVector<T1,false>, DynamicVector<T2,false> >
+ {
+ typedef DynamicVector< typename MathTrait<T1,T2>::Type, false > Type;
+ };
+ \endcode
+*/
+template< typename T1, typename T2 >
+struct MathTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure {
+ using HighType = INVALID_TYPE;
+ using LowType = INVALID_TYPE;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Helper = MathTrait< Decay_<T1>, Decay_<T2> >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using HighType = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , Helper
+ , Failure >::HighType;
+
+ using LowType = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , Helper
+ , Failure >::LowType;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATION FOR IDENTICAL TYPES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization for two identical types.
+// \ingroup math_traits
+//
+// This specialization of the MathTrait class template handles the special case that the two
+// given types are identical. In this case, the nested types \a HighType and \a LowType are
+// set to the given type \a T (ignoring \a const and \a volatile qualifiers and reference
+// modifiers).
+*/
+template< typename T >
+struct MathTrait<T,T>
+{
+ //**********************************************************************************************
+ using HighType = Decay_<T>;
+ using LowType = HighType;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MATHTRAIT SPECIALIZATION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Macro for the creation of MathTrait specializations for the built-in data types.
+// \ingroup math_traits
+//
+// This macro is used for the setup of the MathTrait specializations for the built-in data types.
+*/
+#define BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION(T1,T2,HIGH,LOW) \
+ template<> \
+ struct MathTrait< T1, T2 > \
+ { \
+ using HighType = HIGH; \
+ using LowType = LOW; \
+ }
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Macro for the creation of MathTrait specializations for the complex data type.
+// \ingroup math_traits
+//
+// This macro is used for the setup of the MathTrait specializations for the complex data type.
+*/
+#define BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( T1 ) \
+ template< typename T2 > \
+ struct MathTrait< T1, complex<T2> > \
+ { \
+ using HighType = complex<T2>; \
+ using LowType = T1; \
+ }; \
+ template< typename T2 > \
+ struct MathTrait< complex<T2>, T1 > \
+ { \
+ using HighType = complex<T2>; \
+ using LowType = T1; \
+ }
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UNSIGNED CHAR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , unsigned char , unsigned char , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , char , char , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , signed char , signed char , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , wchar_t , wchar_t , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , unsigned short, unsigned short, unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , short , short , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , unsigned int , unsigned int , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , int , int , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , unsigned long , unsigned long , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , long , long , unsigned char );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , std::size_t , std::size_t , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , std::ptrdiff_t, std::ptrdiff_t, unsigned char );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , float , float , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , double , double , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned char , long double , long double , unsigned char );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CHAR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , unsigned char , char , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , char , char , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , signed char , signed char , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , wchar_t , wchar_t , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , unsigned short, unsigned short, char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , short , short , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , unsigned int , unsigned int , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , int , int , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , unsigned long , unsigned long , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , long , long , char );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , std::size_t , std::size_t , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , std::ptrdiff_t, std::ptrdiff_t, char );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , float , float , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , double , double , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( char , long double , long double , char );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIGNED CHAR SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , unsigned char , signed char , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , char , signed char , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , signed char , signed char , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , wchar_t , wchar_t , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , unsigned short, unsigned short, signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , short , short , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , unsigned int , unsigned int , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , int , int , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , unsigned long , unsigned long , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , long , long , signed char );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , std::size_t , std::size_t , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , std::ptrdiff_t, std::ptrdiff_t, signed char );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , float , float , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , double , double , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( signed char , long double , long double , signed char );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// WCHAR_T SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , unsigned char , wchar_t , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , char , wchar_t , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , signed char , wchar_t , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , wchar_t , wchar_t , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , unsigned short, unsigned short, wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , short , short , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , unsigned int , unsigned int , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , int , int , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , unsigned long , unsigned long , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , long , long , wchar_t );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , std::size_t , std::size_t , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , std::ptrdiff_t, std::ptrdiff_t, wchar_t );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , float , float , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , double , double , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( wchar_t , long double , long double , wchar_t );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UNSIGNED SHORT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, unsigned char , unsigned short, unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, char , unsigned short, char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, signed char , unsigned short, signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, wchar_t , unsigned short, wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, unsigned short, unsigned short, unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, short , short , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, unsigned int , unsigned int , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, int , int , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, unsigned long , unsigned long , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, long , long , unsigned short );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, std::size_t , std::size_t , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, std::ptrdiff_t, std::ptrdiff_t, unsigned short );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, float , float , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, double , double , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned short, long double , long double , unsigned short );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SHORT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , unsigned char , short , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , char , short , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , signed char , short , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , wchar_t , short , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , unsigned short, short , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , short , short , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , unsigned int , unsigned int , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , int , int , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , unsigned long , unsigned long , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , long , long , short );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , std::size_t , std::size_t , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , std::ptrdiff_t, std::ptrdiff_t, short );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , float , float , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , double , double , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( short , long double , long double , short );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UNSIGNED INT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , unsigned char , unsigned int , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , char , unsigned int , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , signed char , unsigned int , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , wchar_t , unsigned int , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , unsigned short, unsigned int , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , short , unsigned int , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , unsigned int , unsigned int , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , int , int , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , unsigned long , unsigned long , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , long , long , unsigned int );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , std::size_t , std::size_t , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , std::ptrdiff_t, std::ptrdiff_t, unsigned int );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , float , float , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , double , double , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned int , long double , long double , unsigned int );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// INT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , unsigned char , int , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , char , int , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , signed char , int , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , wchar_t , int , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , unsigned short, int , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , short , int , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , unsigned int , int , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , int , int , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , unsigned long , unsigned long , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , long , long , int );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , std::size_t , std::size_t , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , std::ptrdiff_t, std::ptrdiff_t, int );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , float , float , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , double , double , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( int , long double , long double , int );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UNSIGNED LONG SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , unsigned char , unsigned long , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , char , unsigned long , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , signed char , unsigned long , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , wchar_t , unsigned long , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , unsigned short, unsigned long , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , short , unsigned long , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , unsigned int , unsigned long , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , int , unsigned long , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , unsigned long , unsigned long , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , long , long , unsigned long );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , std::size_t , std::size_t , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , std::ptrdiff_t, std::ptrdiff_t, unsigned long );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , float , float , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , double , double , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( unsigned long , long double , long double , unsigned long );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LONG SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , unsigned char , long , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , char , long , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , signed char , long , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , wchar_t , long , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , unsigned short, long , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , short , long , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , unsigned int , long , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , int , long , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , unsigned long , long , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , long , long , long );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , std::size_t , std::size_t , long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , std::ptrdiff_t, std::ptrdiff_t, long );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , float , float , long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , double , double , long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long , long double , long double , long );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SIZE_T SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+#if defined(_WIN64)
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , unsigned char , std::size_t , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , char , std::size_t , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , signed char , std::size_t , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , wchar_t , std::size_t , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , unsigned short, std::size_t , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , short , std::size_t , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , unsigned int , std::size_t , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , int , std::size_t , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , unsigned long , std::size_t , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , long , std::size_t , long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , std::size_t , std::size_t , std::size_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , std::ptrdiff_t, std::ptrdiff_t, std::size_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , float , float , std::size_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , double , double , std::size_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::size_t , long double , long double , std::size_t );
+/*! \endcond */
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// PTRDIFF_T SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+#if defined(_WIN64)
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, unsigned char , std::ptrdiff_t, unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, char , std::ptrdiff_t, char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, signed char , std::ptrdiff_t, signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, wchar_t , std::ptrdiff_t, wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, unsigned short, std::ptrdiff_t, unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, short , std::ptrdiff_t, short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, unsigned int , std::ptrdiff_t, unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, int , std::ptrdiff_t, int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, unsigned long , std::ptrdiff_t, unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, long , std::ptrdiff_t, long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, std::size_t , std::ptrdiff_t, std::size_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, std::ptrdiff_t, std::ptrdiff_t, std::ptrdiff_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, float , float , std::ptrdiff_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, double , double , std::ptrdiff_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t, long double , long double , std::ptrdiff_t );
+/*! \endcond */
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FLOAT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , unsigned char , float , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , char , float , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , signed char , float , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , wchar_t , float , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , unsigned short, float , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , short , float , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , unsigned int , float , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , int , float , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , unsigned long , float , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , long , float , long );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , std::size_t , float , std::size_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , std::ptrdiff_t, float , std::ptrdiff_t );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , float , float , float );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , double , double , float );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( float , long double , long double , float );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DOUBLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , unsigned char , double , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , char , double , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , signed char , double , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , wchar_t , double , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , unsigned short, double , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , short , double , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , unsigned int , double , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , int , double , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , unsigned long , double , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , long , double , long );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , std::size_t , double , std::size_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , std::ptrdiff_t, double , std::ptrdiff_t );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , float , double , float );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , double , double , double );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( double , long double , long double , double );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LONG DOUBLE SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+// Type 1 Type 2 High type Low type
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , unsigned char , long double , unsigned char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , char , long double , char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , signed char , long double , signed char );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , wchar_t , long double , wchar_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , unsigned short, long double , unsigned short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , short , long double , short );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , unsigned int , long double , unsigned int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , int , long double , int );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , unsigned long , long double , unsigned long );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , long , long double , long );
+#if defined(_WIN64)
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , std::size_t , long double , std::size_t );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , std::ptrdiff_t, long double , std::ptrdiff_t );
+#endif
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , float , long double , float );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , double , long double , double );
+BLAZE_CREATE_BUILTIN_MATHTRAIT_SPECIALIZATION( long double , long double , long double , long double );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPLEX SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( unsigned char );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( char );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( signed char );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( wchar_t );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( unsigned short );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( short );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( unsigned int );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( int );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( unsigned long );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( long );
+#if defined(_WIN64)
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( std::size_t );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( std::ptrdiff_t );
+#endif
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( float );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( double );
+BLAZE_CREATE_COMPLEX_MATHTRAIT_SPECIALIZATION( long double );
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, typename T2 >
+struct MathTrait< complex<T1>, complex<T2> >
+{
+ using HighType = complex<typename MathTrait<T1,T2>::HighType>;
+ using LowType = complex<typename MathTrait<T1,T2>::LowType>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/MultExprTrait.h b/src/cpu/blaze/math/traits/MultExprTrait.h
new file mode 100644
index 00000000..901f8cbe
--- /dev/null
+++ b/src/cpu/blaze/math/traits/MultExprTrait.h
@@ -0,0 +1,349 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/MultExprTrait.h
+// \brief Header file for the MultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_MULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_MULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DMatDMatMultExprTrait.h>
+#include <blaze/math/traits/DMatDVecMultExprTrait.h>
+#include <blaze/math/traits/DMatScalarMultExprTrait.h>
+#include <blaze/math/traits/DMatSMatMultExprTrait.h>
+#include <blaze/math/traits/DMatSVecMultExprTrait.h>
+#include <blaze/math/traits/DMatTDMatMultExprTrait.h>
+#include <blaze/math/traits/DMatTSMatMultExprTrait.h>
+#include <blaze/math/traits/DVecDVecMultExprTrait.h>
+#include <blaze/math/traits/DVecScalarMultExprTrait.h>
+#include <blaze/math/traits/DVecSVecMultExprTrait.h>
+#include <blaze/math/traits/DVecTDVecMultExprTrait.h>
+#include <blaze/math/traits/DVecTSVecMultExprTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SMatDMatMultExprTrait.h>
+#include <blaze/math/traits/SMatDVecMultExprTrait.h>
+#include <blaze/math/traits/SMatScalarMultExprTrait.h>
+#include <blaze/math/traits/SMatSMatMultExprTrait.h>
+#include <blaze/math/traits/SMatSVecMultExprTrait.h>
+#include <blaze/math/traits/SMatTDMatMultExprTrait.h>
+#include <blaze/math/traits/SMatTSMatMultExprTrait.h>
+#include <blaze/math/traits/SVecDVecMultExprTrait.h>
+#include <blaze/math/traits/SVecScalarMultExprTrait.h>
+#include <blaze/math/traits/SVecSVecMultExprTrait.h>
+#include <blaze/math/traits/SVecTDVecMultExprTrait.h>
+#include <blaze/math/traits/SVecTSVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatDMatMultExprTrait.h>
+#include <blaze/math/traits/TDMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatScalarMultExprTrait.h>
+#include <blaze/math/traits/TDMatSMatMultExprTrait.h>
+#include <blaze/math/traits/TDMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TDMatTDMatMultExprTrait.h>
+#include <blaze/math/traits/TDMatTSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecDVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecScalarMultExprTrait.h>
+#include <blaze/math/traits/TDVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecSVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TDVecTSVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatDMatMultExprTrait.h>
+#include <blaze/math/traits/TSMatDVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatScalarMultExprTrait.h>
+#include <blaze/math/traits/TSMatSMatMultExprTrait.h>
+#include <blaze/math/traits/TSMatSVecMultExprTrait.h>
+#include <blaze/math/traits/TSMatTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSMatTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecDVecMultExprTrait.h>
+#include <blaze/math/traits/TSVecScalarMultExprTrait.h>
+#include <blaze/math/traits/TSVecSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecSVecMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSMatMultExprTrait.h>
+#include <blaze/math/traits/TSVecTSVecMultExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the resulting expression type of a multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a multiplication expression
+// between scalars, vectors, and matrices. Given the two types \a T1 and \a T2, which must be
+// either scalar, vector, or matrix types, the nested type \a Type corresponds to the resulting
+// return type. In case \a T1 or \a T2 don't fit or if the two types cannot be multiplied, the
+// resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename T1 // Type of the left-hand side multiplication operand
+ , typename T2 > // Type of the right-hand side multiplication operand
+struct MultExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T1>
+ , If_< IsDenseMatrix<T1>
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T2>
+ , DMatDMatMultExprTrait<T1,T2>
+ , DMatTDMatMultExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , DMatSMatMultExprTrait<T1,T2>
+ , DMatTSMatMultExprTrait<T1,T2> > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsColumnVector<T2>
+ , DMatDVecMultExprTrait<T1,T2>
+ , Failure >
+ , If_< IsColumnVector<T2>
+ , DMatSVecMultExprTrait<T1,T2>
+ , Failure > >
+ , If_< IsNumeric<T2>
+ , DMatScalarMultExprTrait<T1,T2>
+ , Failure > > >
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T2>
+ , TDMatDMatMultExprTrait<T1,T2>
+ , TDMatTDMatMultExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TDMatSMatMultExprTrait<T1,T2>
+ , TDMatTSMatMultExprTrait<T1,T2> > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsColumnVector<T2>
+ , TDMatDVecMultExprTrait<T1,T2>
+ , Failure >
+ , If_< IsColumnVector<T2>
+ , TDMatSVecMultExprTrait<T1,T2>
+ , Failure > >
+ , If_< IsNumeric<T2>
+ , TDMatScalarMultExprTrait<T1,T2>
+ , Failure > > > >
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T2>
+ , SMatDMatMultExprTrait<T1,T2>
+ , SMatTDMatMultExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , SMatSMatMultExprTrait<T1,T2>
+ , SMatTSMatMultExprTrait<T1,T2> > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsColumnVector<T2>
+ , SMatDVecMultExprTrait<T1,T2>
+ , Failure >
+ , If_< IsColumnVector<T2>
+ , SMatSVecMultExprTrait<T1,T2>
+ , Failure > >
+ , If_< IsNumeric<T2>
+ , SMatScalarMultExprTrait<T1,T2>
+ , Failure > > >
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T2>
+ , TSMatDMatMultExprTrait<T1,T2>
+ , TSMatTDMatMultExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TSMatSMatMultExprTrait<T1,T2>
+ , TSMatTSMatMultExprTrait<T1,T2> > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsColumnVector<T2>
+ , TSMatDVecMultExprTrait<T1,T2>
+ , Failure >
+ , If_< IsColumnVector<T2>
+ , TSMatSVecMultExprTrait<T1,T2>
+ , Failure > >
+ , If_< IsNumeric<T2>
+ , TSMatScalarMultExprTrait<T1,T2>
+ , Failure > > > > >
+ , If_< IsVector<T1>
+ , If_< IsDenseVector<T1>
+ , If_< IsRowVector<T1>
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T2>
+ , TDVecDMatMultExprTrait<T1,T2>
+ , TDVecTDMatMultExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TDVecSMatMultExprTrait<T1,T2>
+ , TDVecTSMatMultExprTrait<T1,T2> > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T2>
+ , TDVecTDVecMultExprTrait<T1,T2>
+ , TDVecDVecMultExprTrait<T1,T2> >
+ , If_< IsRowVector<T2>
+ , TDVecTSVecMultExprTrait<T1,T2>
+ , TDVecSVecMultExprTrait<T1,T2> > >
+ , If_< IsNumeric<T2>
+ , TDVecScalarMultExprTrait<T1,T2>
+ , Failure > > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T2>
+ , DVecTDVecMultExprTrait<T1,T2>
+ , DVecDVecMultExprTrait<T1,T2> >
+ , If_< IsRowVector<T2>
+ , DVecTSVecMultExprTrait<T1,T2>
+ , DVecSVecMultExprTrait<T1,T2> > >
+ , If_< IsNumeric<T2>
+ , DVecScalarMultExprTrait<T1,T2>
+ , Failure > > >
+ , If_< IsRowVector<T1>
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T2>
+ , TSVecDMatMultExprTrait<T1,T2>
+ , TSVecTDMatMultExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TSVecSMatMultExprTrait<T1,T2>
+ , TSVecTSMatMultExprTrait<T1,T2> > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T2>
+ , TSVecTDVecMultExprTrait<T1,T2>
+ , TSVecDVecMultExprTrait<T1,T2> >
+ , If_< IsRowVector<T2>
+ , TSVecTSVecMultExprTrait<T1,T2>
+ , TSVecSVecMultExprTrait<T1,T2> > >
+ , If_< IsNumeric<T2>
+ , TSVecScalarMultExprTrait<T1,T2>
+ , Failure > > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T2>
+ , SVecTDVecMultExprTrait<T1,T2>
+ , SVecDVecMultExprTrait<T1,T2> >
+ , If_< IsRowVector<T2>
+ , SVecTSVecMultExprTrait<T1,T2>
+ , SVecSVecMultExprTrait<T1,T2> > >
+ , If_< IsNumeric<T2>
+ , SVecScalarMultExprTrait<T1,T2>
+ , Failure > > > >
+ , If_< IsNumeric<T1>
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T2>
+ , DMatScalarMultExprTrait<T2,T1>
+ , TDMatScalarMultExprTrait<T2,T1> >
+ , If_< IsRowMajorMatrix<T2>
+ , SMatScalarMultExprTrait<T2,T1>
+ , TSMatScalarMultExprTrait<T2,T1> > >
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T2>
+ , TDVecScalarMultExprTrait<T2,T1>
+ , DVecScalarMultExprTrait<T2,T1> >
+ , If_< IsRowVector<T2>
+ , TSVecScalarMultExprTrait<T2,T1>
+ , SVecScalarMultExprTrait<T2,T1> > >
+ , If_< IsNumeric<T2>
+ , MultTrait<T1,T2>
+ , Failure > > >
+ , Failure > > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , MultExprTrait< Decay_<T1>, Decay_<T2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the MultExprTrait class template.
+// \ingroup math_traits
+//
+// The MultExprTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the MultExprTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename MultExprTrait<T1,T2>::Type;
+ using Type2 = MultExprTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side multiplication operand
+ , typename T2 > // Type of the right-hand side multiplication operand
+using MultExprTrait_ = typename MultExprTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/MultTrait.h b/src/cpu/blaze/math/traits/MultTrait.h
new file mode 100644
index 00000000..dff5e2b4
--- /dev/null
+++ b/src/cpu/blaze/math/traits/MultTrait.h
@@ -0,0 +1,236 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/MultTrait.h
+// \brief Header file for the multiplication trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_MULTTRAIT_H_
+#define _BLAZE_MATH_TRAITS_MULTTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/CommonType.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the MultTrait class.
+// \ingroup math_traits
+//
+// \section multtrait_general General
+//
+// The MultTrait class template offers the possibility to select the resulting data type of
+// a generic multiplication operation between the two given types \a T1 and \a T2. MultTrait
+// defines the nested type \a Type, which represents the resulting data type of the multiplication.
+// In case the two types \a T1 and \a T2 cannot be multiplied, a compilation error is created.
+// Note that \c const and \c volatile qualifiers and reference modifiers are generally ignored.
+//
+// Per default, MultTrait supports all built-in data types. Additionally, the Blaze library
+// provides appropriate specializations for the following user-defined arithmetic types:
+//
+// <ul>
+// <li>std::complex</li>
+// <li>blaze::StaticVector</li>
+// <li>blaze::HybridVector</li>
+// <li>blaze::DynamicVector</li>
+// <li>blaze::CustomVector</li>
+// <li>blaze::CompressedVector</li>
+// <li>blaze::StaticMatrix</li>
+// <li>blaze::HybridMatrix</li>
+// <li>blaze::DynamicMatrix</li>
+// <li>blaze::CustomMatrix</li>
+// <li>blaze::CompressedMatrix</li>
+// <li>blaze::SymmetricMatrix</li>
+// <li>blaze::HermitianMatrix</li>
+// <li>blaze::LowerMatrix</li>
+// <li>blaze::UniLowerMatrix</li>
+// <li>blaze::StrictlyLowerMatrix</li>
+// <li>blaze::UpperMatrix</li>
+// <li>blaze::UniUpperMatrix</li>
+// <li>blaze::StrictlyUpperMatrix</li>
+// <li>blaze::DiagonalMatrix</li>
+// </ul>
+//
+//
+// \n \section multtrait_specializations Creating custom specializations
+//
+// MultTrait is guaranteed to work for all data types that provide a multiplication operator
+// (i.e. \c operator*). In order to add support for user-defined data types that either don't
+// provide a multiplication operator or whose addition operator returns a proxy object instead
+// of a concrete type (as it is common in expression template libraries) it is possible to
+// specialize the MultTrait template. The following example shows the according specialization
+// for the multiplication between two dynamic column vectors:
+
+ \code
+ template< typename T1, typename T2 >
+ struct MultTrait< DynamicVector<T1,columnVector>, DynamicVector<T2,columnVector> >
+ {
+ typedef DynamicVector< typename MultTrait<T1,T2>::Type, columnVector > Type;
+ };
+ \endcode
+
+// \n \section multtrait_examples Examples
+//
+// The following example demonstrates the use of the MultTrait template, where depending on
+// the two given data types the resulting data type is selected:
+
+ \code
+ template< typename T1, typename T2 > // The two generic types
+ typename MultTrait<T1,T2>::Type // The resulting generic return type
+ mult( const T1& t1, const T2& t2 ) //
+ { // The function 'mult' returns the
+ return t1 * t2; // product of the two given values
+ } //
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct MultTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type1 = Decay_<T1>;
+ using Type2 = Decay_<T2>;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct MultType { using Type = decltype( std::declval<Type1>() * std::declval<Type2>() ); };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , MultTrait<Type1,Type2>
+ , MultType >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the MultTrait class template for a complex and a built-in type.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct MultTrait< complex<T1>, T2, EnableIf_< IsBuiltin<T2> > >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< complex<T1> , T2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the MultTrait class template for a built-in and a complex type.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct MultTrait< T1, complex<T2>, EnableIf_< IsBuiltin<T1> > >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< T1, complex<T2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the MultTrait class template for two complex types.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct MultTrait< complex<T1>, complex<T2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< complex<T1>, complex<T2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the MultTrait class template.
+// \ingroup math_traits
+//
+// The MultTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the MultTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename MultTrait<T1,T2>::Type;
+ using Type2 = MultTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1, typename T2 >
+using MultTrait_ = typename MultTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/RealTrait.h b/src/cpu/blaze/math/traits/RealTrait.h
new file mode 100644
index 00000000..d51a9523
--- /dev/null
+++ b/src/cpu/blaze/math/traits/RealTrait.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/RealTrait.h
+// \brief Header file for the real trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_REALTRAIT_H_
+#define _BLAZE_MATH_TRAITS_REALTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the RealTrait class.
+// \ingroup math_traits
+//
+// The RealTrait class template offers the possibility to select the resulting data type of a
+// generic \a real operation on the given type \a T. Given the type \a T, which must either be
+// a scalar, vector, or matrix type, the nested type \a Type corresponds to the resulting data
+// type of the operation. In case the type of \a T doesn't fit or if no \a real operation exists
+// for the type, the resulting data type \a Type is set to \a INVALID_TYPE. Note that \a const
+// and \a volatile qualifiers and reference modifiers are generally ignored.
+*/
+template< typename T > // Type of the operand
+struct RealTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct MatrixOrVector {
+ using RT = typename RealTrait< ElementType_<T> >::Type;
+ using Type = typename T::template Rebind<RT>::Other;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Builtin {
+ using Type = T;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Complex {
+ using Type = typename T::value_type;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure {
+ using Type = INVALID_TYPE;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< Or< IsMatrix<T>, IsVector<T> >
+ , MatrixOrVector
+ , If_< IsBuiltin<T>
+ , Builtin
+ , If_< IsComplex<T>
+ , Complex
+ , Failure > > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , RealTrait< Decay_<T> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RealTrait class template.
+// \ingroup math_traits
+//
+// The RealTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the RealTrait class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename RealTrait<T>::Type;
+ using Type2 = RealTrait_<T>;
+ \endcode
+*/
+template< typename T > // Type of the operand
+using RealTrait_ = typename RealTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/RowExprTrait.h b/src/cpu/blaze/math/traits/RowExprTrait.h
new file mode 100644
index 00000000..fe1bb302
--- /dev/null
+++ b/src/cpu/blaze/math/traits/RowExprTrait.h
@@ -0,0 +1,139 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/RowExprTrait.h
+// \brief Header file for the RowExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_ROWEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_ROWEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/views/Forward.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type type of a row operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a row operation. Given the
+// dense or sparse matrix type \a MT, the nested type \a Type corresponds to the resulting return
+// type. In case the given type is neither a dense nor a sparse matrix type, the resulting data
+// type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the matrix operand
+struct RowExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Result*******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T >
+ struct Result {
+ using Type = Row<T,IsRowMajorMatrix<T>::value,IsDenseMatrix<T>::value,IsSymmetric<T>::value>;
+ };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = RemoveReference_<MT>;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsComputation<Tmp>, IsTransExpr<Tmp> >
+ , If_< Or< IsConst<Tmp>, IsVolatile<Tmp> >
+ , RowExprTrait< RemoveCV_<Tmp> >
+ , Failure >
+ , If_< IsMatrix<Tmp>
+ , Result<Tmp>
+ , Failure >
+ >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RowExprTrait type trait.
+// \ingroup math_traits
+//
+// The RowExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the RowExprTrait class template. For instance, given the matrix type \a MT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename RowExprTrait<MT>::Type;
+ using Type2 = RowExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the matrix operand
+using RowExprTrait_ = typename RowExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/RowTrait.h b/src/cpu/blaze/math/traits/RowTrait.h
new file mode 100644
index 00000000..341b2d15
--- /dev/null
+++ b/src/cpu/blaze/math/traits/RowTrait.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/RowTrait.h
+// \brief Header file for the row trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_ROWTRAIT_H_
+#define _BLAZE_MATH_TRAITS_ROWTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the RowTrait class.
+// \ingroup math_traits
+//
+// \section rowtrait_general General
+//
+// The RowTrait class template offers the possibility to select the resulting data type when
+// creating a view on a specific row of a dense or sparse matrix. RowTrait defines the nested
+// type \a Type, which represents the resulting data type of the row operation. In case the
+// given data type is not a dense or sparse matrix type, the resulting data type \a Type is
+// set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and reference modifiers
+// are generally ignored.
+//
+// Per default, the RowTrait template only supports the following matrix types:
+//
+// <ul>
+// <li>blaze::StaticMatrix</li>
+// <li>blaze::HybridMatrix</li>
+// <li>blaze::DynamicMatrix</li>
+// <li>blaze::CustomMatrix</li>
+// <li>blaze::CompressedMatrix</li>
+// <li>blaze::Submatrix</li>
+// </ul>
+//
+//
+// \section rowtrait_specializations Creating custom specializations
+//
+// It is possible to specialize the RowTrait template for additional user-defined matrix types.
+// The following example shows the according specialization for the DynamicMatrix class template:
+
+ \code
+ template< typename T1, bool SO >
+ struct RowTrait< DynamicMatrix<T1,SO> >
+ {
+ typedef DynamicVector<T1,true> Type;
+ };
+ \endcode
+
+// \n \section rowtrait_examples Examples
+//
+// The following example demonstrates the use of the RowTrait template, where depending on
+// the given matrix type the resulting row type is selected:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of the row type of a row-major dynamic matrix
+ typedef blaze::DynamicMatrix<int,rowMajor> MatrixType1;
+ typedef typename RowTrait<MatrixType1>::Type RowType1;
+
+ // Definition of the row type of the column-major static matrix
+ typedef blaze::StaticMatrix<int,3UL,3UL,columnMajor> MatrixType2;
+ typedef typename RowTrait<MatrixType2>::Type RowType2;
+ \endcode
+*/
+template< typename MT > // Type of the matrix
+struct RowTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , RowTrait< Decay_<MT> >
+ , Failure >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RowTrait type trait.
+// \ingroup math_traits
+//
+// The RowTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the RowTrait class template. For instance, given the matrix type \a MT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename RowTrait<MT>::Type;
+ using Type2 = RowTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the matrix
+using RowTrait_ = typename RowTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatCTransExprTrait.h b/src/cpu/blaze/math/traits/SMatCTransExprTrait.h
new file mode 100644
index 00000000..1fe7f99e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatCTransExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatCTransExprTrait.h
+// \brief Header file for the SMatCTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATCTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATCTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/traits/SMatForEachExprTrait.h>
+#include <blaze/math/traits/SMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix conjugate transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix conjugate transpose operation. Given the row-major sparse matrix type \a MT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a MT is not
+// a row-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the sparse matrix
+struct SMatCTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatTransExprTrait< SMatForEachExprTrait_<MT,Conj> >
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , SMatCTransExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatCTransExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatCTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SMatCTransExprTrait class template. For instance, given the row-major sparse
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SMatCTransExprTrait<MT>::Type;
+ using Type2 = SMatCTransExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the sparse matrix
+using SMatCTransExprTrait_ = typename SMatCTransExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatDMatAddExprTrait.h b/src/cpu/blaze/math/traits/SMatDMatAddExprTrait.h
new file mode 100644
index 00000000..ba49ebd6
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatDMatAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatDMatAddExprTrait.h
+// \brief Header file for the SMatDMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATDMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATDMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/dense matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/dense matrix addition. Given the row-major sparse matrix type \a MT1 and the row-major
+// dense matrix type \a MT2, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a MT1 is not a row-major sparse matrix type or \a MT2 is not a row-major dense
+// matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct SMatDMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsRowMajorMatrix<MT2> >
+ , DMatSMatAddExpr<MT2,MT1,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatDMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatDMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatDMatAddExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatDMatAddExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the row-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SMatDMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatDMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using SMatDMatAddExprTrait_ = typename SMatDMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatDMatMultExprTrait.h b/src/cpu/blaze/math/traits/SMatDMatMultExprTrait.h
new file mode 100644
index 00000000..5c0d29be
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatDMatMultExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatDMatMultExprTrait.h
+// \brief Header file for the SMatDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/dense matrix multiplication. Given the row-major sparse matrix type \a MT1 and the
+// row-major dense matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a row-major sparse matrix type or \a MT2 is
+// not a row-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct SMatDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsRowMajorMatrix<MT2> >
+ , SMatDMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatDMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatDMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatDMatMultExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the row-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SMatDMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatDMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using SMatDMatMultExprTrait_ = typename SMatDMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatDMatSubExprTrait.h b/src/cpu/blaze/math/traits/SMatDMatSubExprTrait.h
new file mode 100644
index 00000000..4182decf
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatDMatSubExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatDMatSubExprTrait.h
+// \brief Header file for the SMatDMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATDMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATDMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/dense matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/dense matrix subtraction. Given the row-major sparse matrix type \a MT1 and the
+// row-major dense matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a row-major sparse matrix type or \a MT2 is
+// not a row-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct SMatDMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsRowMajorMatrix<MT2> >
+ , SMatDMatSubExpr<MT1,MT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatDMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatDMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatDMatSubExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatDMatSubExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the row-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SMatDMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatDMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using SMatDMatSubExprTrait_ = typename SMatDMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatDVecMultExprTrait.h b/src/cpu/blaze/math/traits/SMatDVecMultExprTrait.h
new file mode 100644
index 00000000..026c5353
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatDVecMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatDVecMultExprTrait.h
+// \brief Header file for the SMatDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/dense vector multiplication. Given the row-major sparse matrix type \a MT and the
+// non-transpose dense vector type \a VT, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT is not a row-major sparse matrix type or \a VT is not
+// a non-transpose dense vector type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side row-major sparse matrix
+ , typename VT > // Type of the right-hand side non-transpose dense vector
+struct SMatDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsDenseVector<VT> , IsColumnVector<VT> >
+ , SMatDVecMultExpr<MT,VT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , SMatDVecMultExprTrait< Decay_<MT>, Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatDVecMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatDVecMultExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT and the non-transpose dense vector type \a VT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SMatDVecMultExprTrait<MT,VT>::Type;
+ using Type2 = SMatDVecMultExprTrait_<MT,VT>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side row-major sparse matrix
+ , typename VT > // Type of the right-hand side non-transpose dense vector
+using SMatDVecMultExprTrait_ = typename SMatDVecMultExprTrait<MT,VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatEvalExprTrait.h b/src/cpu/blaze/math/traits/SMatEvalExprTrait.h
new file mode 100644
index 00000000..bb277160
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatEvalExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatEvalExprTrait.h
+// \brief Header file for the SMatEvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATEVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATEVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix evaluation operation. Given the row-major sparse matrix type \a MT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a MT is not a
+// row-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the sparse matrix
+struct SMatEvalExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatEvalExpr<MT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , SMatEvalExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatEvalExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatEvalExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SMatEvalExprTrait class template. For instance, given the row-major sparse
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SMatEvalExprTrait<MT>::Type;
+ using Type2 = SMatEvalExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the sparse matrix
+using SMatEvalExprTrait_ = typename SMatEvalExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatForEachExprTrait.h b/src/cpu/blaze/math/traits/SMatForEachExprTrait.h
new file mode 100644
index 00000000..df83bf49
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatForEachExprTrait.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatForEachExprTrait.h
+// \brief Header file for the SMatForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATFOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATFOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix for-each operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse matrix
+// for-each operation. Given the row-major sparse matrix type \a MT and the custom operation type
+// \a OP, the nested type \a Type corresponds to the resulting expression type. In case \a MT is
+// not a row-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the sparse matrix
+ , typename OP > // Type of the custom operation
+struct SMatForEachExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatForEachExpr<MT,OP,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , SMatForEachExprTrait< Decay_<MT>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatForEachExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SMatForEachExprTrait class template. For instance, given the row-major sparse
+// matrix type \a MT and the custom operation type \a OP the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename SMatForEachExprTrait<MT,OP>::Type;
+ using Type2 = SMatForEachExprTrait_<MT,OP>;
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , typename OP > // Type of the custom operation
+using SMatForEachExprTrait_ = typename SMatForEachExprTrait<MT,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatSMatAddExprTrait.h b/src/cpu/blaze/math/traits/SMatSMatAddExprTrait.h
new file mode 100644
index 00000000..0d25c92e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatSMatAddExprTrait.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatSMatAddExprTrait.h
+// \brief Header file for the SMatSMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATSMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATSMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/sparse matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/sparse matrix addition. Given the two row-major sparse matrix types \a MT1 and
+// \a MT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a MT1 or \a MT2 is not a row-major sparse matrix, the resulting data type
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct SMatSMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , SMatSMatAddExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatSMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatSMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatSMatAddExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatSMatAddExprTrait class template. For instance, given the row-major
+// sparse matrix types \a MT1 and \a MT2 the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SMatSMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatSMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using SMatSMatAddExprTrait_ = typename SMatSMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatSMatMultExprTrait.h b/src/cpu/blaze/math/traits/SMatSMatMultExprTrait.h
new file mode 100644
index 00000000..ab31c214
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatSMatMultExprTrait.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatSMatMultExprTrait.h
+// \brief Header file for the SMatSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/sparse matrix multiplication. Given the two row-major sparse matrix types \a MT1 and
+// \a MT2, the nested type \a Type corresponds to the resulting expression type. In case either
+// \a MT1 or \a MT2 is not a row-major sparse matrix, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct SMatSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , SMatSMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatSMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatSMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatSMatMultExprTrait class template. For instance, given the row-major
+// sparse matrix types \a MT1 and \a MT2 the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SMatSMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatSMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using SMatSMatMultExprTrait_ = typename SMatSMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatSMatSubExprTrait.h b/src/cpu/blaze/math/traits/SMatSMatSubExprTrait.h
new file mode 100644
index 00000000..6e7fb857
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatSMatSubExprTrait.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatSMatSubExprTrait.h
+// \brief Header file for the SMatSMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATSMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATSMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/sparse matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/sparse matrix subtraction. Given the two row-major sparse matrix types \a MT1 and
+// \a MT2, the nested type \a Type corresponds to the resulting expression type. In case either
+// \a MT1 or \a MT2 is not a row-major sparse matrix, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct SMatSMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , SMatSMatSubExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatSMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatSMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatSMatSubExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatSMatSubExprTrait class template. For instance, given the row-major
+// sparse matrix types \a MT1 and \a MT2 the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SMatSMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatSMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using SMatSMatSubExprTrait_ = typename SMatSMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatSVecMultExprTrait.h b/src/cpu/blaze/math/traits/SMatSVecMultExprTrait.h
new file mode 100644
index 00000000..53845a67
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatSVecMultExprTrait.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatSVecMultExprTrait.h
+// \brief Header file for the SMatSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/SMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/sparse vector multiplication. Given the row-major sparse matrix type \a MT and the
+// non-transpose sparse vector type \a VT, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT is not a row-major sparse matrix type or \a VT is not
+// a non-transpose sparse vector type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side row-major sparse matrix
+ , typename VT > // Type of the right-hand side non-transpose sparse vector
+struct SMatSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , If_< IsSymmetric<MT>
+ , TSMatSVecMultExpr< SMatTransExprTrait_<MT>, VT >
+ , SMatSVecMultExpr<MT,VT> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , SMatSVecMultExprTrait< Decay_<MT>, Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatSVecMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatSVecMultExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT and the non-transpose sparse vector type \a VT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SMatSVecMultExprTrait<MT,VT>::Type;
+ using Type2 = SMatSVecMultExprTrait_<MT,VT>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side row-major sparse matrix
+ , typename VT > // Type of the right-hand side non-transpose sparse vector
+using SMatSVecMultExprTrait_ = typename SMatSVecMultExprTrait<MT,VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatScalarDivExprTrait.h b/src/cpu/blaze/math/traits/SMatScalarDivExprTrait.h
new file mode 100644
index 00000000..fdc8af75
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatScalarDivExprTrait.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatScalarDivExprTrait.h
+// \brief Header file for the SMatScalarDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATSCALARDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATSCALARDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the SMatScalarDivExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST
+ , bool Condition >
+struct SMatScalarDivExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<MT> >, IsBuiltin<ST> >
+ , DivTrait_< UnderlyingBuiltin_<MT>, ST >
+ , DivTrait_< UnderlyingNumeric_<MT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< IsInvertible<ScalarType>
+ , SMatScalarMultExpr<MT,ScalarType,false>
+ , SMatScalarDivExpr<MT,ScalarType,false> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SMatScalarDivExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST >
+struct SMatScalarDivExprTraitHelper<MT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/scalar division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/scalar division. Given the row-major sparse matrix type \a MT and the scalar type
+// \a ST, the nested type \a Type corresponds to the resulting expression type. In case either
+// \a MT is not a row-major sparse matrix type or \a ST is not a scalar type, the resulting
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST > // Type of the right-hand side scalar
+struct SMatScalarDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , SMatScalarDivExprTrait< Decay_<MT>, Decay_<ST> >
+ , SMatScalarDivExprTraitHelper<MT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatScalarDivExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatScalarDivExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatScalarDivExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT and the scalar type \a ST the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename SMatScalarDivExprTrait<MT,ST>::Type;
+ using Type2 = SMatScalarDivExprTrait_<MT,ST>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST > // Type of the right-hand side scalar
+using SMatScalarDivExprTrait_ = typename SMatScalarDivExprTrait<MT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatScalarMultExprTrait.h b/src/cpu/blaze/math/traits/SMatScalarMultExprTrait.h
new file mode 100644
index 00000000..5dbccd06
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatScalarMultExprTrait.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatScalarMultExprTrait.h
+// \brief Header file for the SMatScalarMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATSCALARMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATSCALARMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the SMatScalarMultExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST
+ , bool Condition >
+struct SMatScalarMultExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<MT> >, IsBuiltin<ST> >
+ , MultTrait_< UnderlyingBuiltin_<MT>, ST >
+ , MultTrait_< UnderlyingNumeric_<MT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = SMatScalarMultExpr<MT,ScalarType,false>;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SMatScalarMultExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST >
+struct SMatScalarMultExprTraitHelper<MT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/scalar multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/scalar multiplication. Given the row-major sparse matrix type \a MT and the scalar
+// type \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a MT is not a row-major sparse matrix type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST > // Type of the right-hand side scalar
+struct SMatScalarMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , SMatScalarMultExprTrait< Decay_<MT>, Decay_<ST> >
+ , SMatScalarMultExprTraitHelper<MT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatScalarMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatScalarMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatScalarMultExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT and the scalar type \a ST the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename SMatScalarMultExprTrait<MT,ST>::Type;
+ using Type2 = SMatScalarMultExprTrait_<MT,ST>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST > // Type of the right-hand side scalar
+using SMatScalarMultExprTrait_ = typename SMatScalarMultExprTrait<MT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatSerialExprTrait.h b/src/cpu/blaze/math/traits/SMatSerialExprTrait.h
new file mode 100644
index 00000000..3fab26bd
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatSerialExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatSerialExprTrait.h
+// \brief Header file for the SMatSerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATSERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATSERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix serial evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix serial evaluation operation. Given the row-major sparse matrix type \a MT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a MT is not
+// a row-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the sparse matrix
+struct SMatSerialExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatSerialExpr<MT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , SMatSerialExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatSerialExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatSerialExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SMatSerialExprTrait class template. For instance, given the row-major sparse
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SMatSerialExprTrait<MT>::Type;
+ using Type2 = SMatSerialExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the sparse matrix
+using SMatSerialExprTrait_ = typename SMatSerialExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatTDMatAddExprTrait.h b/src/cpu/blaze/math/traits/SMatTDMatAddExprTrait.h
new file mode 100644
index 00000000..136aeca7
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatTDMatAddExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatTDMatAddExprTrait.h
+// \brief Header file for the SMatTDMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATTDMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATTDMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/transpose dense matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/transpose dense matrix addition. Given the row-major sparse matrix type \a MT1 and the
+// column-major dense matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a row-major sparse matrix type or \a MT2 is not
+// a column-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct SMatTDMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsColumnMajorMatrix<MT2> >
+ , TDMatSMatAddExpr<MT2,MT1>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatTDMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatTDMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatTDMatAddExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatTDMatAddExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the column-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SMatTDMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatTDMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using SMatTDMatAddExprTrait_ = typename SMatTDMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatTDMatMultExprTrait.h b/src/cpu/blaze/math/traits/SMatTDMatMultExprTrait.h
new file mode 100644
index 00000000..c5387685
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatTDMatMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatTDMatMultExprTrait.h
+// \brief Header file for the SMatTDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATTDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATTDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/transpose dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/transpose dense matrix multiplication. Given the row-major sparse matrix type \a MT1
+// and the column-major dense matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major sparse matrix type or
+// \a MT2 is not a column-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct SMatTDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsColumnMajorMatrix<MT2> >
+ , SMatTDMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatTDMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatTDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatTDMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatTDMatMultExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the column-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SMatTDMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatTDMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using SMatTDMatMultExprTrait_ = typename SMatTDMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatTDMatSubExprTrait.h b/src/cpu/blaze/math/traits/SMatTDMatSubExprTrait.h
new file mode 100644
index 00000000..50eb0f0b
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatTDMatSubExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatTDMatSubExprTrait.h
+// \brief Header file for the SMatTDMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATTDMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATTDMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/transpose dense matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/transpose dense matrix subtraction. Given the row-major sparse matrix type \a MT1
+// and the column-major dense matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major sparse matrix type or
+// \a MT2 is not a column-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct SMatTDMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsColumnMajorMatrix<MT2> >
+ , SMatTDMatSubExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatTDMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatTDMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatTDMatSubExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatTDMatSubExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the column-major dense matrix type \a MT2 the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SMatTDMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatTDMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using SMatTDMatSubExprTrait_ = typename SMatTDMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatTSMatAddExprTrait.h b/src/cpu/blaze/math/traits/SMatTSMatAddExprTrait.h
new file mode 100644
index 00000000..f396bfce
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatTSMatAddExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatTSMatAddExprTrait.h
+// \brief Header file for the SMatTSMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATTSMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATTSMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/transpose sparse matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/transpose sparse matrix addition. Given the row-major sparse matrix type \a MT1
+// and the column-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major sparse matrix type or
+// \a MT2 is not a column-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct SMatTSMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , SMatTSMatAddExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatTSMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatTSMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatTSMatAddExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatTSMatAddExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the column-major sparse matrix type \a MT2 the following two
+// type definitions are identical:
+
+ \code
+ using Type1 = typename SMatTSMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatTSMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using SMatTSMatAddExprTrait_ = typename SMatTSMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatTSMatMultExprTrait.h b/src/cpu/blaze/math/traits/SMatTSMatMultExprTrait.h
new file mode 100644
index 00000000..07cdf80f
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatTSMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatTSMatMultExprTrait.h
+// \brief Header file for the SMatTSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATTSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATTSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/transpose sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/transpose sparse matrix multiplication. Given the row-major sparse matrix type \a MT1
+// and the column-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major sparse matrix type or
+// \a MT2 is not a column-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct SMatTSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , SMatTSMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatTSMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatTSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatTSMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatTSMatMultExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the column-major sparse matrix type \a MT2 the following two
+// type definitions are identical:
+
+ \code
+ using Type1 = typename SMatTSMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatTSMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using SMatTSMatMultExprTrait_ = typename SMatTSMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatTSMatSubExprTrait.h b/src/cpu/blaze/math/traits/SMatTSMatSubExprTrait.h
new file mode 100644
index 00000000..836cdaa1
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatTSMatSubExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatTSMatSubExprTrait.h
+// \brief Header file for the SMatTSMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATTSMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATTSMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix/transpose sparse matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix/transpose sparse matrix subtraction. Given the row-major sparse matrix type \a MT1
+// and the column-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a row-major sparse matrix type or
+// \a MT2 is not a column-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct SMatTSMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , SMatTSMatSubExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , SMatTSMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatTSMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatTSMatSubExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the SMatTSMatSubExprTrait class template. For instance, given the row-major
+// sparse matrix type \a MT1 and the column-major sparse matrix type \a MT2 the following two
+// type definitions are identical:
+
+ \code
+ using Type1 = typename SMatTSMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = SMatTSMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side row-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using SMatTSMatSubExprTrait_ = typename SMatTSMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SMatTransExprTrait.h b/src/cpu/blaze/math/traits/SMatTransExprTrait.h
new file mode 100644
index 00000000..717bc803
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SMatTransExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SMatTransExprTrait.h
+// \brief Header file for the SMatTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SMATTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SMATTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix transpose operation. Given the row-major sparse matrix type \a MT, the nested type
+// \a Type corresponds to the resulting expression type. In case \a MT is not a row-major
+// sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the sparse matrix
+struct SMatTransExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , SMatTransExpr<MT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , SMatTransExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SMatTransExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SMatTransExprTrait class template. For instance, given the row-major sparse
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SMatTransExprTrait<MT>::Type;
+ using Type2 = SMatTransExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the sparse matrix
+using SMatTransExprTrait_ = typename SMatTransExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecCTransExprTrait.h b/src/cpu/blaze/math/traits/SVecCTransExprTrait.h
new file mode 100644
index 00000000..c5a172c6
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecCTransExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecCTransExprTrait.h
+// \brief Header file for the SVecCTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECCTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECCTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/traits/SVecForEachExprTrait.h>
+#include <blaze/math/traits/SVecTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector conjugate transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector conjugate transpose operation. Given the non-transpose sparse vector type \a VT,
+// the nested type \a Type corresponds to the resulting expression type. In case \a VT is
+// not a non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the sparse vector
+struct SVecCTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecTransExprTrait< SVecForEachExprTrait_<VT,Conj> >
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , SVecCTransExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecCTransExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecCTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SVecCTransExprTrait class template. For instance, given the non-transpose sparse
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecCTransExprTrait<VT>::Type;
+ using Type2 = SVecCTransExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the sparse vector
+using SVecCTransExprTrait_ = typename SVecCTransExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecDVecAddExprTrait.h b/src/cpu/blaze/math/traits/SVecDVecAddExprTrait.h
new file mode 100644
index 00000000..4b8b06af
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecDVecAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecDVecAddExprTrait.h
+// \brief Header file for the SVecDVecAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECDVECADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECDVECADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/dense vector addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/dense vector addition. Given the non-transpose sparse vector type \a VT1 and the
+// non-transpose dense vector type\a VT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT1 is not a non-transpose sparse vector type or \a VT2
+// is not a non-transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct SVecDVecAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2> , IsColumnVector<VT2> >
+ , DVecSVecAddExpr<VT2,VT1,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecDVecAddExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecDVecAddExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecDVecAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecDVecAddExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and the non-transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecDVecAddExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecDVecAddExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using SVecDVecAddExprTrait_ = typename SVecDVecAddExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecDVecCrossExprTrait.h b/src/cpu/blaze/math/traits/SVecDVecCrossExprTrait.h
new file mode 100644
index 00000000..72ba6abb
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecDVecCrossExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecDVecCrossExprTrait.h
+// \brief Header file for the SVecDVecCrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECDVECCROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECDVECCROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/dense vector cross product.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/dense vector cross product. Given the non-transpose sparse vector type \a VT1 and
+// the non-transpose dense vector type\a VT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT1 is not a non-transpose sparse vector
+// type or \a VT2 is not a non-transpose dense vector type, the resulting \a Type is set
+// to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct SVecDVecCrossExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2> , IsColumnVector<VT2> >
+ , SVecDVecCrossExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecDVecCrossExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecDVecCrossExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecDVecCrossExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecDVecCrossExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and the non-transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecDVecCrossExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecDVecCrossExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using SVecDVecCrossExprTrait_ = typename SVecDVecCrossExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecDVecDivExprTrait.h b/src/cpu/blaze/math/traits/SVecDVecDivExprTrait.h
new file mode 100644
index 00000000..3d833b03
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecDVecDivExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecDVecDivExprTrait.h
+// \brief Header file for the SVecDVecDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECDVECDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECDVECDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/dense vector division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/dense vector division. Given the non-transpose sparse vector type \a VT1 and
+// the non-transpose dense vector type\a VT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT1 is not a non-transpose sparse vector
+// type or \a VT2 is not a non-transpose dense vector type, the resulting \a Type is set
+// to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct SVecDVecDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2> , IsColumnVector<VT2> >
+ , SVecDVecDivExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecDVecDivExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecDVecDivExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecDVecDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecDVecDivExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and the non-transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecDVecDivExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecDVecDivExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using SVecDVecDivExprTrait_ = typename SVecDVecDivExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecDVecMultExprTrait.h b/src/cpu/blaze/math/traits/SVecDVecMultExprTrait.h
new file mode 100644
index 00000000..4f684e86
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecDVecMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecDVecMultExprTrait.h
+// \brief Header file for the SVecDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/dense vector multiplication. Given the non-transpose sparse vector type \a VT1 and
+// the non-transpose dense vector type\a VT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT1 is not a non-transpose sparse vector
+// type or \a VT2 is not a non-transpose dense vector type, the resulting \a Type is set
+// to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct SVecDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2> , IsColumnVector<VT2> >
+ , SVecDVecMultExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecDVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecDVecMultExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and the non-transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecDVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecDVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using SVecDVecMultExprTrait_ = typename SVecDVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecDVecSubExprTrait.h b/src/cpu/blaze/math/traits/SVecDVecSubExprTrait.h
new file mode 100644
index 00000000..e5270a56
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecDVecSubExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecDVecSubExprTrait.h
+// \brief Header file for the SVecDVecSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECDVECSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECDVECSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/dense vector subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/dense vector subtraction. Given the non-transpose sparse vector type \a VT1 and the
+// non-transpose dense vector type\a VT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT1 is not a non-transpose sparse vector type or \a VT2
+// is not a non-transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct SVecDVecSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2> , IsColumnVector<VT2> >
+ , SVecDVecSubExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecDVecSubExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecDVecSubExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecDVecSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecDVecSubExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and the non-transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecDVecSubExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecDVecSubExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using SVecDVecSubExprTrait_ = typename SVecDVecSubExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecEvalExprTrait.h b/src/cpu/blaze/math/traits/SVecEvalExprTrait.h
new file mode 100644
index 00000000..7ebb2926
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecEvalExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecEvalExprTrait.h
+// \brief Header file for the SVecEvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECEVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECEVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector evaluation operation. Given the non-transpose sparse vector type \a VT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a VT is not a
+// non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the sparse vector
+struct SVecEvalExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecEvalExpr<VT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , SVecEvalExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecEvalExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecEvalExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SVecEvalExprTrait class template. For instance, given the non-transpose sparse
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecEvalExprTrait<VT>::Type;
+ using Type2 = SVecEvalExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the sparse vector
+using SVecEvalExprTrait_ = typename SVecEvalExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecForEachExprTrait.h b/src/cpu/blaze/math/traits/SVecForEachExprTrait.h
new file mode 100644
index 00000000..14861d9f
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecForEachExprTrait.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecForEachExprTrait.h
+// \brief Header file for the SVecForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECFOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECFOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector for-each operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse vector
+// custom operation. Given the non-transpose sparse vector type \a VT and the custom operation type
+// \a OP, the nested type \a Type corresponds to the resulting expression type. In case \a VT is
+// not a non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the sparse vector
+ , typename OP > // Type of the custom operation
+struct SVecForEachExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecForEachExpr<VT,OP,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , SVecForEachExprTrait< Decay_<VT>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecForEachExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SVecForEachExprTrait class template. For instance, given the non-transpose sparse
+// vector type \a VT and the custom operation type \a OP the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename SVecForEachExprTrait<VT,OP>::Type;
+ using Type2 = SVecForEachExprTrait_<VT,OP>;
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , typename OP > // Type of the custom operation
+using SVecForEachExprTrait_ = typename SVecForEachExprTrait<VT,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecSVecAddExprTrait.h b/src/cpu/blaze/math/traits/SVecSVecAddExprTrait.h
new file mode 100644
index 00000000..a2c839dd
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecSVecAddExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecSVecAddExprTrait.h
+// \brief Header file for the SVecSVecAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECSVECADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECSVECADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/sparse vector addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/sparse vector addition. Given the two non-transpose sparse vector types \a VT1 and
+// \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose sparse vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct SVecSVecAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2> >
+ , SVecSVecAddExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecSVecAddExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecSVecAddExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecSVecAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecSVecAddExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename SVecSVecAddExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecSVecAddExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using SVecSVecAddExprTrait_ = typename SVecSVecAddExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecSVecCrossExprTrait.h b/src/cpu/blaze/math/traits/SVecSVecCrossExprTrait.h
new file mode 100644
index 00000000..2719b310
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecSVecCrossExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecSVecCrossExprTrait.h
+// \brief Header file for the SVecSVecCrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECSVECCROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECSVECCROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/sparse vector cross product.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/sparse vector cross product. Given the two non-transpose sparse vector types \a VT1
+// and \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose sparse vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct SVecSVecCrossExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2> >
+ , SVecSVecCrossExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecSVecCrossExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecSVecCrossExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecSVecCrossExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecSVecCrossExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename SVecSVecCrossExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecSVecCrossExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using SVecSVecCrossExprTrait_ = typename SVecSVecCrossExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecSVecMultExprTrait.h b/src/cpu/blaze/math/traits/SVecSVecMultExprTrait.h
new file mode 100644
index 00000000..d7185e68
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecSVecMultExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecSVecMultExprTrait.h
+// \brief Header file for the SVecSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/sparse vector multiplication. Given the two non-transpose sparse vector types \a VT1
+// and \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose sparse vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct SVecSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2> >
+ , SVecSVecMultExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecSVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecSVecMultExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename SVecSVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecSVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using SVecSVecMultExprTrait_ = typename SVecSVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecSVecSubExprTrait.h b/src/cpu/blaze/math/traits/SVecSVecSubExprTrait.h
new file mode 100644
index 00000000..60de7d72
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecSVecSubExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecSVecSubExprTrait.h
+// \brief Header file for the SVecSVecSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECSVECSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECSVECSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/sparse vector subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/sparse vector subtraction. Given the two non-transpose sparse vector types \a VT1
+// and \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a non-transpose sparse vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct SVecSVecSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsColumnVector<VT2> >
+ , SVecSVecSubExpr<VT1,VT2,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecSVecSubExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecSVecSubExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecSVecSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecSVecSubExprTrait class template. For instance, given the
+// non-transpose sparse vector types \a VT1 and \a VT2 the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename SVecSVecSubExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecSVecSubExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using SVecSVecSubExprTrait_ = typename SVecSVecSubExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecScalarDivExprTrait.h b/src/cpu/blaze/math/traits/SVecScalarDivExprTrait.h
new file mode 100644
index 00000000..b6d44743
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecScalarDivExprTrait.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecScalarDivExprTrait.h
+// \brief Header file for the SVecScalarDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECSCALARDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECSCALARDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the SVecScalarDivExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST
+ , bool Condition >
+struct SVecScalarDivExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<VT> >, IsBuiltin<ST> >
+ , DivTrait_< UnderlyingBuiltin_<VT>, ST >
+ , DivTrait_< UnderlyingNumeric_<VT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< IsInvertible<ScalarType>
+ , SVecScalarMultExpr<VT,ScalarType,false>
+ , SVecScalarDivExpr<VT,ScalarType,false> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SVecScalarDivExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST >
+struct SVecScalarDivExprTraitHelper<VT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/scalar division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/scalar division. Given the non-transpose sparse vector type \a VT and the scalar
+// type \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT is not a non-transpose sparse vector type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST > // Type of the right-hand side scalar
+struct SVecScalarDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsSparseVector<VT>, IsColumnVector<VT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , SVecScalarDivExprTrait< Decay_<VT>, Decay_<ST> >
+ , SVecScalarDivExprTraitHelper<VT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecScalarDivExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecScalarDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecScalarDivExprTrait class template. For instance, given the
+// non-transpose sparse vector type \a VT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SVecScalarDivExprTrait<VT,ST>::Type;
+ using Type2 = SVecScalarDivExprTrait_<VT,ST>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST > // Type of the right-hand side scalar
+using SVecScalarDivExprTrait_ = typename SVecScalarDivExprTrait<VT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecScalarMultExprTrait.h b/src/cpu/blaze/math/traits/SVecScalarMultExprTrait.h
new file mode 100644
index 00000000..3542c9d6
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecScalarMultExprTrait.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecScalarMultExprTrait.h
+// \brief Header file for the SVecScalarMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECSCALARMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECSCALARMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the SVecScalarMultExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST
+ , bool Condition >
+struct SVecScalarMultExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<VT> >, IsBuiltin<ST> >
+ , MultTrait_< UnderlyingBuiltin_<VT>, ST >
+ , MultTrait_< UnderlyingNumeric_<VT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = SVecScalarMultExpr<VT,ScalarType,false>;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SVecScalarMultExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST >
+struct SVecScalarMultExprTraitHelper<VT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/scalar multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/scalar multiplication. Given the non-transpose sparse vector type \a VT and the
+// scalar type \a ST, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a VT is not a non-transpose sparse vector type or \a ST is not a scalar
+// type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST > // Type of the right-hand side scalar
+struct SVecScalarMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsSparseVector<VT>, IsColumnVector<VT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , SVecScalarMultExprTrait< Decay_<VT>, Decay_<ST> >
+ , SVecScalarMultExprTraitHelper<VT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecScalarMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecScalarMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecScalarMultExprTrait class template. For instance, given the
+// non-transpose sparse vector type \a VT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SVecScalarMultExprTrait<VT,ST>::Type;
+ using Type2 = SVecScalarMultExprTrait_<VT,ST>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST > // Type of the right-hand side scalar
+using SVecScalarMultExprTrait_ = typename SVecScalarMultExprTrait<VT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecSerialExprTrait.h b/src/cpu/blaze/math/traits/SVecSerialExprTrait.h
new file mode 100644
index 00000000..d0e3535e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecSerialExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecSerialExprTrait.h
+// \brief Header file for the SVecSerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECSERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECSERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector serial evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector serial evaluation operation. Given the non-transpose sparse vector type \a VT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a VT is not a
+// non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the sparse vector
+struct SVecSerialExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecSerialExpr<VT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , SVecSerialExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecSerialExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecSerialExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SVecSerialExprTrait class template. For instance, given the non-transpose sparse
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecSerialExprTrait<VT>::Type;
+ using Type2 = SVecSerialExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the sparse vector
+using SVecSerialExprTrait_ = typename SVecSerialExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecTDVecMultExprTrait.h b/src/cpu/blaze/math/traits/SVecTDVecMultExprTrait.h
new file mode 100644
index 00000000..de94b881
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecTDVecMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecTDVecMultExprTrait.h
+// \brief Header file for the SVecTDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECTDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECTDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/transpose dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/transpose dense vector multiplication (outer product). Given the non-transpose
+// sparse vector type \a VT1 and the transpose dense vector type \a VT2, the nested type
+// \a Type corresponds to the resulting expression type. In case either \a VT1 is not a
+// non-transpose sparse vector type or \a VT2 is not a transpose dense vector type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct SVecTDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsDenseVector<VT2> , IsRowVector<VT2> >
+ , SVecTDVecMultExpr<VT1,VT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecTDVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecTDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecTDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecTDVecMultExprTrait class template. For instance, given the
+// non-transpose sparse vector type \a VT1 and the transpose dense vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecTDVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecTDVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using SVecTDVecMultExprTrait_ = typename SVecTDVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecTSVecMultExprTrait.h b/src/cpu/blaze/math/traits/SVecTSVecMultExprTrait.h
new file mode 100644
index 00000000..333792f7
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecTSVecMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecTSVecMultExprTrait.h
+// \brief Header file for the SVecTSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECTSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECTSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/transpose sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/transpose sparse vector multiplication (outer product). Given the non-transpose
+// sparse vector type \a VT1 and the transpose sparse vector type \a VT2, the nested type
+// \a Type corresponds to the resulting expression type. In case either \a VT1 is not a
+// non-transpose sparse vector type or \a VT2 is not a transpose sparse vector type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct SVecTSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsColumnVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , SVecTSVecMultExpr<VT1,VT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , SVecTSVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecTSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecTSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the SVecTSVecMultExprTrait class template. For instance, given the
+// non-transpose sparse vector type \a VT1 and the transpose sparse vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecTSVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = SVecTSVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side non-transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using SVecTSVecMultExprTrait_ = typename SVecTSVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SVecTransExprTrait.h b/src/cpu/blaze/math/traits/SVecTransExprTrait.h
new file mode 100644
index 00000000..d9e1aaad
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SVecTransExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SVecTransExprTrait.h
+// \brief Header file for the SVecTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SVECTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SVECTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector transpose operation. Given the non-transpose sparse vector type \a VT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a VT is not a
+// non-transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the sparse vector
+struct SVecTransExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsColumnVector<VT> >
+ , SVecTransExpr<VT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , SVecTransExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SVecTransExprTrait class template.
+// \ingroup math_traits
+//
+// The SVecTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SVecTransExprTrait class template. For instance, given the non-transpose sparse
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SVecTransExprTrait<VT>::Type;
+ using Type2 = SVecTransExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the sparse vector
+using SVecTransExprTrait_ = typename SVecTransExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SerialExprTrait.h b/src/cpu/blaze/math/traits/SerialExprTrait.h
new file mode 100644
index 00000000..51f633cd
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SerialExprTrait.h
@@ -0,0 +1,147 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SerialExprTrait.h
+// \brief Header file for the SerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DMatSerialExprTrait.h>
+#include <blaze/math/traits/DVecSerialExprTrait.h>
+#include <blaze/math/traits/SMatSerialExprTrait.h>
+#include <blaze/math/traits/SVecSerialExprTrait.h>
+#include <blaze/math/traits/TDMatSerialExprTrait.h>
+#include <blaze/math/traits/TDVecSerialExprTrait.h>
+#include <blaze/math/traits/TSMatSerialExprTrait.h>
+#include <blaze/math/traits/TSVecSerialExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of a serial evaluation expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a serial evaluation
+// expression. Given the type \a T, which must either be a vector or matrix type, the nested
+// type \a Type corresponds to the resulting return type. In case the type of \a T doesn't
+// fit or if no serial evaluation operation exists for the type, the resulting data type
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename T > // Type of the serial evaluation operand
+struct SerialExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T>
+ , If_< IsDenseMatrix<T>
+ , If_< IsRowMajorMatrix<T>
+ , DMatSerialExprTrait<T>
+ , TDMatSerialExprTrait<T> >
+ , If_< IsRowMajorMatrix<T>
+ , SMatSerialExprTrait<T>
+ , TSMatSerialExprTrait<T> > >
+ , If_< IsVector<T>
+ , If_< IsDenseVector<T>
+ , If_< IsRowVector<T>
+ , TDVecSerialExprTrait<T>
+ , DVecSerialExprTrait<T> >
+ , If_< IsRowVector<T>
+ , TSVecSerialExprTrait<T>
+ , SVecSerialExprTrait<T> > >
+ , Failure > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , SerialExprTrait< Decay_<T> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SerialExprTrait class template.
+// \ingroup math_traits
+//
+// The SerialExprTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the SerialExprTrait class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename SerialExprTrait<T>::Type;
+ using Type2 = SerialExprTrait_<T>;
+ \endcode
+*/
+template< typename T > // Type of the serial evaluation operand
+using SerialExprTrait_ = typename SerialExprTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SubExprTrait.h b/src/cpu/blaze/math/traits/SubExprTrait.h
new file mode 100644
index 00000000..e497b236
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SubExprTrait.h
@@ -0,0 +1,225 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SubExprTrait.h
+// \brief Header file for the SubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DMatDMatSubExprTrait.h>
+#include <blaze/math/traits/DMatSMatSubExprTrait.h>
+#include <blaze/math/traits/DMatTDMatSubExprTrait.h>
+#include <blaze/math/traits/DMatTSMatSubExprTrait.h>
+#include <blaze/math/traits/DVecDVecSubExprTrait.h>
+#include <blaze/math/traits/DVecSVecSubExprTrait.h>
+#include <blaze/math/traits/SMatDMatSubExprTrait.h>
+#include <blaze/math/traits/SMatSMatSubExprTrait.h>
+#include <blaze/math/traits/SMatTDMatSubExprTrait.h>
+#include <blaze/math/traits/SMatTSMatSubExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SVecDVecSubExprTrait.h>
+#include <blaze/math/traits/SVecSVecSubExprTrait.h>
+#include <blaze/math/traits/TDMatDMatSubExprTrait.h>
+#include <blaze/math/traits/TDMatSMatSubExprTrait.h>
+#include <blaze/math/traits/TDMatTDMatSubExprTrait.h>
+#include <blaze/math/traits/TDMatTSMatSubExprTrait.h>
+#include <blaze/math/traits/TDVecTDVecSubExprTrait.h>
+#include <blaze/math/traits/TDVecTSVecSubExprTrait.h>
+#include <blaze/math/traits/TSMatDMatSubExprTrait.h>
+#include <blaze/math/traits/TSMatSMatSubExprTrait.h>
+#include <blaze/math/traits/TSMatTDMatSubExprTrait.h>
+#include <blaze/math/traits/TSMatTSMatSubExprTrait.h>
+#include <blaze/math/traits/TSVecTDVecSubExprTrait.h>
+#include <blaze/math/traits/TSVecTSVecSubExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of a subtraction expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a subtraction expression
+// between scalar, vectors, and matrices. Given the two types \a T1 and \a T2, which must be
+// either scalar, vector, or matrix types, the nested type \a Type corresponds to the resulting
+// return type. In case \a T1 or \a T2 don't fit or if the two types cannot be subtracted, the
+// resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename T1 // Type of the left-hand side subtraction operand
+ , typename T2 > // Type of the right-hand side subtraction operand
+struct SubExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T1>
+ , If_< IsMatrix<T2>
+ , If_< IsDenseMatrix<T1>
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsRowMajorMatrix<T2>
+ , DMatDMatSubExprTrait<T1,T2>
+ , DMatTDMatSubExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TDMatDMatSubExprTrait<T1,T2>
+ , TDMatTDMatSubExprTrait<T1,T2> > >
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsRowMajorMatrix<T2>
+ , DMatSMatSubExprTrait<T1,T2>
+ , DMatTSMatSubExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TDMatSMatSubExprTrait<T1,T2>
+ , TDMatTSMatSubExprTrait<T1,T2> > > >
+ , If_< IsDenseMatrix<T2>
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsRowMajorMatrix<T2>
+ , SMatDMatSubExprTrait<T1,T2>
+ , SMatTDMatSubExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TSMatDMatSubExprTrait<T1,T2>
+ , TSMatTDMatSubExprTrait<T1,T2> > >
+ , If_< IsRowMajorMatrix<T1>
+ , If_< IsRowMajorMatrix<T2>
+ , SMatSMatSubExprTrait<T1,T2>
+ , SMatTSMatSubExprTrait<T1,T2> >
+ , If_< IsRowMajorMatrix<T2>
+ , TSMatSMatSubExprTrait<T1,T2>
+ , TSMatTSMatSubExprTrait<T1,T2> > > > >
+ , Failure >
+ , If_< IsVector<T1>
+ , If_< IsVector<T2>
+ , If_< IsDenseVector<T1>
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T1>
+ , If_< IsRowVector<T2>
+ , TDVecTDVecSubExprTrait<T1,T2>
+ , Failure >
+ , If_< IsRowVector<T2>
+ , Failure
+ , DVecDVecSubExprTrait<T1,T2> > >
+ , If_< IsRowVector<T1>
+ , If_< IsRowVector<T2>
+ , TDVecTSVecSubExprTrait<T1,T2>
+ , Failure >
+ , If_< IsRowVector<T2>
+ , Failure
+ , DVecSVecSubExprTrait<T1,T2> > > >
+ , If_< IsDenseVector<T2>
+ , If_< IsRowVector<T1>
+ , If_< IsRowVector<T2>
+ , TSVecTDVecSubExprTrait<T1,T2>
+ , Failure >
+ , If_< IsRowVector<T2>
+ , Failure
+ , SVecDVecSubExprTrait<T1,T2> > >
+ , If_< IsRowVector<T1>
+ , If_< IsRowVector<T2>
+ , TSVecTSVecSubExprTrait<T1,T2>
+ , Failure >
+ , If_< IsRowVector<T2>
+ , Failure
+ , SVecSVecSubExprTrait<T1,T2> > > > >
+ , Failure >
+ , If_< IsNumeric<T1>
+ , If_< IsNumeric<T2>
+ , SubTrait<T1,T2>
+ , Failure >
+ , Failure > > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , SubExprTrait< Decay_<T1>, Decay_<T2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SubExprTrait class template.
+// \ingroup math_traits
+//
+// The SubExprTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the SubExprTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename SubExprTrait<T1,T2>::Type;
+ using Type2 = SubExprTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side subtraction operand
+ , typename T2 > // Type of the right-hand side subtraction operand
+using SubExprTrait_ = typename SubExprTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SubTrait.h b/src/cpu/blaze/math/traits/SubTrait.h
new file mode 100644
index 00000000..9f66a401
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SubTrait.h
@@ -0,0 +1,236 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SubTrait.h
+// \brief Header file for the subtraction trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SUBTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SUBTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/CommonType.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the SubTrait class.
+// \ingroup math_traits
+//
+// \section subtrait_general General
+//
+// The SubTrait class template offers the possibility to select the resulting data type of a
+// generic subtraction operation between the two given types \a T1 and \a T2. SubTrait defines
+// the nested type \a Type, which represents the resulting data type of the subtraction. In case
+// the two types \a T1 and \a T2 cannot be subtracted, a compilation error is created. Note that
+// \c const and \c volatile qualifiers and reference modifiers are generally ignored.
+//
+// Per default, SubTrait supports all built-in data types. Additionally, the Blaze library
+// provides appropriate specializations for the following user-defined arithmetic types:
+//
+// <ul>
+// <li>std::complex</li>
+// <li>blaze::StaticVector</li>
+// <li>blaze::HybridVector</li>
+// <li>blaze::DynamicVector</li>
+// <li>blaze::CustomVector</li>
+// <li>blaze::CompressedVector</li>
+// <li>blaze::StaticMatrix</li>
+// <li>blaze::HybridMatrix</li>
+// <li>blaze::DynamicMatrix</li>
+// <li>blaze::CustomMatrix</li>
+// <li>blaze::CompressedMatrix</li>
+// <li>blaze::SymmetricMatrix</li>
+// <li>blaze::HermitianMatrix</li>
+// <li>blaze::LowerMatrix</li>
+// <li>blaze::UniLowerMatrix</li>
+// <li>blaze::StrictlyLowerMatrix</li>
+// <li>blaze::UpperMatrix</li>
+// <li>blaze::UniUpperMatrix</li>
+// <li>blaze::StrictlyUpperMatrix</li>
+// <li>blaze::DiagonalMatrix</li>
+// </ul>
+//
+//
+// \n \section subtrait_specializations Creating custom specializations
+//
+// SubTrait is guaranteed to work for all data types that provide a subtraction operator (i.e.
+// \c operator-). In order to add support for user-defined data types that either don't provide
+// a subtraction operator or whose subtraction operator returns a proxy object instead of a
+// concrete type (as it is for instance common in expression template libraries) it is possible
+// to specialize the SubTrait template. The following example shows the according specialization
+// for the subtraction between two dynamic column vectors:
+
+ \code
+ template< typename T1, typename T2 >
+ struct SubTrait< DynamicVector<T1,columnVector>, DynamicVector<T2,columnVector> >
+ {
+ typedef DynamicVector< typename SubTrait<T1,T2>::Type, columnVector > Type;
+ };
+ \endcode
+
+// \n \section subtrait_examples Examples
+//
+// The following example demonstrates the use of the SubTrait template, where depending on
+// the two given data types the resulting data type is selected:
+
+ \code
+ template< typename T1, typename T2 > // The two generic types
+ typename SubTrait<T1,T2>::Type // The resulting generic return type
+ sub( const T1& t1, const T2& t2 ) //
+ { // The function 'sub' returns the
+ return t1 - t2; // difference of the two given values
+ } //
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct SubTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type1 = Decay_<T1>;
+ using Type2 = Decay_<T2>;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct SubType { using Type = decltype( std::declval<Type1>() - std::declval<Type2>() ); };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T1>, IsVolatile<T1>, IsReference<T1>
+ , IsConst<T2>, IsVolatile<T2>, IsReference<T2> >
+ , SubTrait<Type1,Type2>
+ , SubType >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SubTrait class template for a complex and a built-in type.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct SubTrait< complex<T1>, T2, EnableIf_< IsBuiltin<T2> > >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< complex<T1> , T2 >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SubTrait class template for a built-in and a complex type.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct SubTrait< T1, complex<T2>, EnableIf_< IsBuiltin<T1> > >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< T1, complex<T2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the SubTrait class template for two complex types.
+// \ingroup math_traits
+*/
+template< typename T1, typename T2 >
+struct SubTrait< complex<T1>, complex<T2> >
+{
+ public:
+ //**********************************************************************************************
+ using Type = CommonType_< complex<T1>, complex<T2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SubTrait class template.
+// \ingroup math_traits
+//
+// The SubTrait_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the SubTrait class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename SubTrait<T1,T2>::Type;
+ using Type2 = SubTrait_<T1,T2>;
+ \endcode
+*/
+template< typename T1, typename T2 >
+using SubTrait_ = typename SubTrait<T1,T2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SubmatrixExprTrait.h b/src/cpu/blaze/math/traits/SubmatrixExprTrait.h
new file mode 100644
index 00000000..90bed58d
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SubmatrixExprTrait.h
@@ -0,0 +1,138 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SubmatrixExprTrait.h
+// \brief Header file for the SubmatrixExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SUBMATRIXEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SUBMATRIXEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/views/Forward.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type type of a submatrix operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a submatrix operation.
+// Given the dense or sparse matrix type \a MT and the alignment flag \a AF, the nested type
+// \a Type corresponds to the resulting return type. In case the given type is neither a
+// dense nor a sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the matrix operand
+ , bool AF > // Alignment flag
+struct SubmatrixExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Result*******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T >
+ struct Result { using Type = Submatrix<T,AF,IsColumnMajorMatrix<T>::value,IsDenseMatrix<T>::value>; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = RemoveReference_<MT>;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsComputation<Tmp>, IsTransExpr<Tmp> >
+ , If_< Or< IsConst<Tmp>, IsVolatile<Tmp> >
+ , SubmatrixExprTrait< RemoveCV_<Tmp>, AF >
+ , Failure >
+ , If_< IsMatrix<Tmp>
+ , Result<Tmp>
+ , Failure >
+ >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SubmatrixExprTrait type trait.
+// \ingroup math_traits
+//
+// The SubmatrixExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SubmatrixExprTrait class template. For instance, given the matrix type \a MT
+// and the alignment flag \a AF the following two type definitions are identical:
+
+ \code
+ using Type1 = typename SubmatrixExprTrait<MT,AF>::Type;
+ using Type2 = SubmatrixExprTrait_<MT,AF>;
+ \endcode
+*/
+template< typename MT // Type of the matrix operand
+ , bool AF > // Alignment flag
+using SubmatrixExprTrait_ = typename SubmatrixExprTrait<MT,AF>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SubmatrixTrait.h b/src/cpu/blaze/math/traits/SubmatrixTrait.h
new file mode 100644
index 00000000..7248780a
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SubmatrixTrait.h
@@ -0,0 +1,158 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SubmatrixTrait.h
+// \brief Header file for the submatrix trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SUBMATRIXTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SUBMATRIXTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the SubmatrixTrait class.
+// \ingroup math_traits
+//
+// \section submatrixtrait_general General
+//
+// The SubmatrixTrait class template offers the possibility to select the resulting data type
+// when creating a submatrix of a dense or sparse matrix. SubmatrixTrait defines the nested
+// type \a Type, which represents the resulting data type of the submatrix operation. In case
+// the given data type is not a dense or sparse matrix type, the resulting data type \a Type
+// is set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and reference
+// modifiers are generally ignored.
+//
+// Per default, the SubmatrixTrait template only supports the following matrix types:
+//
+// <ul>
+// <li>blaze::StaticMatrix</li>
+// <li>blaze::HybridMatrix</li>
+// <li>blaze::DynamicMatrix</li>
+// <li>blaze::CustomMatrix</li>
+// <li>blaze::CompressedMatrix</li>
+// <li>blaze::Submatrix</li>
+// </ul>
+//
+//
+// \section submatrixtrait_specializations Creating custom specializations
+//
+// It is possible to specialize the SubmatrixTrait template for additional user-defined matrix
+// types. The following example shows the according specialization for the DynamicMatrix class
+// template:
+
+ \code
+ template< typename T1, bool SO >
+ struct SubmatrixTrait< DynamicMatrix<T1,SO> >
+ {
+ typedef DynamicMatrix<T1,SO> Type;
+ };
+ \endcode
+
+// \n \section submatrixtrait_examples Examples
+//
+// The following example demonstrates the use of the SubmatrixTrait template, where depending
+// on the given matrix type the according result type is selected:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ // Definition of the result type of a row-major dynamic matrix
+ typedef blaze::DynamicMatrix<int,rowMajor> MatrixType1;
+ typedef typename SubmatrixTrait<MatrixType1>::Type ResultType1;
+
+ // Definition of the result type of a column-major static matrix
+ typedef blaze::StaticMatrix<int,3UL,3UL,columnMajor> MatrixType2;
+ typedef typename SubmatrixTrait<MatrixType2>::Type ResultType2;
+ \endcode
+*/
+template< typename MT > // Type of the matrix
+struct SubmatrixTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , SubmatrixTrait< Decay_<MT> >
+ , Failure >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SubmatrixTrait type trait.
+// \ingroup math_traits
+//
+// The SubmatrixTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SubmatrixTrait class template. For instance, given the matrix type \a MT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename SubmatrixTrait<MT>::Type;
+ using Type2 = SubmatrixTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the matrix
+using SubmatrixTrait_ = typename SubmatrixTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SubvectorExprTrait.h b/src/cpu/blaze/math/traits/SubvectorExprTrait.h
new file mode 100644
index 00000000..137a6ca5
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SubvectorExprTrait.h
@@ -0,0 +1,138 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SubvectorExprTrait.h
+// \brief Header file for the SubvectorExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SUBVECTOREXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SUBVECTOREXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/math/views/Forward.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type type of a subvector operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a subvector operation.
+// Given the dense or sparse vector type \a VT and the alignment flag \a AF, the nested type
+// \a Type corresponds to the resulting return type. In case the given type is neither a
+// dense nor a sparse vector type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the vector operand
+ , bool AF > // Alignment Flag
+struct SubvectorExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Result*******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T >
+ struct Result { using Type = Subvector<T,AF,IsRowVector<T>::value,IsDenseVector<T>::value>; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = RemoveReference_<VT>;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsComputation<Tmp>, IsTransExpr<Tmp> >
+ , If_< Or< IsConst<Tmp>, IsVolatile<Tmp> >
+ , SubvectorExprTrait< RemoveCV_<Tmp>, AF >
+ , Failure >
+ , If_< IsVector<Tmp>
+ , Result<Tmp>
+ , Failure >
+ >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SubvectorExprTrait type trait.
+// \ingroup math_traits
+//
+// The SubvectorExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SubvectorExprTrait class template. For instance, given the vector type \a VT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename SubvectorExprTrait<VT,AF>::Type;
+ using Type2 = SubvectorExprTrait_<VT,AF>;
+ \endcode
+*/
+template< typename VT // Type of the vector operand
+ , bool AF > // Alignment Flag
+using SubvectorExprTrait_ = typename SubvectorExprTrait<VT,AF>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/SubvectorTrait.h b/src/cpu/blaze/math/traits/SubvectorTrait.h
new file mode 100644
index 00000000..8d6c7c5e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/SubvectorTrait.h
@@ -0,0 +1,160 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/SubvectorTrait.h
+// \brief Header file for the subvector trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_SUBVECTORTRAIT_H_
+#define _BLAZE_MATH_TRAITS_SUBVECTORTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base template for the SubvectorTrait class.
+// \ingroup math_traits
+//
+// \section subvectortrait_general General
+//
+// The SubvectorTrait class template offers the possibility to select the resulting data type
+// when creating a subvector of a dense or sparse vector. SubvectorTrait defines the nested
+// type \a Type, which represents the resulting data type of the subvector operation. In case
+// the given data type is not a dense or sparse vector type, the resulting data type \a Type
+// is set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and reference
+// modifiers are generally ignored.
+//
+// Per default, the SubvectorTrait template only supports the following vector types:
+//
+// <ul>
+// <li>blaze::StaticVector</li>
+// <li>blaze::HybridVector</li>
+// <li>blaze::DynamicVector</li>
+// <li>blaze::CustomVector</li>
+// <li>blaze::CompressedVector</li>
+// <li>blaze::Subvector</li>
+// <li>blaze::Row</li>
+// <li>blaze::Column</li>
+// </ul>
+//
+//
+// \section subvectortrait_specializations Creating custom specializations
+//
+// It is possible to specialize the SubvectorTrait template for additional user-defined vector
+// types. The following example shows the according specialization for the DynamicVector class
+// template:
+
+ \code
+ template< typename T1, bool TF >
+ struct SubvectorTrait< DynamicVector<T1,TF> >
+ {
+ typedef DynamicVector<T1,TF> Type;
+ };
+ \endcode
+
+// \n \section subvectortrait_examples Examples
+//
+// The following example demonstrates the use of the SubvectorTrait template, where depending
+// on the given vector type the according result type is selected:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ // Definition of the result type of a dynamic column vector
+ typedef blaze::DynamicVector<int,columnVector> VectorType1;
+ typedef typename SubvectorTrait<VectorType1>::Type ResultType1;
+
+ // Definition of the result type of the static row vector
+ typedef blaze::StaticVector<int,3UL,rowVector> VectorType2;
+ typedef typename SubvectorTrait<VectorType2>::Type ResultType2;
+ \endcode
+*/
+template< typename VT > // Type of the vector
+struct SubvectorTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , SubvectorTrait< Decay_<VT> >
+ , Failure >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the SubvectorTrait type trait.
+// \ingroup math_traits
+//
+// The SubvectorTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SubvectorTrait class template. For instance, given the vector type \a VT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename SubvectorTrait<VT>::Type;
+ using Type2 = SubvectorTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the vector
+using SubvectorTrait_ = typename SubvectorTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatCTransExprTrait.h b/src/cpu/blaze/math/traits/TDMatCTransExprTrait.h
new file mode 100644
index 00000000..6da7e9cb
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatCTransExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatCTransExprTrait.h
+// \brief Header file for the TDMatCTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATCTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATCTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/traits/TDMatForEachExprTrait.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix conjugate transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix conjugate transpose operation. Given the column-major dense matrix type \a MT,
+// the nested type \a Type corresponds to the resulting expression type. In case \a MT is
+// not a column-major dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct TDMatCTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , TDMatTransExprTrait< TDMatForEachExprTrait_<MT,Conj> >
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDMatCTransExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatCTransExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatCTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TDMatCTransExprTrait class template. For instance, given the column-major dense
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatCTransExprTrait<MT>::Type;
+ using Type2 = TDMatCTransExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using TDMatCTransExprTrait_ = typename TDMatCTransExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatDMatAddExprTrait.h b/src/cpu/blaze/math/traits/TDMatDMatAddExprTrait.h
new file mode 100644
index 00000000..e00d1a22
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatDMatAddExprTrait.h
@@ -0,0 +1,130 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatDMatAddExprTrait.h
+// \brief Header file for the TDMatDMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATDMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATDMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/dense matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/dense matrix addition. Given the column-major dense matrix type \a MT1 and the
+// row-major dense matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a column-major dense matrix type or \a MT2 is
+// not a row-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct TDMatDMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , If_< IsSymmetric<MT1>
+ , DMatDMatAddExpr< MT2, TDMatTransExprTrait_<MT1>, false >
+ , If_< IsSymmetric<MT2>
+ , DMatDMatAddExpr< DMatTransExprTrait_<MT2>, MT1, true >
+ , DMatTDMatAddExpr<MT2,MT1> > >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatDMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatDMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatDMatAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatDMatAddExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the row-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatDMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatDMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using TDMatDMatAddExprTrait_ = typename TDMatDMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatDMatMultExprTrait.h b/src/cpu/blaze/math/traits/TDMatDMatMultExprTrait.h
new file mode 100644
index 00000000..bdad0a06
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatDMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatDMatMultExprTrait.h
+// \brief Header file for the TDMatDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/dense matrix multiplication. Given the column-major dense matrix type \a MT1
+// and the row-major dense matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a column-major dense matrix type
+// or \a MT2 is not a row-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct TDMatDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDMatDMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatDMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatDMatMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatDMatMultExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the row-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatDMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatDMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using TDMatDMatMultExprTrait_ = typename TDMatDMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatDMatSubExprTrait.h b/src/cpu/blaze/math/traits/TDMatDMatSubExprTrait.h
new file mode 100644
index 00000000..a4339fbf
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatDMatSubExprTrait.h
@@ -0,0 +1,130 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatDMatSubExprTrait.h
+// \brief Header file for the TDMatDMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATDMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATDMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/dense matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/dense matrix subtraction. Given the column-major dense matrix type \a MT1 and
+// the row-major dense matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a column-major dense matrix type or \a MT2 is
+// not a row-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct TDMatDMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , If_< IsSymmetric<MT1>
+ , DMatDMatSubExpr< TDMatTransExprTrait_<MT1>, MT2, false >
+ , If_< IsSymmetric<MT2>
+ , DMatDMatSubExpr< MT1, DMatTransExprTrait_<MT2>, true >
+ , DMatTDMatSubExpr<MT1,MT2> > >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatDMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatDMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatDMatSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatDMatSubExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the row-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatDMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatDMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using TDMatDMatSubExprTrait_ = typename TDMatDMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatDVecMultExprTrait.h b/src/cpu/blaze/math/traits/TDMatDVecMultExprTrait.h
new file mode 100644
index 00000000..fccd5926
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatDVecMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatDVecMultExprTrait.h
+// \brief Header file for the TDMatDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/dense vector multiplication. Given the column-major dense matrix type \a MT
+// and the non-transpose dense vector type \a VT, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT is not a column-major dense matrix type or
+// \a VT is not a non-transpose dense vector type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side column-major dense matrix
+ , typename VT > // Type of the right-hand side non-transpose dense vector
+struct TDMatDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsDenseVector<VT>, IsColumnVector<VT> >
+ , TDMatDVecMultExpr<MT,VT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TDMatDVecMultExprTrait< Decay_<MT>, Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatDVecMultExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT and the non-transpose dense vector type \a VT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatDVecMultExprTrait<MT,VT>::Type;
+ using Type2 = TDMatDVecMultExprTrait_<MT,VT>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side column-major dense matrix
+ , typename VT > // Type of the right-hand side non-transpose dense vector
+using TDMatDVecMultExprTrait_ = typename TDMatDVecMultExprTrait<MT,VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatEvalExprTrait.h b/src/cpu/blaze/math/traits/TDMatEvalExprTrait.h
new file mode 100644
index 00000000..003c993d
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatEvalExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatEvalExprTrait.h
+// \brief Header file for the TDMatEvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATEVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATEVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix evaluation operation. Given the column-major dense matrix type \a MT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a MT is not a
+// column-major dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct TDMatEvalExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatEvalExpr<MT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDMatEvalExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatEvalExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatEvalExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TDMatEvalExprTrait class template. For instance, given the column-major dense
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatEvalExprTrait<MT>::Type;
+ using Type2 = TDMatEvalExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using TDMatEvalExprTrait_ = typename TDMatEvalExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatForEachExprTrait.h b/src/cpu/blaze/math/traits/TDMatForEachExprTrait.h
new file mode 100644
index 00000000..d2e9a4a9
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatForEachExprTrait.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatForEachExprTrait.h
+// \brief Header file for the TDMatForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATFOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATFOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix custom operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense matrix
+// custom operation. Given the column-major dense matrix type \a MT and the custom operation type
+// \a OP, the nested type \a Type corresponds to the resulting expression type. In case \a MT is
+// not a column-major dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the dense matrix
+ , typename OP > // Type of the custom operation
+struct TDMatForEachExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatForEachExpr<MT,OP,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDMatForEachExprTrait< Decay_<MT>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatForEachExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TDMatForEachExprTrait class template. For instance, given the column-major dense
+// matrix type \a MT and the custom operation type \a OP the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDMatForEachExprTrait<MT,OP>::Type;
+ using Type2 = TDMatForEachExprTrait_<MT,OP>;
+ \endcode
+*/
+template< typename MT // Type of the dense matrix
+ , typename OP > // Type of the custom operation
+using TDMatForEachExprTrait_ = typename TDMatForEachExprTrait<MT,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatInvExprTrait.h b/src/cpu/blaze/math/traits/TDMatInvExprTrait.h
new file mode 100644
index 00000000..97e8ffbb
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatInvExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatInvExprTrait.h
+// \brief Header file for the TDMatInvExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATINVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATINVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix inversion operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense matrix
+// inversion operation. Given the column-major dense matrix type \a MT, the nested type \a Type
+// corresponds to the resulting expression type. In case \a MT is not a column-major dense matrix
+// type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct TDMatInvExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatInvExpr<MT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDMatInvExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatInvExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatInvExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TDMatInvExprTrait class template. For instance, given the column-major dense
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatInvExprTrait<MT>::Type;
+ using Type2 = TDMatInvExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using TDMatInvExprTrait_ = typename TDMatInvExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatSMatAddExprTrait.h b/src/cpu/blaze/math/traits/TDMatSMatAddExprTrait.h
new file mode 100644
index 00000000..29412372
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatSMatAddExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatSMatAddExprTrait.h
+// \brief Header file for the TDMatSMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATSMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATSMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/sparse matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/sparse matrix addition. Given the column-major dense matrix type \a MT1 and the
+// row-major sparse matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a column-major dense matrix type or \a MT2 is
+// not a row-major sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct TDMatSMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDMatSMatAddExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatSMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatSMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatSMatAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatSMatAddExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the row-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatSMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatSMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using TDMatSMatAddExprTrait_ = typename TDMatSMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatSMatMultExprTrait.h b/src/cpu/blaze/math/traits/TDMatSMatMultExprTrait.h
new file mode 100644
index 00000000..d0b99d45
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatSMatMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatSMatMultExprTrait.h
+// \brief Header file for the TDMatSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/sparse matrix multiplication. Given the column-major dense matrix type \a MT1
+// and the row-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a column-major dense matrix type
+// or \a MT2 is not a row-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct TDMatSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDMatSMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatSMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatSMatMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatSMatMultExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the row-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatSMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatSMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using TDMatSMatMultExprTrait_ = typename TDMatSMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatSMatSubExprTrait.h b/src/cpu/blaze/math/traits/TDMatSMatSubExprTrait.h
new file mode 100644
index 00000000..f01732ac
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatSMatSubExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatSMatSubExprTrait.h
+// \brief Header file for the TDMatSMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATSMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATSMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/sparse matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/sparse matrix subtraction. Given the column-major dense matrix type \a MT1
+// and the row-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a column-major dense matrix type
+// or \a MT2 is not a row-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct TDMatSMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TDMatSMatSubExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatSMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatSMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatSMatSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatSMatSubExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the row-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatSMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatSMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using TDMatSMatSubExprTrait_ = typename TDMatSMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatSVecMultExprTrait.h b/src/cpu/blaze/math/traits/TDMatSVecMultExprTrait.h
new file mode 100644
index 00000000..731827d7
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatSVecMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatSVecMultExprTrait.h
+// \brief Header file for the TDMatSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/sparse vector multiplication. Given the column-major dense matrix type \a MT
+// and the non-transpose sparse vector type \a VT, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT is not a column-major dense matrix type or
+// \a VT is not a non-transpose sparse vector type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side column-major dense matrix
+ , typename VT > // Type of the right-hand side non-transpose sparse vector
+struct TDMatSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT> , IsColumnMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TDMatSVecMultExpr<MT,VT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TDMatSVecMultExprTrait< Decay_<MT>, Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatSVecMultExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT and the non-transpose sparse vector type \a VT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatSVecMultExprTrait<MT,VT>::Type;
+ using Type2 = TDMatSVecMultExprTrait_<MT,VT>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side column-major dense matrix
+ , typename VT > // Type of the right-hand side non-transpose sparse vector
+using TDMatSVecMultExprTrait_ = typename TDMatSVecMultExprTrait<MT,VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatScalarDivExprTrait.h b/src/cpu/blaze/math/traits/TDMatScalarDivExprTrait.h
new file mode 100644
index 00000000..a53fd038
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatScalarDivExprTrait.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatScalarDivExprTrait.h
+// \brief Header file for the TDMatScalarDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATSCALARDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATSCALARDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TDMatScalarDivExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST
+ , bool Condition >
+struct TDMatScalarDivExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<MT> >, IsBuiltin<ST> >
+ , DivTrait_< UnderlyingBuiltin_<MT>, ST >
+ , DivTrait_< UnderlyingNumeric_<MT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< IsInvertible<ScalarType>
+ , DMatScalarMultExpr<MT,ScalarType,true>
+ , DMatScalarDivExpr<MT,ScalarType,true> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TDMatScalarDivExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST >
+struct TDMatScalarDivExprTraitHelper<MT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/scalar division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/scalar division. Given the column-major dense matrix type \a MT and the scalar
+// type \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a MT is not a column-major dense matrix type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar
+struct TDMatScalarDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , TDMatScalarDivExprTrait< Decay_<MT>, Decay_<ST> >
+ , TDMatScalarDivExprTraitHelper<MT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatScalarDivExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatScalarDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatScalarDivExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TDMatScalarDivExprTrait<MT,ST>::Type;
+ using Type2 = TDMatScalarDivExprTrait_<MT,ST>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar
+using TDMatScalarDivExprTrait_ = typename TDMatScalarDivExprTrait<MT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatScalarMultExprTrait.h b/src/cpu/blaze/math/traits/TDMatScalarMultExprTrait.h
new file mode 100644
index 00000000..c4d9e792
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatScalarMultExprTrait.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatScalarMultExprTrait.h
+// \brief Header file for the TDMatScalarMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATSCALARMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATSCALARMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TDMatScalarMultExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST
+ , bool Condition >
+struct TDMatScalarMultExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<MT> >, IsBuiltin<ST> >
+ , MultTrait_< UnderlyingBuiltin_<MT>, ST >
+ , MultTrait_< UnderlyingNumeric_<MT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = DMatScalarMultExpr<MT,ScalarType,true>;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TDMatScalarMultExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST >
+struct TDMatScalarMultExprTraitHelper<MT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/scalar multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/scalar multiplication. Given the column-major dense matrix type \a MT and the
+// scalar type \a ST, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a MT is not a column-major dense matrix type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar
+struct TDMatScalarMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , TDMatScalarMultExprTrait< Decay_<MT>, Decay_<ST> >
+ , TDMatScalarMultExprTraitHelper<MT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatScalarMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatScalarMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatScalarMultExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TDMatScalarMultExprTrait<MT,ST>::Type;
+ using Type2 = TDMatScalarMultExprTrait_<MT,ST>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side dense matrix
+ , typename ST > // Type of the right-hand side scalar
+using TDMatScalarMultExprTrait_ = typename TDMatScalarMultExprTrait<MT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatSerialExprTrait.h b/src/cpu/blaze/math/traits/TDMatSerialExprTrait.h
new file mode 100644
index 00000000..ffa30801
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatSerialExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatSerialExprTrait.h
+// \brief Header file for the TDMatSerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATSERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATSERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix serial evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix serial evaluation operation. Given the column-major dense matrix type \a MT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a MT is not
+// a column-major dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct TDMatSerialExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatSerialExpr<MT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDMatSerialExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatSerialExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatSerialExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TDMatSerialExprTrait class template. For instance, given the column-major dense
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatSerialExprTrait<MT>::Type;
+ using Type2 = TDMatSerialExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using TDMatSerialExprTrait_ = typename TDMatSerialExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatTDMatAddExprTrait.h b/src/cpu/blaze/math/traits/TDMatTDMatAddExprTrait.h
new file mode 100644
index 00000000..23389f74
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatTDMatAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatTDMatAddExprTrait.h
+// \brief Header file for the TDMatTDMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATTDMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATTDMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/transpose dense matrix
+// addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/transpose dense matrix addition. Given the two column-major dense matrix types
+// \a MT1 and \a MT2, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a MT1 or \a MT2 is not a column-major dense matrix, the resulting data type
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct TDMatTDMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , DMatDMatAddExpr<MT1,MT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatTDMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatTDMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatTDMatAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatTDMatAddExprTrait class template. For instance, given the
+// column-major dense matrix types \a MT1 and \a MT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDMatTDMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatTDMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using TDMatTDMatAddExprTrait_ = typename TDMatTDMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatTDMatMultExprTrait.h b/src/cpu/blaze/math/traits/TDMatTDMatMultExprTrait.h
new file mode 100644
index 00000000..9a866315
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatTDMatMultExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatTDMatMultExprTrait.h
+// \brief Header file for the TDMatTDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATTDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATTDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/transpose dense matrix
+// multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/transpose dense matrix multiplication. Given the two column-major dense matrix
+// types \a MT1 and \a MT2, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a MT1 or \a MT2 is not a column-major dense matrix, the resulting data type
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct TDMatTDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDMatTDMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatTDMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatTDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatTDMatMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatTDMatMultExprTrait class template. For instance, given the
+// column-major dense matrix types \a MT1 and \a MT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDMatTDMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatTDMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using TDMatTDMatMultExprTrait_ = typename TDMatTDMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatTDMatSubExprTrait.h b/src/cpu/blaze/math/traits/TDMatTDMatSubExprTrait.h
new file mode 100644
index 00000000..1679299d
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatTDMatSubExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatTDMatSubExprTrait.h
+// \brief Header file for the TDMatTDMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATTDMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATTDMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/transpose dense matrix
+// subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/transpose dense matrix subtraction. Given the two column-major dense matrix
+// types \a MT1 and \a MT2, the nested type \a Type corresponds to the resulting expression
+// type. In case either \a MT1 or \a MT2 is not a column-major dense matrix, the resulting
+// data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct TDMatTDMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , DMatDMatSubExpr<MT1,MT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatTDMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatTDMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatTDMatSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatTDMatSubExprTrait class template. For instance, given the
+// column-major dense matrix types \a MT1 and \a MT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDMatTDMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatTDMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using TDMatTDMatSubExprTrait_ = typename TDMatTDMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatTSMatAddExprTrait.h b/src/cpu/blaze/math/traits/TDMatTSMatAddExprTrait.h
new file mode 100644
index 00000000..f33903cd
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatTSMatAddExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatTSMatAddExprTrait.h
+// \brief Header file for the TDMatTSMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATTSMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATTSMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/transpose sparse matrix
+// addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/transpose sparse matrix addition. Given the column-major dense matrix type \a MT1
+// and the column-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a column-major dense matrix type or
+// \a MT2 is not a column-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct TDMatTSMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , DMatSMatAddExpr<MT1,MT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatTSMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatTSMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatTSMatAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatTSMatAddExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the column-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatTSMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatTSMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using TDMatTSMatAddExprTrait_ = typename TDMatTSMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatTSMatMultExprTrait.h b/src/cpu/blaze/math/traits/TDMatTSMatMultExprTrait.h
new file mode 100644
index 00000000..24f0ac17
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatTSMatMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatTSMatMultExprTrait.h
+// \brief Header file for the TDMatTSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATTSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATTSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/transpose sparse matrix
+// multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/transpose sparse matrix multiplication. Given the column-major dense matrix type
+// \a MT1 and the column-major sparse matrix type \a MT2, the nested type \a Type corresponds to
+// the resulting expression type. In case either \a MT1 is not a column-major dense matrix type
+// or \a MT2 is not a column-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct TDMatTSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TDMatTSMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatTSMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatTSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatTSMatMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatTSMatMultExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the column-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatTSMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatTSMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using TDMatTSMatMultExprTrait_ = typename TDMatTSMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatTSMatSubExprTrait.h b/src/cpu/blaze/math/traits/TDMatTSMatSubExprTrait.h
new file mode 100644
index 00000000..78872afa
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatTSMatSubExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatTSMatSubExprTrait.h
+// \brief Header file for the TDMatTSMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATTSMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATTSMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense matrix/transpose sparse matrix
+// subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense matrix/transpose sparse matrix subtraction. Given the column-major dense matrix type
+// \a MT1 and the column-major sparse matrix type \a MT2, the nested type \a Type corresponds
+// to the resulting expression type. In case either \a MT1 is not a column-major dense matrix
+// type or \a MT2 is not a column-major sparse matrix type, the resulting data type \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct TDMatTSMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT1> , IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , DMatSMatSubExpr<MT1,MT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TDMatTSMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatTSMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatTSMatSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDMatTSMatSubExprTrait class template. For instance, given the
+// column-major dense matrix type \a MT1 and the column-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatTSMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = TDMatTSMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major dense matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using TDMatTSMatSubExprTrait_ = typename TDMatTSMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDMatTransExprTrait.h b/src/cpu/blaze/math/traits/TDMatTransExprTrait.h
new file mode 100644
index 00000000..a1eb600e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDMatTransExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDMatTransExprTrait.h
+// \brief Header file for the TDMatTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDMATTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDMATTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense matrix transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// matrix transpose operation. Given the column-major dense matrix type \a MT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a MT is not a
+// column-major dense matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the dense matrix
+struct TDMatTransExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , DMatTransExpr<MT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDMatTransExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDMatTransExprTrait class template.
+// \ingroup math_traits
+//
+// The TDMatTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TDMatTransExprTrait class template. For instance, given the column-major dense
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDMatTransExprTrait<MT>::Type;
+ using Type2 = TDMatTransExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the dense matrix
+using TDMatTransExprTrait_ = typename TDMatTransExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecCTransExprTrait.h b/src/cpu/blaze/math/traits/TDVecCTransExprTrait.h
new file mode 100644
index 00000000..73fece21
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecCTransExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecCTransExprTrait.h
+// \brief Header file for the TDVecCTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECCTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECCTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/traits/TDVecForEachExprTrait.h>
+#include <blaze/math/traits/TDVecTransExprTrait.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector conjugate transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector conjugate transpose operation. Given the transpose dense vector type \a VT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a VT is not
+// a transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the dense vector
+struct TDVecCTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , TDVecTransExprTrait< TDVecForEachExprTrait_<VT,Conj> >
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TDVecCTransExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecCTransExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecCTransExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecCTransExprTrait class template. For instance, given the transpose
+// dense vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecCTransExprTrait<VT>::Type;
+ using Type2 = TDVecCTransExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the dense vector
+using TDVecCTransExprTrait_ = typename TDVecCTransExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecDMatMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecDMatMultExprTrait.h
new file mode 100644
index 00000000..59e35c34
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecDMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecDMatMultExprTrait.h
+// \brief Header file for the TDVecDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/dense matrix multiplication. Given the transpose dense vector type \a VT and the
+// row-major dense matrix type \a MT, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT is not a transpose dense vector type or \a MT is
+// not a row-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side transpose dense vector
+ , typename MT > // Type of the right-hand side row-major dense matrix
+struct TDVecDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , TDVecDMatMultExpr<VT,MT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDVecDMatMultExprTrait< Decay_<VT>, Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecDMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecDMatMultExprTrait class template. For instance, given the transpose
+// dense vector type \a VT and the row-major dense matrix type \a MT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TDVecDMatMultExprTrait<VT,MT>::Type;
+ using Type2 = TDVecDMatMultExprTrait_<VT,MT>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side transpose dense vector
+ , typename MT > // Type of the right-hand side row-major dense matrix
+using TDVecDMatMultExprTrait_ = typename TDVecDMatMultExprTrait<VT,MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecDVecMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecDVecMultExprTrait.h
new file mode 100644
index 00000000..c36b0089
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecDVecMultExprTrait.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecDVecMultExprTrait.h
+// \brief Header file for the TDVecDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TDVecDVecMultExprTrait.
+// \ingroup math_traits
+*/
+template< typename VT1
+ , typename VT2
+ , bool Valid >
+struct TDVecDVecMultExprTraitHelper
+{
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TDVecDVecMultExprTrait auxiliary helper struct.
+// \ingroup math_traits
+*/
+template< typename VT1
+ , typename VT2 >
+struct TDVecDVecMultExprTraitHelper<VT1,VT2,true>
+{
+ //**********************************************************************************************
+ using Type = MultTrait_< ElementType_<VT1>, ElementType_<VT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/dense vector multiplication (inner product). Given the transpose dense vector
+// type \a VT1 and the non-transpose dense vector type \a VT2, the nested type \a Type corresponds
+// to the resulting expression type. In case either \a VT1 is not a transpose dense vector
+// type or \a VT2 is not a non-transpose dense vector type, the resulting \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct TDVecDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { valid = IsDenseVector<VT1>::value && IsRowVector<VT1>::value &&
+ IsDenseVector<VT2>::value && IsColumnVector<VT2>::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecDVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , TDVecDVecMultExprTraitHelper<VT1,VT2,valid> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecDVecMultExprTrait class template. For instance, given
+// the transpose dense vector type \a VT1 and non-transpose dense vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecDVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecDVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using TDVecDVecMultExprTrait_ = typename TDVecDVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecEvalExprTrait.h b/src/cpu/blaze/math/traits/TDVecEvalExprTrait.h
new file mode 100644
index 00000000..a0fbea3c
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecEvalExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecEvalExprTrait.h
+// \brief Header file for the TDVecEvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECEVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECEVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector evaluation operation. Given the transpose dense vector type \a VT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a VT is not a
+// transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the dense vector
+struct TDVecEvalExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecEvalExpr<VT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TDVecEvalExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecEvalExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecEvalExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecEvalExprTrait class template. For instance, given the transpose
+// dense vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecEvalExprTrait<VT>::Type;
+ using Type2 = TDVecEvalExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the dense vector
+using TDVecEvalExprTrait_ = typename TDVecEvalExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecForEachExprTrait.h b/src/cpu/blaze/math/traits/TDVecForEachExprTrait.h
new file mode 100644
index 00000000..6a57bb69
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecForEachExprTrait.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecForEachExprTrait.h
+// \brief Header file for the TDVecForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECFOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECFOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector custom operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense vector
+// custom operation. Given the transpose dense vector type \a VT and the custom operation type
+// \a OP, the nested type \a Type corresponds to the resulting expression type. In case \a VT is
+// not a transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the dense vector
+ , typename OP > // Type of the custom operation
+struct TDVecForEachExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecForEachExpr<VT,OP,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TDVecForEachExprTrait< Decay_<VT>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecForEachExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecForEachExprTrait class template. For instance, given the transpose
+// dense vector type \a VT and the custom operation type \a OP the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename TDVecForEachExprTrait<VT>::Type;
+ using Type2 = TDVecForEachExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT // Type of the dense vector
+ , typename OP > // Type of the custom operation
+using TDVecForEachExprTrait_ = typename TDVecForEachExprTrait<VT,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecSMatMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecSMatMultExprTrait.h
new file mode 100644
index 00000000..12792c62
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecSMatMultExprTrait.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecSMatMultExprTrait.h
+// \brief Header file for the TDVecSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/SMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/sparse matrix multiplication. Given the transpose dense vector type \a VT and the
+// row-major sparse matrix type \a MT, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT is not a transpose dense vector type or \a MT is
+// not a row-major sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side transpose dense vector
+ , typename MT > // Type of the right-hand side row-major sparse matrix
+struct TDVecSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT> , IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , If_< IsSymmetric<MT>
+ , TDVecTSMatMultExpr< VT, SMatTransExprTrait_<MT> >
+ , TDVecSMatMultExpr<VT,MT> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDVecSMatMultExprTrait< Decay_<VT>, Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecSMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecSMatMultExprTrait class template. For instance, given the transpose
+// dense vector type \a VT and the row-major sparse matrix type \a MT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TDVecSMatMultExprTrait<VT,MT>::Type;
+ using Type2 = TDVecSMatMultExprTrait_<VT,MT>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side transpose dense vector
+ , typename MT > // Type of the right-hand side row-major sparse matrix
+using TDVecSMatMultExprTrait_ = typename TDVecSMatMultExprTrait<VT,MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecSVecMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecSVecMultExprTrait.h
new file mode 100644
index 00000000..fe8a48e6
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecSVecMultExprTrait.h
@@ -0,0 +1,158 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecSVecMultExprTrait.h
+// \brief Header file for the TDVecSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TDVecSVecMultExprTrait.
+// \ingroup math_traits
+*/
+template< typename VT1
+ , typename VT2
+ , bool Valid >
+struct TDVecSVecMultExprTraitHelper
+{
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TDVecSVecMultExprTrait auxiliary helper struct.
+// \ingroup math_traits
+*/
+template< typename VT1
+ , typename VT2 >
+struct TDVecSVecMultExprTraitHelper<VT1,VT2,true>
+{
+ //**********************************************************************************************
+ using Type = MultTrait_< ElementType_<VT1>, ElementType_<VT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/sparse vector multiplication (inner product). Given the transpose dense vector
+// type \a VT1 and the non-transpose sparse vector type \a VT2, the nested type \a Type corresponds
+// to the resulting expression type. In case either \a VT1 is not a transpose dense vector
+// type or \a VT2 is not a non-transpose sparse vector type, the resulting \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct TDVecSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { valid = IsDenseVector<VT1>::value && IsRowVector<VT1>::value &&
+ IsSparseVector<VT2>::value && IsColumnVector<VT2>::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecSVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , TDVecSVecMultExprTraitHelper<VT1,VT2,valid> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecSVecMultExprTrait class template. For instance, given
+// the transpose dense vector type \a VT1 and non-transpose sparse vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecSVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecSVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using TDVecSVecMultExprTrait_ = typename TDVecSVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecScalarDivExprTrait.h b/src/cpu/blaze/math/traits/TDVecScalarDivExprTrait.h
new file mode 100644
index 00000000..f75a1222
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecScalarDivExprTrait.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecScalarDivExprTrait.h
+// \brief Header file for the TDVecScalarDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECSCALARDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECSCALARDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TDVecScalarDivExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST
+ , bool Condition >
+struct TDVecScalarDivExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<VT> >, IsBuiltin<ST> >
+ , DivTrait_< UnderlyingBuiltin_<VT>, ST >
+ , DivTrait_< UnderlyingNumeric_<VT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< IsInvertible<ScalarType>
+ , DVecScalarMultExpr<VT,ScalarType,true>
+ , DVecScalarDivExpr<VT,ScalarType,true> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TDVecScalarDivExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST >
+struct TDVecScalarDivExprTraitHelper<VT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/scalar division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/scalar division. Given the transpose dense vector type \a VT and the scalar
+// type \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT is not a transpose dense vector type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST > // Type of the right-hand side scalar
+struct TDVecScalarDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsDenseVector<VT>, IsRowVector<VT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , TDVecScalarDivExprTrait< Decay_<VT>, Decay_<ST> >
+ , TDVecScalarDivExprTraitHelper<VT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecScalarDivExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecScalarDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecScalarDivExprTrait class template. For instance, given
+// the transpose dense vector type \a VT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TDVecScalarDivExprTrait<VT,ST>::Type;
+ using Type2 = TDVecScalarDivExprTrait_<VT,ST>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST > // Type of the right-hand side scalar
+using TDVecScalarDivExprTrait_ = typename TDVecScalarDivExprTrait<VT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecScalarMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecScalarMultExprTrait.h
new file mode 100644
index 00000000..cfe50799
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecScalarMultExprTrait.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecScalarMultExprTrait.h
+// \brief Header file for the TDVecScalarMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECSCALARMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECSCALARMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TDVecScalarMultExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST
+ , bool Condition >
+struct TDVecScalarMultExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<VT> >, IsBuiltin<ST> >
+ , MultTrait_< UnderlyingBuiltin_<VT> ,ST >
+ , MultTrait_< UnderlyingNumeric_<VT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = DVecScalarMultExpr<VT,ScalarType,true>;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TDVecScalarMultExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST >
+struct TDVecScalarMultExprTraitHelper<VT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/scalar multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/scalar multiplication. Given the transpose dense vector type \a VT and the
+// scalar type \a ST, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a VT is not a transpose dense vector type or \a ST is not a scalar type,
+// the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST > // Type of the right-hand side scalar
+struct TDVecScalarMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsDenseVector<VT>, IsRowVector<VT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , TDVecScalarMultExprTrait< Decay_<VT>, Decay_<ST> >
+ , TDVecScalarMultExprTraitHelper<VT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecScalarMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecScalarMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecScalarMultExprTrait class template. For instance, given
+// the transpose dense vector type \a VT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TDVecScalarMultExprTrait<VT,ST>::Type;
+ using Type2 = TDVecScalarMultExprTrait_<VT,ST>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side dense vector
+ , typename ST > // Type of the right-hand side scalar
+using TDVecScalarMultExprTrait_ = typename TDVecScalarMultExprTrait<VT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecSerialExprTrait.h b/src/cpu/blaze/math/traits/TDVecSerialExprTrait.h
new file mode 100644
index 00000000..0c518359
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecSerialExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecSerialExprTrait.h
+// \brief Header file for the TDVecSerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECSERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECSERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector serial evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector serial evaluation operation. Given the transpose dense vector type \a VT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a VT is not
+// a transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the dense vector
+struct TDVecSerialExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecSerialExpr<VT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TDVecSerialExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecSerialExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecSerialExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecSerialExprTrait class template. For instance, given the transpose
+// dense vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecSerialExprTrait<VT>::Type;
+ using Type2 = TDVecSerialExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the dense vector
+using TDVecSerialExprTrait_ = typename TDVecSerialExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTDMatMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecTDMatMultExprTrait.h
new file mode 100644
index 00000000..75b795a6
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTDMatMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTDMatMultExprTrait.h
+// \brief Header file for the TDVecTDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/transpose dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/transpose dense matrix multiplication. Given the transpose dense vector type \a VT
+// and the column-major dense matrix type \a MT, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT is not a transpose dense vector type or
+// \a MT is not a column-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side transpose dense vector
+ , typename MT > // Type of the right-hand side column-major dense matrix
+struct TDVecTDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , TDVecTDMatMultExpr<VT,MT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDVecTDMatMultExprTrait< Decay_<VT>, Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTDMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecTDMatMultExprTrait class template. For instance, given the transpose
+// dense vector type \a VT and the column-major dense matrix type \a MT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TDVecTDMatMultExprTrait<VT,MT>::Type;
+ using Type2 = TDVecTDMatMultExprTrait_<VT,MT>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side transpose dense vector
+ , typename MT > // Type of the right-hand side column-major dense matrix
+using TDVecTDMatMultExprTrait_ = typename TDVecTDMatMultExprTrait<VT,MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTDVecAddExprTrait.h b/src/cpu/blaze/math/traits/TDVecTDVecAddExprTrait.h
new file mode 100644
index 00000000..46ceaea3
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTDVecAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTDVecAddExprTrait.h
+// \brief Header file for the TDVecTDVecAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTDVECADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTDVECADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/transpose dense vector
+// addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/transpose dense vector addition. Given the two transpose dense vector types
+// \a VT1 and \a VT2, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a VT1 or \a VT2 is not a transpose dense vector type, the resulting \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TDVecTDVecAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2> >
+ , DVecDVecAddExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTDVecAddExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTDVecAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTDVecAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTDVecAddExprTrait class template. For instance, given the
+// transpose dense vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDVecTDVecAddExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTDVecAddExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TDVecTDVecAddExprTrait_ = typename TDVecTDVecAddExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTDVecCrossExprTrait.h b/src/cpu/blaze/math/traits/TDVecTDVecCrossExprTrait.h
new file mode 100644
index 00000000..73d6743b
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTDVecCrossExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTDVecCrossExprTrait.h
+// \brief Header file for the TDVecTDVecCrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTDVECCROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTDVECCROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/dense vector cross product.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/dense vector cross product. Given the two transpose dense vector types \a VT1 and
+// \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a transpose dense vector type, the resulting \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TDVecTDVecCrossExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2> >
+ , DVecDVecCrossExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTDVecCrossExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTDVecCrossExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTDVecCrossExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTDVecCrossExprTrait class template. For instance, given the
+// transpose dense vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDVecTDVecCrossExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTDVecCrossExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TDVecTDVecCrossExprTrait_ = typename TDVecTDVecCrossExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTDVecDivExprTrait.h b/src/cpu/blaze/math/traits/TDVecTDVecDivExprTrait.h
new file mode 100644
index 00000000..f735127b
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTDVecDivExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTDVecDivExprTrait.h
+// \brief Header file for the TDVecTDVecDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTDVECDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTDVECDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/transpose dense vector
+// division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/transpose dense vector division. Given the two transpose dense vector types
+// \a VT1 and \a VT2, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a VT1 or \a VT2 is not a transpose dense vector type, the resulting \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TDVecTDVecDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2> >
+ , DVecDVecDivExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTDVecDivExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTDVecDivExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTDVecDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTDVecDivExprTrait class template. For instance, given the
+// transpose dense vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDVecTDVecDivExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTDVecDivExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TDVecTDVecDivExprTrait_ = typename TDVecTDVecDivExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTDVecMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecTDVecMultExprTrait.h
new file mode 100644
index 00000000..faf2bf27
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTDVecMultExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTDVecMultExprTrait.h
+// \brief Header file for the TDVecTDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/transpose dense vector
+// multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/transpose dense vector multiplication. Given the two transpose dense vector
+// types \a VT1 and \a VT2, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a VT1 or \a VT2 is not a transpose dense vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TDVecTDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2> >
+ , DVecDVecMultExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTDVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTDVecMultExprTrait class template. For instance, given the
+// transpose dense vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDVecTDVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTDVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TDVecTDVecMultExprTrait_ = typename TDVecTDVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTDVecSubExprTrait.h b/src/cpu/blaze/math/traits/TDVecTDVecSubExprTrait.h
new file mode 100644
index 00000000..4c9deba6
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTDVecSubExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTDVecSubExprTrait.h
+// \brief Header file for the TDVecTDVecSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTDVECSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTDVECSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/transpose dense vector
+// subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/transpose dense vector subtraction. Given the two transpose dense vector types
+// \a VT1 and \a VT2, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a VT1 or \a VT2 is not a transpose dense vector type, the resulting \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TDVecTDVecSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2>, IsRowVector<VT2> >
+ , DVecDVecSubExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTDVecSubExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTDVecSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTDVecSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTDVecSubExprTrait class template. For instance, given the
+// transpose dense vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TDVecTDVecSubExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTDVecSubExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TDVecTDVecSubExprTrait_ = typename TDVecTDVecSubExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTSMatMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecTSMatMultExprTrait.h
new file mode 100644
index 00000000..56724272
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTSMatMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTSMatMultExprTrait.h
+// \brief Header file for the TDVecTSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/transpose sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/transpose sparse matrix multiplication. Given the transpose dense vector type \a VT
+// and the column-major sparse matrix type \a MT, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT is not a transpose dense vector type or
+// \a MT is not a column-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side transpose dense vector
+ , typename MT > // Type of the right-hand side column-major sparse matrix
+struct TDVecTSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT> , IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , TDVecTSMatMultExpr<VT,MT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TDVecTSMatMultExprTrait< Decay_<VT>, Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTSMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecTSMatMultExprTrait class template. For instance, given the transpose
+// dense vector type \a VT and the column-major sparse matrix type \a MT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TDVecTSMatMultExprTrait<VT,MT>::Type;
+ using Type2 = TDVecTSMatMultExprTrait_<VT,MT>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side transpose dense vector
+ , typename MT > // Type of the right-hand side column-major sparse matrix
+using TDVecTSMatMultExprTrait_ = typename TDVecTSMatMultExprTrait<VT,MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTSVecAddExprTrait.h b/src/cpu/blaze/math/traits/TDVecTSVecAddExprTrait.h
new file mode 100644
index 00000000..82e85362
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTSVecAddExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTSVecAddExprTrait.h
+// \brief Header file for the TDVecTSVecAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTSVECADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTSVECADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/transpose sparse vector
+// addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/transpose sparse vector addition. Given the transpose dense vector type \a VT1
+// and the transpose sparse vector type \a VT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT1 is not a transpose dense vector type or
+// \a VT2 is not a transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct TDVecTSVecAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , DVecSVecAddExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTSVecAddExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTSVecAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTSVecAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTSVecAddExprTrait class template. For instance, given
+// the transpose dense vector type \a VT1 and the transpose sparse vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecTSVecAddExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTSVecAddExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using TDVecTSVecAddExprTrait_ = typename TDVecTSVecAddExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTSVecCrossExprTrait.h b/src/cpu/blaze/math/traits/TDVecTSVecCrossExprTrait.h
new file mode 100644
index 00000000..1ed68423
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTSVecCrossExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTSVecCrossExprTrait.h
+// \brief Header file for the TDVecTSVecCrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTSVECCROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTSVECCROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector/sparse vector cross product.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector/sparse vector cross product. Given the transpose dense vector type \a VT1 and the
+// transpose sparse vector type\a VT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT1 is not a transpose dense vector type or \a VT2 is
+// not a transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct TDVecTSVecCrossExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , DVecSVecCrossExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTSVecCrossExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTSVecCrossExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTSVecCrossExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTSVecCrossExprTrait class template. For instance, given
+// the transpose dense vector type \a VT1 and the transpose sparse vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecTSVecCrossExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTSVecCrossExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using TDVecTSVecCrossExprTrait_ = typename TDVecTSVecCrossExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTSVecMultExprTrait.h b/src/cpu/blaze/math/traits/TDVecTSVecMultExprTrait.h
new file mode 100644
index 00000000..1bd739ee
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTSVecMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTSVecMultExprTrait.h
+// \brief Header file for the TDVecTSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/transpose sparse vector
+// multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/transpose sparse vector multiplication. Given the transpose dense vector type
+// \a VT1 and the transpose sparse vector type \a VT2, the nested type \a Type corresponds to
+// the resulting expression type. In case either \a VT1 is not a transpose dense vector type or
+// \a VT2 is not a transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct TDVecTSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , DVecSVecMultExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTSVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTSVecMultExprTrait class template. For instance, given
+// the transpose dense vector type \a VT1 and the transpose sparse vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecTSVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTSVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using TDVecTSVecMultExprTrait_ = typename TDVecTSVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTSVecSubExprTrait.h b/src/cpu/blaze/math/traits/TDVecTSVecSubExprTrait.h
new file mode 100644
index 00000000..09fdd4f0
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTSVecSubExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTSVecSubExprTrait.h
+// \brief Header file for the TDVecTSVecSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTSVECSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTSVECSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose dense vector/transpose sparse vector
+// subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// dense vector/transpose sparse vector subtraction. Given the transpose dense vector type
+// \a VT1 and the transpose sparse vector type \a VT2, the nested type \a Type corresponds to
+// the resulting expression type. In case either \a VT1 is not a transpose dense vector type or
+// \a VT2 is not a transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct TDVecTSVecSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT1> , IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , DVecSVecSubExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TDVecTSVecSubExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTSVecSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTSVecSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TDVecTSVecSubExprTrait class template. For instance, given
+// the transpose dense vector type \a VT1 and the transpose sparse vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecTSVecSubExprTrait<VT1,VT2>::Type;
+ using Type2 = TDVecTSVecSubExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose dense vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using TDVecTSVecSubExprTrait_ = typename TDVecTSVecSubExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TDVecTransExprTrait.h b/src/cpu/blaze/math/traits/TDVecTransExprTrait.h
new file mode 100644
index 00000000..40566044
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TDVecTransExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TDVecTransExprTrait.h
+// \brief Header file for the TDVecTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TDVECTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TDVECTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a dense vector transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a dense
+// vector transpose operation. Given the transpose dense vector type \a VT, the nested type
+// \a Type corresponds to the resulting expression type. In case \a VT is not a transpose
+// dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the dense vector
+struct TDVecTransExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsDenseVector<VT>, IsRowVector<VT> >
+ , DVecTransExpr<VT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TDVecTransExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TDVecTransExprTrait class template.
+// \ingroup math_traits
+//
+// The TDVecTransExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TDVecTransExprTrait class template. For instance, given the transpose
+// dense vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TDVecTransExprTrait<VT>::Type;
+ using Type2 = TDVecTransExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the dense vector
+using TDVecTransExprTrait_ = typename TDVecTransExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatCTransExprTrait.h b/src/cpu/blaze/math/traits/TSMatCTransExprTrait.h
new file mode 100644
index 00000000..8056f317
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatCTransExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatCTransExprTrait.h
+// \brief Header file for the TSMatCTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATCTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATCTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/traits/TSMatForEachExprTrait.h>
+#include <blaze/math/traits/TSMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix conjugate transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix conjugate transpose operation. Given the column-major sparse matrix type \a MT,
+// the nested type \a Type corresponds to the resulting expression type. In case \a MT is
+// not a column-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the sparse matrix
+struct TSMatCTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , TSMatTransExprTrait< TSMatForEachExprTrait_<MT,Conj> >
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSMatCTransExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatCTransExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatCTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TSMatCTransExprTrait class template. For instance, given the column-major sparse
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatCTransExprTrait<MT>::Type;
+ using Type2 = TSMatCTransExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the sparse matrix
+using TSMatCTransExprTrait_ = typename TSMatCTransExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatDMatAddExprTrait.h b/src/cpu/blaze/math/traits/TSMatDMatAddExprTrait.h
new file mode 100644
index 00000000..90cd113f
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatDMatAddExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatDMatAddExprTrait.h
+// \brief Header file for the TSMatDMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATDMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATDMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/dense matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/dense matrix addition. Given the column-major sparse matrix type \a MT1 and
+// the row-major dense matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a column-major sparse matrix type or \a MT2 is
+// not a row-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct TSMatDMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsRowMajorMatrix<MT2> >
+ , DMatTSMatAddExpr<MT2,MT1>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatDMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatDMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatDMatAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatDMatAddExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the row-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatDMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatDMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using TSMatDMatAddExprTrait_ = typename TSMatDMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatDMatMultExprTrait.h b/src/cpu/blaze/math/traits/TSMatDMatMultExprTrait.h
new file mode 100644
index 00000000..8f72e5d9
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatDMatMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatDMatMultExprTrait.h
+// \brief Header file for the TSMatDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/dense matrix multiplication. Given the column-major sparse matrix type \a MT1
+// and the row-major dense matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a column-major sparse matrix type
+// or \a MT2 is not a row-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct TSMatDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsRowMajorMatrix<MT2> >
+ , TSMatDMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatDMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatDMatMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatDMatMultExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the row-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatDMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatDMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using TSMatDMatMultExprTrait_ = typename TSMatDMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatDMatSubExprTrait.h b/src/cpu/blaze/math/traits/TSMatDMatSubExprTrait.h
new file mode 100644
index 00000000..63546571
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatDMatSubExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatDMatSubExprTrait.h
+// \brief Header file for the TSMatDMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATDMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATDMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/dense matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/dense matrix subtraction. Given the column-major sparse matrix type \a MT1 and
+// the row-major dense matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a column-major sparse matrix type or \a MT2 is
+// not a row-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+struct TSMatDMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsRowMajorMatrix<MT2> >
+ , TSMatDMatSubExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatDMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatDMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatDMatSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatDMatSubExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the row-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatDMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatDMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major dense matrix
+using TSMatDMatSubExprTrait_ = typename TSMatDMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatDVecMultExprTrait.h b/src/cpu/blaze/math/traits/TSMatDVecMultExprTrait.h
new file mode 100644
index 00000000..747a3662
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatDVecMultExprTrait.h
@@ -0,0 +1,129 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatDVecMultExprTrait.h
+// \brief Header file for the TSMatDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/TSMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/dense vector multiplication. Given the column-major sparse matrix type \a MT
+// and the non-transpose dense vector type \a VT, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT is not a column-major sparse matrix type or
+// \a VT is not a non-transpose dense vector type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side column-major sparse matrix
+ , typename VT > // Type of the right-hand side non-transpose dense vector
+struct TSMatDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsDenseVector<VT> , IsColumnVector<VT> >
+ , If_< IsSymmetric<MT>
+ , SMatDVecMultExpr< TSMatTransExprTrait_<MT>, VT >
+ , TSMatDVecMultExpr<MT,VT> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TSMatDVecMultExprTrait< Decay_<MT>, Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatDVecMultExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT and the non-transpose dense vector type \a VT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatDVecMultExprTrait<MT,VT>::Type;
+ using Type2 = TSMatDVecMultExprTrait_<MT,VT>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side column-major sparse matrix
+ , typename VT > // Type of the right-hand side non-transpose dense vector
+using TSMatDVecMultExprTrait_ = typename TSMatDVecMultExprTrait<MT,VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatEvalExprTrait.h b/src/cpu/blaze/math/traits/TSMatEvalExprTrait.h
new file mode 100644
index 00000000..25767c0e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatEvalExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatEvalExprTrait.h
+// \brief Header file for the TSMatEvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATEVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATEVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix evaluation operation. Given the column-major sparse matrix type \a MT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a MT is not a
+// column-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the sparse matrix
+struct TSMatEvalExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatEvalExpr<MT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSMatEvalExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatEvalExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatEvalExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TSMatEvalExprTrait class template. For instance, given the column-major sparse
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatEvalExprTrait<MT>::Type;
+ using Type2 = TSMatEvalExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the sparse matrix
+using TSMatEvalExprTrait_ = typename TSMatEvalExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatForEachExprTrait.h b/src/cpu/blaze/math/traits/TSMatForEachExprTrait.h
new file mode 100644
index 00000000..c7c6862e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatForEachExprTrait.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatForEachExprTrait.h
+// \brief Header file for the TSMatForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATFOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATFOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix for-each operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse matrix
+// for-each operation. Given the column-major sparse matrix type \a MT and the custom operation
+// type \a OP, the nested type \a Type corresponds to the resulting expression type. In case \a MT
+// is not a column-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the sparse matrix
+ , typename OP > // Type of the custom operation
+struct TSMatForEachExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatForEachExpr<MT,OP,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSMatForEachExprTrait< Decay_<MT>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The SMatForEachExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the SMatForEachExprTrait class template. For instance, given the column-major sparse
+// matrix type \a MT and the custom operation type \a OP the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TSMatForEachExprTrait<MT,OP>::Type;
+ using Type2 = TSMatForEachExprTrait_<MT,OP>;
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , typename OP > // Type of the custom operation
+using TSMatForEachExprTrait_ = typename TSMatForEachExprTrait<MT,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatSMatAddExprTrait.h b/src/cpu/blaze/math/traits/TSMatSMatAddExprTrait.h
new file mode 100644
index 00000000..3cd4e9b4
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatSMatAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatSMatAddExprTrait.h
+// \brief Header file for the TSMatSMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATSMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATSMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/sparse matrix addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/sparse matrix addition. Given the column-major sparse matrix type \a MT1 and
+// the row-major sparse matrix type \a MT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a MT1 is not a column-major sparse matrix type or \a MT2 is
+// not a row-major sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct TSMatSMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , SMatTSMatAddExpr<MT2,MT1>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatSMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatSMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatSMatAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatSMatAddExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the row-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatSMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatSMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using TSMatSMatAddExprTrait_ = typename TSMatSMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatSMatMultExprTrait.h b/src/cpu/blaze/math/traits/TSMatSMatMultExprTrait.h
new file mode 100644
index 00000000..38953f10
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatSMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatSMatMultExprTrait.h
+// \brief Header file for the TSMatSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/sparse matrix multiplication. Given the column-major sparse matrix type \a MT1
+// and the row-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a column-major sparse matrix type
+// or \a MT2 is not a row-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct TSMatSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TSMatSMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatSMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatSMatMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatSMatMultExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the row-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatSMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatSMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using TSMatSMatMultExprTrait_ = typename TSMatSMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatSMatSubExprTrait.h b/src/cpu/blaze/math/traits/TSMatSMatSubExprTrait.h
new file mode 100644
index 00000000..d620d547
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatSMatSubExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatSMatSubExprTrait.h
+// \brief Header file for the TSMatSMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATSMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATSMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/sparse matrix subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/sparse matrix subtraction. Given the column-major sparse matrix type \a MT1
+// and the row-major sparse matrix type \a MT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT1 is not a column-major sparse matrix type
+// or \a MT2 is not a row-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+struct TSMatSMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
+ , TSMatSMatSubExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatSMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatSMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatSMatSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatSMatSubExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the row-major sparse matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatSMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatSMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side row-major sparse matrix
+using TSMatSMatSubExprTrait_ = typename TSMatSMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatSVecMultExprTrait.h b/src/cpu/blaze/math/traits/TSMatSVecMultExprTrait.h
new file mode 100644
index 00000000..a8641b9a
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatSVecMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatSVecMultExprTrait.h
+// \brief Header file for the TSMatSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/sparse vector multiplication. Given the column-major sparse matrix type \a MT
+// and the non-transpose sparse vector type \a VT, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a MT is not a column-major sparse matrix type or
+// \a VT is not a non-transpose sparse vector type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side column-major sparse matrix
+ , typename VT > // Type of the right-hand side non-transpose sparse vector
+struct TSMatSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>
+ , IsSparseVector<VT>, IsColumnVector<VT> >
+ , TSMatSVecMultExpr<MT,VT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TSMatSVecMultExprTrait< Decay_<MT>, Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatSVecMultExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT and the non-transpose sparse vector type \a VT the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatSVecMultExprTrait<MT,VT>::Type;
+ using Type2 = TSMatSVecMultExprTrait_<MT,VT>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side column-major sparse matrix
+ , typename VT > // Type of the right-hand side non-transpose sparse vector
+using TSMatSVecMultExprTrait_ = typename TSMatSVecMultExprTrait<MT,VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatScalarDivExprTrait.h b/src/cpu/blaze/math/traits/TSMatScalarDivExprTrait.h
new file mode 100644
index 00000000..24f929cf
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatScalarDivExprTrait.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatScalarDivExprTrait.h
+// \brief Header file for the TSMatScalarDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATSCALARDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATSCALARDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TSMatScalarDivExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST
+ , bool Condition >
+struct TSMatScalarDivExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<MT> >, IsBuiltin<ST> >
+ , DivTrait_< UnderlyingBuiltin_<MT>, ST >
+ , DivTrait_< UnderlyingNumeric_<MT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< IsInvertible<ScalarType>
+ , SMatScalarMultExpr<MT,ScalarType,true>
+ , SMatScalarDivExpr<MT,ScalarType,true> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TSMatScalarDivExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST >
+struct TSMatScalarDivExprTraitHelper<MT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/scalar division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/scalar division. Given the column-major sparse matrix type \a MT and the scalar
+// type \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a MT is not a column-major sparse matrix type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST > // Type of the right-hand side scalar
+struct TSMatScalarDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , TSMatScalarDivExprTrait< Decay_<MT>, Decay_<ST> >
+ , TSMatScalarDivExprTraitHelper<MT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatScalarDivExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatScalarDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatScalarDivExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TSMatScalarDivExprTrait<MT,ST>::Type;
+ using Type2 = TSMatScalarDivExprTrait_<MT,ST>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST > // Type of the right-hand side scalar
+using TSMatScalarDivExprTrait_ = typename TSMatScalarDivExprTrait<MT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatScalarMultExprTrait.h b/src/cpu/blaze/math/traits/TSMatScalarMultExprTrait.h
new file mode 100644
index 00000000..7c32fe92
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatScalarMultExprTrait.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatScalarMultExprTrait.h
+// \brief Header file for the TSMatScalarMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATSCALARMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATSCALARMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TSMatScalarMultExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST
+ , bool Condition >
+struct TSMatScalarMultExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<MT> >, IsBuiltin<ST> >
+ , MultTrait_< UnderlyingBuiltin_<MT>, ST >
+ , MultTrait_< UnderlyingNumeric_<MT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = SMatScalarMultExpr<MT,ScalarType,true>;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TSMatScalarMultExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename MT
+ , typename ST >
+struct TSMatScalarMultExprTraitHelper<MT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/scalar multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/scalar multiplication. Given the column-major sparse matrix type \a MT and the
+// scalar type \a ST, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a MT is not a column-major sparse matrix type or \a ST is not a scalar type,
+// the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST > // Type of the right-hand side scalar
+struct TSMatScalarMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , TSMatScalarMultExprTrait< Decay_<MT>, Decay_<ST> >
+ , TSMatScalarMultExprTraitHelper<MT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatScalarMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatScalarMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatScalarMultExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TSMatScalarMultExprTrait<MT,ST>::Type;
+ using Type2 = TSMatScalarMultExprTrait_<MT,ST>;
+ \endcode
+*/
+template< typename MT // Type of the left-hand side sparse matrix
+ , typename ST > // Type of the right-hand side scalar
+using TSMatScalarMultExprTrait_ = typename TSMatScalarMultExprTrait<MT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatSerialExprTrait.h b/src/cpu/blaze/math/traits/TSMatSerialExprTrait.h
new file mode 100644
index 00000000..5d6a74b6
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatSerialExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatSerialExprTrait.h
+// \brief Header file for the TSMatSerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATSERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATSERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix serial evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix serial evaluation operation. Given the column-major sparse matrix type \a MT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a MT is not a
+// column-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the sparse matrix
+struct TSMatSerialExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatSerialExpr<MT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSMatSerialExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatSerialExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatSerialExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TSMatSerialExprTrait class template. For instance, given the column-major sparse
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatSerialExprTrait<MT>::Type;
+ using Type2 = TSMatSerialExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the sparse matrix
+using TSMatSerialExprTrait_ = typename TSMatSerialExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatTDMatAddExprTrait.h b/src/cpu/blaze/math/traits/TSMatTDMatAddExprTrait.h
new file mode 100644
index 00000000..27525fee
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatTDMatAddExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatTDMatAddExprTrait.h
+// \brief Header file for the TSMatTDMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATTDMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATTDMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/transpose dense matrix
+// addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/transpose dense matrix addition. Given the column-major sparse matrix type
+// \a MT1 and the column-major dense matrix type \a MT2, the nested type \a Type corresponds
+// to the resulting expression type. In case either \a MT1 is not a column-major sparse matrix
+// type or \a MT2 is not a column-major dense matrix type, the resulting data type \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct TSMatTDMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsColumnMajorMatrix<MT2> >
+ , DMatSMatAddExpr<MT2,MT1,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatTDMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatTDMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatTDMatAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatTDMatAddExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the column-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatTDMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatTDMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using TSMatTDMatAddExprTrait_ = typename TSMatTDMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatTDMatMultExprTrait.h b/src/cpu/blaze/math/traits/TSMatTDMatMultExprTrait.h
new file mode 100644
index 00000000..6d4e52ba
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatTDMatMultExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatTDMatMultExprTrait.h
+// \brief Header file for the TSMatTDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATTDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATTDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/transpose dense matrix
+// multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/transpose dense matrix multiplication. Given the column-major sparse matrix type
+// \a MT1 and the column-major dense matrix type \a MT2, the nested type \a Type corresponds to
+// the resulting expression type. In case either \a MT1 is not a column-major sparse matrix type
+// or \a MT2 is not a column-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct TSMatTDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsColumnMajorMatrix<MT2> >
+ , TSMatTDMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatTDMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatTDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatTDMatMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatTDMatMultExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the column-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatTDMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatTDMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using TSMatTDMatMultExprTrait_ = typename TSMatTDMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatTDMatSubExprTrait.h b/src/cpu/blaze/math/traits/TSMatTDMatSubExprTrait.h
new file mode 100644
index 00000000..948d8f2e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatTDMatSubExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatTDMatSubExprTrait.h
+// \brief Header file for the TSMatTDMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATTDMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATTDMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/transpose dense matrix
+// subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/transpose dense matrix subtraction. Given the column-major sparse matrix type
+// \a MT1 and the column-major dense matrix type \a MT2, the nested type \a Type corresponds
+// to the resulting expression type. In case either \a MT1 is not a column-major sparse matrix
+// type or \a MT2 is not a column-major dense matrix type, the resulting data type \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+struct TSMatTDMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsDenseMatrix<MT2> , IsColumnMajorMatrix<MT2> >
+ , SMatDMatSubExpr<MT1,MT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatTDMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatTDMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatTDMatSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatTDMatSubExprTrait class template. For instance, given the
+// column-major sparse matrix type \a MT1 and the column-major dense matrix type \a MT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatTDMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatTDMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major dense matrix
+using TSMatTDMatSubExprTrait_ = typename TSMatTDMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatTSMatAddExprTrait.h b/src/cpu/blaze/math/traits/TSMatTSMatAddExprTrait.h
new file mode 100644
index 00000000..a5e94b6f
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatTSMatAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatTSMatAddExprTrait.h
+// \brief Header file for the TSMatTSMatAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATTSMATADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATTSMATADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/transpose sparse matrix
+// addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/transpose sparse matrix addition. Given the two column-major sparse matrix
+// types \a MT1 and \a MT2, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a MT1 or \a MT2 is not a column-major sparse matrix, the resulting data type
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct TSMatTSMatAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TSMatTSMatAddExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatTSMatAddExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatTSMatAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatTSMatAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatTSMatAddExprTrait class template. For instance, given the
+// column-major sparse matrix types \a MT1 and \a MT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TSMatTSMatAddExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatTSMatAddExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using TSMatTSMatAddExprTrait_ = typename TSMatTSMatAddExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatTSMatMultExprTrait.h b/src/cpu/blaze/math/traits/TSMatTSMatMultExprTrait.h
new file mode 100644
index 00000000..584e9a15
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatTSMatMultExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatTSMatMultExprTrait.h
+// \brief Header file for the TSMatTSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATTSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATTSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/transpose sparse matrix
+// multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/transpose sparse matrix multiplication. Given the two column-major sparse matrix
+// types \a MT1 and \a MT2, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a MT1 or \a MT2 is not a column-major sparse matrix, the resulting data type
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct TSMatTSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TSMatTSMatMultExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatTSMatMultExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatTSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatTSMatMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatTSMatMultExprTrait class template. For instance, given the
+// column-major sparse matrix types \a MT1 and \a MT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TSMatTSMatMultExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatTSMatMultExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using TSMatTSMatMultExprTrait_ = typename TSMatTSMatMultExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatTSMatSubExprTrait.h b/src/cpu/blaze/math/traits/TSMatTSMatSubExprTrait.h
new file mode 100644
index 00000000..4759ad25
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatTSMatSubExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatTSMatSubExprTrait.h
+// \brief Header file for the TSMatTSMatSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATTSMATSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATTSMATSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse matrix/transpose sparse matrix
+// subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse matrix/transpose sparse matrix subtraction. Given the two column-major sparse matrix
+// types \a MT1 and \a MT2, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a MT1 or \a MT2 is not a column-major sparse matrix, the resulting data type
+// \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+struct TSMatTSMatSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT1>, IsColumnMajorMatrix<MT1>
+ , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
+ , TSMatTSMatSubExpr<MT1,MT2>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT1>, IsVolatile<MT1>, IsReference<MT1>
+ , IsConst<MT2>, IsVolatile<MT2>, IsReference<MT2> >
+ , TSMatTSMatSubExprTrait< Decay_<MT1>, Decay_<MT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatTSMatSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatTSMatSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSMatTSMatSubExprTrait class template. For instance, given the
+// column-major sparse matrix types \a MT1 and \a MT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TSMatTSMatSubExprTrait<MT1,MT2>::Type;
+ using Type2 = TSMatTSMatSubExprTrait_<MT1,MT2>;
+ \endcode
+*/
+template< typename MT1 // Type of the left-hand side column-major sparse matrix
+ , typename MT2 > // Type of the right-hand side column-major sparse matrix
+using TSMatTSMatSubExprTrait_ = typename TSMatTSMatSubExprTrait<MT1,MT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSMatTransExprTrait.h b/src/cpu/blaze/math/traits/TSMatTransExprTrait.h
new file mode 100644
index 00000000..51177d5b
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSMatTransExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSMatTransExprTrait.h
+// \brief Header file for the TSMatTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSMATTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSMATTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse matrix transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// matrix transpose operation. Given the column-major sparse matrix type \a MT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a MT is not a
+// column-major sparse matrix type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename MT > // Type of the sparse matrix
+struct TSMatTransExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , SMatTransExpr<MT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSMatTransExprTrait< Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSMatTransExprTrait class template.
+// \ingroup math_traits
+//
+// The TSMatTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TSMatTransExprTrait class template. For instance, given the column-major sparse
+// matrix type \a MT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSMatTransExprTrait<MT>::Type;
+ using Type2 = TSMatTransExprTrait_<MT>;
+ \endcode
+*/
+template< typename MT > // Type of the sparse matrix
+using TSMatTransExprTrait_ = typename TSMatTransExprTrait<MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecCTransExprTrait.h b/src/cpu/blaze/math/traits/TSVecCTransExprTrait.h
new file mode 100644
index 00000000..1807c921
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecCTransExprTrait.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecCTransExprTrait.h
+// \brief Header file for the TSVecCTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECCTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECCTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/functors/Forward.h>
+#include <blaze/math/traits/TSVecForEachExprTrait.h>
+#include <blaze/math/traits/TSVecTransExprTrait.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector conjugate transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector conjugate transpose operation. Given the transpose sparse vector type \a VT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a VT is not
+// a transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the sparse vector
+struct TSVecCTransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , TSVecTransExprTrait< TSVecForEachExprTrait_<VT,Conj> >
+ , Failure >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TSVecCTransExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecCTransExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecCTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TSVecCTransExprTrait class template. For instance, given the transpose sparse
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecCTransExprTrait<VT>::Type;
+ using Type2 = TSVecCTransExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the sparse vector
+using TSVecCTransExprTrait_ = typename TSVecCTransExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecDMatMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecDMatMultExprTrait.h
new file mode 100644
index 00000000..70e7888f
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecDMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecDMatMultExprTrait.h
+// \brief Header file for the TSVecDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/dense matrix multiplication. Given the transpose sparse vector type \a VT and the
+// row-major dense matrix type \a MT, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT is not a transpose sparse vector type or \a MT is
+// not a row-major dense matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side transpose sparse vector
+ , typename MT > // Type of the right-hand side row-major dense matrix
+struct TSVecDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT> , IsRowMajorMatrix<MT> >
+ , TSVecDMatMultExpr<VT,MT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSVecDMatMultExprTrait< Decay_<VT>, Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecDMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TSVecDMatMultExprTrait class template. For instance, given the transpose
+// sparse vector type \a VT and the row-major dense matrix type \a MT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TSVecDMatMultExprTrait<VT,MT>::Type;
+ using Type2 = TSVecDMatMultExprTrait_<VT,MT>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side transpose sparse vector
+ , typename MT > // Type of the right-hand side row-major dense matrix
+using TSVecDMatMultExprTrait_ = typename TSVecDMatMultExprTrait<VT,MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecDVecMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecDVecMultExprTrait.h
new file mode 100644
index 00000000..8e04d0ef
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecDVecMultExprTrait.h
@@ -0,0 +1,158 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecDVecMultExprTrait.h
+// \brief Header file for the TSVecDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TSVecDVecMultExprTrait.
+// \ingroup math_traits
+*/
+template< typename VT1
+ , typename VT2
+ , bool Valid >
+struct TSVecDVecMultExprTraitHelper
+{
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TSVecDVecMultExprTrait auxiliary helper struct.
+// \ingroup math_traits
+*/
+template< typename VT1
+ , typename VT2 >
+struct TSVecDVecMultExprTraitHelper<VT1,VT2,true>
+{
+ //**********************************************************************************************
+ using Type = MultTrait_< ElementType_<VT1>, ElementType_<VT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/dense vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/dense vector multiplication (inner product). Given the transpose sparse vector
+// type \a VT1 and the non-transpose dense vector type \a VT2, the nested type \a Type corresponds
+// to the resulting expression type. In case either \a VT1 is not a transpose sparse vector
+// type or \a VT2 is not a non-transpose dense vector type, the resulting \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+struct TSVecDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { valid = IsSparseVector<VT1>::value && IsRowVector<VT1>::value &&
+ IsDenseVector<VT2>::value && IsColumnVector<VT2>::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecDVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , TSVecDVecMultExprTraitHelper<VT1,VT2,valid> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecDVecMultExprTrait class template. For instance, given
+// the transpose sparse vector type \a VT1 and non-transpose dense vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecDVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecDVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose dense vector
+using TSVecDVecMultExprTrait_ = typename TSVecDVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecEvalExprTrait.h b/src/cpu/blaze/math/traits/TSVecEvalExprTrait.h
new file mode 100644
index 00000000..7d9c5546
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecEvalExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecEvalExprTrait.h
+// \brief Header file for the TSVecEvalExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECEVALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECEVALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector evaluation operation. Given the transpose sparse vector type \a VT, the nested
+// type \a Type corresponds to the resulting expression type. In case \a VT is not a
+// transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the sparse vector
+struct TSVecEvalExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecEvalExpr<VT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TSVecEvalExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecEvalExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecEvalExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TSVecEvalExprTrait class template. For instance, given the transpose sparse
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecEvalExprTrait<VT>::Type;
+ using Type2 = TSVecEvalExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the sparse vector
+using TSVecEvalExprTrait_ = typename TSVecEvalExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecForEachExprTrait.h b/src/cpu/blaze/math/traits/TSVecForEachExprTrait.h
new file mode 100644
index 00000000..7104b1c0
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecForEachExprTrait.h
@@ -0,0 +1,119 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecForEachExprTrait.h
+// \brief Header file for the TSVecForEachExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECFOREACHEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECFOREACHEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector for-each operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse vector
+// custom operation. Given the transpose sparse vector type \a VT and the custom operation type
+// \a OP, the nested type \a Type corresponds to the resulting expression type. In case \a VT is
+// not a transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the sparse vector
+ , typename OP > // Type of the custom operation
+struct TSVecForEachExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecForEachExpr<VT,OP,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TSVecForEachExprTrait< Decay_<VT>, OP >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecForEachExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecForEachExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TSVecForEachExprTrait class template. For instance, given the transpose
+// sparse vector type \a VT and the custom operation type \a OP the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename TSVecForEachExprTrait<VT,OP>::Type;
+ using Type2 = TSVecForEachExprTrait_<VT,OP>;
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , typename OP > // Type of the custom operation
+using TSVecForEachExprTrait_ = typename TSVecForEachExprTrait<VT,OP>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecSMatMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecSMatMultExprTrait.h
new file mode 100644
index 00000000..9e8e2153
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecSMatMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecSMatMultExprTrait.h
+// \brief Header file for the TSVecSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/sparse matrix multiplication. Given the transpose sparse vector type \a VT and the
+// row-major sparse matrix type \a MT, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT is not a transpose sparse vector type or \a MT is
+// not a row-major sparse matrix type, the resulting data type \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side transpose sparse vector
+ , typename MT > // Type of the right-hand side row-major sparse matrix
+struct TSVecSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsRowMajorMatrix<MT> >
+ , TSVecSMatMultExpr<VT,MT>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSVecSMatMultExprTrait< Decay_<VT>, Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecSMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TSVecSMatMultExprTrait class template. For instance, given the transpose
+// sparse vector type \a VT and the row-major sparse matrix type \a MT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TSVecSMatMultExprTrait<VT,MT>::Type;
+ using Type2 = TSVecSMatMultExprTrait_<VT,MT>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side transpose sparse vector
+ , typename MT > // Type of the right-hand side row-major sparse matrix
+using TSVecSMatMultExprTrait_ = typename TSVecSMatMultExprTrait<VT,MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecSVecMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecSVecMultExprTrait.h
new file mode 100644
index 00000000..70083024
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecSVecMultExprTrait.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecSVecMultExprTrait.h
+// \brief Header file for the TSVecSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsColumnVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TSVecSVecMultExprTrait.
+// \ingroup math_traits
+*/
+template< typename VT1
+ , typename VT2
+ , bool Valid >
+struct TSVecSVecMultExprTraitHelper
+{
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TSVecSVecMultExprTrait auxiliary helper struct.
+// \ingroup math_traits
+*/
+template< typename VT1
+ , typename VT2 >
+struct TSVecSVecMultExprTraitHelper<VT1,VT2,true>
+{
+ //**********************************************************************************************
+ using Type = MultTrait_< ElementType_<VT1>, ElementType_<VT2> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/sparse vector multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/sparse vector multiplication (inner product). Given the transpose sparse vector
+// type \a VT1 and the non-transpose sparse vector type \a VT2, the nested type \a Type corresponds
+// to the resulting expression type. In case either \a VT1 is not a transpose sparse vector
+// type or \a VT2 is not a non-transpose sparse vector type, the resulting \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+struct TSVecSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { valid = IsSparseVector<VT1>::value && IsRowVector<VT1>::value &&
+ IsSparseVector<VT2>::value && IsColumnVector<VT2>::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecSVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , TSVecSVecMultExprTraitHelper<VT1,VT2,valid> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecSVecMultExprTrait class template. For instance, given
+// the transpose sparse vector type \a VT1 and non-transpose sparse vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecSVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecSVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side non-transpose sparse vector
+using TSVecSVecMultExprTrait_ = typename TSVecSVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecScalarDivExprTrait.h b/src/cpu/blaze/math/traits/TSVecScalarDivExprTrait.h
new file mode 100644
index 00000000..9df29be6
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecScalarDivExprTrait.h
@@ -0,0 +1,172 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecScalarDivExprTrait.h
+// \brief Header file for the TSVecScalarDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECSCALARDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECSCALARDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/typetraits/IsInvertible.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TSVecScalarDivExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST
+ , bool Condition >
+struct TSVecScalarDivExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<VT> >, IsBuiltin<ST> >
+ , DivTrait_< UnderlyingBuiltin_<VT> ,ST >
+ , DivTrait_< UnderlyingNumeric_<VT>, ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = If_< IsInvertible<ScalarType>
+ , SVecScalarMultExpr<VT,ScalarType,true>
+ , SVecScalarDivExpr<VT,ScalarType,true> >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TSVecScalarDivExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST >
+struct TSVecScalarDivExprTraitHelper<VT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/scalar division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/scalar division. Given the transpose sparse vector type \a VT and the scalar
+// type \a ST, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT is not a transpose sparse vector type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST > // Type of the right-hand side scalar
+struct TSVecScalarDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsSparseVector<VT>, IsRowVector<VT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , TSVecScalarDivExprTrait< Decay_<VT>, Decay_<ST> >
+ , TSVecScalarDivExprTraitHelper<VT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecScalarDivExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecScalarDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecScalarDivExprTrait class template. For instance, given
+// the transpose sparse vector type \a VT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TSVecScalarDivExprTrait<VT,ST>::Type;
+ using Type2 = TSVecScalarDivExprTrait_<VT,ST>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST > // Type of the right-hand side scalar
+using TSVecScalarDivExprTrait_ = typename TSVecScalarDivExprTrait<VT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecScalarMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecScalarMultExprTrait.h
new file mode 100644
index 00000000..64f1f45b
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecScalarMultExprTrait.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecScalarMultExprTrait.h
+// \brief Header file for the TSVecScalarMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECSCALARMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECSCALARMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/UnderlyingBuiltin.h>
+#include <blaze/math/typetraits/UnderlyingNumeric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the TSVecScalarMultExprTrait trait.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST
+ , bool Condition >
+struct TSVecScalarMultExprTraitHelper
+{
+ private:
+ //**********************************************************************************************
+ using ScalarType = If_< And< IsComplex< UnderlyingNumeric_<VT> >, IsBuiltin<ST> >
+ , MultTrait_< UnderlyingBuiltin_<VT>, ST >
+ , MultTrait_< UnderlyingNumeric_<VT> ,ST > >;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ using Type = SVecScalarMultExpr<VT,ScalarType,true>;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TSVecScalarMultExprTraitHelper class template.
+// \ingroup math_traits
+*/
+template< typename VT
+ , typename ST >
+struct TSVecScalarMultExprTraitHelper<VT,ST,false>
+{
+ public:
+ //**********************************************************************************************
+ using Type = INVALID_TYPE;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/scalar multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/scalar multiplication. Given the transpose sparse vector type \a VT and the
+// scalar type \a ST, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a VT is not a transpose sparse vector type or \a ST is not a scalar type, the
+// resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST > // Type of the right-hand side scalar
+struct TSVecScalarMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ enum : bool { condition = And< IsSparseVector<VT>, IsRowVector<VT>, IsNumeric<ST> >::value };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<ST>, IsVolatile<ST>, IsReference<ST> >
+ , TSVecScalarMultExprTrait< Decay_<VT>, Decay_<ST> >
+ , TSVecScalarMultExprTraitHelper<VT,ST,condition> >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecScalarMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecScalarMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecScalarMultExprTrait class template. For instance, given
+// the transpose sparse vector type \a VT and the scalar type \a ST the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TSVecScalarMultExprTrait<VT,ST>::Type;
+ using Type2 = TSVecScalarMultExprTrait_<VT,ST>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side sparse vector
+ , typename ST > // Type of the right-hand side scalar
+using TSVecScalarMultExprTrait_ = typename TSVecScalarMultExprTrait<VT,ST>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecSerialExprTrait.h b/src/cpu/blaze/math/traits/TSVecSerialExprTrait.h
new file mode 100644
index 00000000..1b2b484e
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecSerialExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecSerialExprTrait.h
+// \brief Header file for the TSVecSerialExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECSERIALEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECSERIALEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector serial evaluation operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector serial evaluation operation. Given the transpose sparse vector type \a VT, the
+// nested type \a Type corresponds to the resulting expression type. In case \a VT is not
+// a transpose sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the sparse vector
+struct TSVecSerialExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecSerialExpr<VT,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TSVecSerialExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecSerialExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecSerialExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TSVecSerialExprTrait class template. For instance, given the transpose sparse
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecSerialExprTrait<VT>::Type;
+ using Type2 = TSVecSerialExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the sparse vector
+using TSVecSerialExprTrait_ = typename TSVecSerialExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTDMatMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecTDMatMultExprTrait.h
new file mode 100644
index 00000000..1bbb1370
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTDMatMultExprTrait.h
@@ -0,0 +1,129 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTDMatMultExprTrait.h
+// \brief Header file for the TSVecTDMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTDMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTDMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/transpose dense matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/transpose dense matrix multiplication. Given the transpose sparse vector type \a VT
+// and the column-major dense matrix type \a MT, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT is not a transpose sparse vector type or
+// \a MT is not a column-major dense matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side transpose sparse vector
+ , typename MT > // Type of the right-hand side column-major dense matrix
+struct TSVecTDMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsDenseMatrix<MT> , IsColumnMajorMatrix<MT> >
+ , If_< IsSymmetric<MT>
+ , TSVecDMatMultExpr< VT, TDMatTransExprTrait_<MT> >
+ , TSVecTDMatMultExpr<VT,MT> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSVecTDMatMultExprTrait< Decay_<VT>, Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTDMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTDMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TSVecTDMatMultExprTrait class template. For instance, given the transpose
+// sparse vector type \a VT and the column-major dense matrix type \a MT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TSVecTDMatMultExprTrait<VT,MT>::Type;
+ using Type2 = TSVecTDMatMultExprTrait_<VT,MT>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side transpose sparse vector
+ , typename MT > // Type of the right-hand side column-major dense matrix
+using TSVecTDMatMultExprTrait_ = typename TSVecTDMatMultExprTrait<VT,MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTDVecAddExprTrait.h b/src/cpu/blaze/math/traits/TSVecTDVecAddExprTrait.h
new file mode 100644
index 00000000..b9551cad
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTDVecAddExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTDVecAddExprTrait.h
+// \brief Header file for the TSVecTDVecAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTDVECADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTDVECADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/transpose dense vector
+// addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/transpose dense vector addition. Given the transpose sparse vector type \a VT1
+// and the transpose dense vector type \a VT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT1 is not a transpose sparse vector type or
+// \a VT2 is not a transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TSVecTDVecAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2> , IsRowVector<VT2> >
+ , DVecSVecAddExpr<VT2,VT1,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTDVecAddExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTDVecAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTDVecAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTDVecAddExprTrait class template. For instance, given
+// the transpose sparse vector types \a VT1 and the transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecTDVecAddExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTDVecAddExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TSVecTDVecAddExprTrait_ = typename TSVecTDVecAddExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTDVecCrossExprTrait.h b/src/cpu/blaze/math/traits/TSVecTDVecCrossExprTrait.h
new file mode 100644
index 00000000..927814f4
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTDVecCrossExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTDVecCrossExprTrait.h
+// \brief Header file for the TSVecTDVecCrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTDVECCROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTDVECCROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/dense vector cross product.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/dense vector cross product. Given the transpose sparse vector type \a VT1 and the
+// transpose dense vector type\a VT2, the nested type \a Type corresponds to the resulting
+// expression type. In case either \a VT1 is not a transpose sparse vector type or \a VT2
+// is not a transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TSVecTDVecCrossExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2> , IsRowVector<VT2> >
+ , SVecDVecCrossExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTDVecCrossExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTDVecCrossExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTDVecCrossExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTDVecCrossExprTrait class template. For instance, given
+// the transpose sparse vector types \a VT1 and the transpose dense vector type \a VT2 the
+// following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecTDVecCrossExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTDVecCrossExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TSVecTDVecCrossExprTrait_ = typename TSVecTDVecCrossExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTDVecDivExprTrait.h b/src/cpu/blaze/math/traits/TSVecTDVecDivExprTrait.h
new file mode 100644
index 00000000..a0ec5966
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTDVecDivExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTDVecDivExprTrait.h
+// \brief Header file for the TSVecTDVecDivExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTDVECDIVEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTDVECDIVEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/transpose dense vector
+// division.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/transpose dense vector division. Given the transpose sparse vector type \a VT1
+// and the transpose dense vector type \a VT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT1 is not a transpose sparse vector type or
+// \a VT2 is not a transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TSVecTDVecDivExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2> , IsRowVector<VT2> >
+ , SVecDVecDivExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTDVecDivExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTDVecDivExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTDVecDivExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTDVecDivExprTrait class template. For instance, given
+// the transpose sparse vector types \a VT1 and the transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecTDVecDivExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTDVecDivExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TSVecTDVecDivExprTrait_ = typename TSVecTDVecDivExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTDVecMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecTDVecMultExprTrait.h
new file mode 100644
index 00000000..05720a07
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTDVecMultExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTDVecMultExprTrait.h
+// \brief Header file for the TSVecTDVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTDVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTDVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/transpose dense vector
+// multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/transpose dense vector multiplication. Given the transpose sparse vector type
+// \a VT1 and the transpose dense vector type \a VT2, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT1 is not a transpose sparse vector type or
+// \a VT2 is not a transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TSVecTDVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2> , IsRowVector<VT2> >
+ , SVecDVecMultExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTDVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTDVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTDVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTDVecMultExprTrait class template. For instance, given
+// the transpose sparse vector types \a VT1 and the transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecTDVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTDVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TSVecTDVecMultExprTrait_ = typename TSVecTDVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTDVecSubExprTrait.h b/src/cpu/blaze/math/traits/TSVecTDVecSubExprTrait.h
new file mode 100644
index 00000000..e97e4a3f
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTDVecSubExprTrait.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTDVecSubExprTrait.h
+// \brief Header file for the TSVecTDVecSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTDVECSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTDVECSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/transpose dense vector
+// subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/transpose dense vector subtraction. Given the transpose sparse vector type
+// \a VT1 and the transpose dense vector type \a VT2, the nested type \a Type corresponds to
+// the resulting expression type. In case either \a VT1 is not a transpose sparse vector type or
+// \a VT2 is not a transpose dense vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+struct TSVecTDVecSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsDenseVector<VT2> , IsRowVector<VT2> >
+ , SVecDVecSubExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTDVecSubExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTDVecSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTDVecSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTDVecSubExprTrait class template. For instance, given
+// the transpose sparse vector types \a VT1 and the transpose dense vector type \a VT2
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecTDVecSubExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTDVecSubExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose dense vector
+using TSVecTDVecSubExprTrait_ = typename TSVecTDVecSubExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTSMatMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecTSMatMultExprTrait.h
new file mode 100644
index 00000000..51e9e0b7
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTSMatMultExprTrait.h
@@ -0,0 +1,129 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTSMatMultExprTrait.h
+// \brief Header file for the TSVecTSMatMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTSMATMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTSMATMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/traits/TSMatTransExprTrait.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/transpose sparse matrix multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/transpose sparse matrix multiplication. Given the transpose sparse vector type \a VT
+// and the column-major sparse matrix type \a MT, the nested type \a Type corresponds to the
+// resulting expression type. In case either \a VT is not a transpose sparse vector type or
+// \a MT is not a column-major sparse matrix type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename VT // Type of the left-hand side transpose sparse vector
+ , typename MT > // Type of the right-hand side column-major sparse matrix
+struct TSVecTSMatMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsRowVector<VT>
+ , IsSparseMatrix<MT>, IsColumnMajorMatrix<MT> >
+ , If_< IsSymmetric<MT>
+ , TSVecSMatMultExpr< VT, TSMatTransExprTrait_<MT> >
+ , TSVecTSMatMultExpr<VT,MT> >
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT>
+ , IsConst<MT>, IsVolatile<MT>, IsReference<MT> >
+ , TSVecTSMatMultExprTrait< Decay_<VT>, Decay_<MT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTSMatMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTSMatMultExprTrait_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the TSVecTSMatMultExprTrait class template. For instance, given the transpose
+// sparse vector type \a VT and the column-major sparse matrix type \a MT the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename TSVecTSMatMultExprTrait<VT,MT>::Type;
+ using Type2 = TSVecTSMatMultExprTrait_<VT,MT>;
+ \endcode
+*/
+template< typename VT // Type of the left-hand side transpose sparse vector
+ , typename MT > // Type of the right-hand side column-major sparse matrix
+using TSVecTSMatMultExprTrait_ = typename TSVecTSMatMultExprTrait<VT,MT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTSVecAddExprTrait.h b/src/cpu/blaze/math/traits/TSVecTSVecAddExprTrait.h
new file mode 100644
index 00000000..df76ddba
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTSVecAddExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTSVecAddExprTrait.h
+// \brief Header file for the TSVecTSVecAddExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTSVECADDEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTSVECADDEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/transpose sparse vector
+// addition.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/transpose sparse vector addition. Given the two transpose sparse vector types
+// \a VT1 and \a VT2, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a VT1 or \a VT2 is not a transpose sparse vector type, the resulting \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct TSVecTSVecAddExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , SVecSVecAddExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTSVecAddExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTSVecAddExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTSVecAddExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTSVecAddExprTrait class template. For instance, given the
+// transpose sparse vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TSVecTSVecAddExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTSVecAddExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using TSVecTSVecAddExprTrait_ = typename TSVecTSVecAddExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTSVecCrossExprTrait.h b/src/cpu/blaze/math/traits/TSVecTSVecCrossExprTrait.h
new file mode 100644
index 00000000..4d2e4f35
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTSVecCrossExprTrait.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTSVecCrossExprTrait.h
+// \brief Header file for the TSVecTSVecCrossExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTSVECCROSSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTSVECCROSSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector/sparse vector cross product.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector/sparse vector cross product. Given the two transpose sparse vector types \a VT1
+// and \a VT2, the nested type \a Type corresponds to the resulting expression type. In case
+// either \a VT1 or \a VT2 is not a transpose sparse vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct TSVecTSVecCrossExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , SVecSVecCrossExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTSVecCrossExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTSVecCrossExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTSVecCrossExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTSVecCrossExprTrait class template. For instance, given the
+// transpose sparse vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TSVecTSVecCrossExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTSVecCrossExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using TSVecTSVecCrossExprTrait_ = typename TSVecTSVecCrossExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTSVecMultExprTrait.h b/src/cpu/blaze/math/traits/TSVecTSVecMultExprTrait.h
new file mode 100644
index 00000000..e8f5d5aa
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTSVecMultExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTSVecMultExprTrait.h
+// \brief Header file for the TSVecTSVecMultExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTSVECMULTEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTSVECMULTEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/transpose sparse vector
+// multiplication.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/transpose sparse vector multiplication. Given the two transpose sparse vector
+// types \a VT1 and \a VT2, the nested type \a Type corresponds to the resulting expression type.
+// In case either \a VT1 or \a VT2 is not a transpose sparse vector type, the resulting \a Type
+// is set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct TSVecTSVecMultExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , SVecSVecMultExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTSVecMultExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTSVecMultExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTSVecMultExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTSVecMultExprTrait class template. For instance, given the
+// transpose sparse vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TSVecTSVecMultExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTSVecMultExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using TSVecTSVecMultExprTrait_ = typename TSVecTSVecMultExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTSVecSubExprTrait.h b/src/cpu/blaze/math/traits/TSVecTSVecSubExprTrait.h
new file mode 100644
index 00000000..17a8e5e0
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTSVecSubExprTrait.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTSVecSubExprTrait.h
+// \brief Header file for the TSVecTSVecSubExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTSVECSUBEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTSVECSUBEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a transpose sparse vector/transpose sparse vector
+// subtraction.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a transpose
+// sparse vector/transpose sparse vector subtraction. Given the two transpose sparse vector types
+// \a VT1 and \a VT2, the nested type \a Type corresponds to the resulting expression type. In
+// case either \a VT1 or \a VT2 is not a transpose sparse vector type, the resulting \a Type is
+// set to \a INVALID_TYPE.
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+struct TSVecTSVecSubExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT1>, IsRowVector<VT1>
+ , IsSparseVector<VT2>, IsRowVector<VT2> >
+ , SVecSVecSubExpr<VT1,VT2,true>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT1>, IsVolatile<VT1>, IsReference<VT1>
+ , IsConst<VT2>, IsVolatile<VT2>, IsReference<VT2> >
+ , TSVecTSVecSubExprTrait< Decay_<VT1>, Decay_<VT2> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTSVecSubExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTSVecSubExprTrait_ alias declaration provides a convenient shortcut to access
+// the nested \a Type of the TSVecTSVecSubExprTrait class template. For instance, given the
+// transpose sparse vector types \a VT1 and \a VT2 the following two type definitions are
+// identical:
+
+ \code
+ using Type1 = typename TSVecTSVecSubExprTrait<VT1,VT2>::Type;
+ using Type2 = TSVecTSVecSubExprTrait_<VT1,VT2>;
+ \endcode
+*/
+template< typename VT1 // Type of the left-hand side transpose sparse vector
+ , typename VT2 > // Type of the right-hand side transpose sparse vector
+using TSVecTSVecSubExprTrait_ = typename TSVecTSVecSubExprTrait<VT1,VT2>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TSVecTransExprTrait.h b/src/cpu/blaze/math/traits/TSVecTransExprTrait.h
new file mode 100644
index 00000000..cc047b74
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TSVecTransExprTrait.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TSVecTransExprTrait.h
+// \brief Header file for the TSVecTransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TSVECTRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TSVECTRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the expression type of a sparse vector transpose operation.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the resulting expression type of a sparse
+// vector transpose operation. Given the transpose sparse vector type \a VT, the nested type
+// \a Type corresponds to the resulting expression type. In case \a VT is not a transpose
+// sparse vector type, the resulting \a Type is set to \a INVALID_TYPE.
+*/
+template< typename VT > // Type of the sparse vector
+struct TSVecTransExprTrait
+{
+ private:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If< And< IsSparseVector<VT>, IsRowVector<VT> >
+ , SVecTransExpr<VT,false>
+ , INVALID_TYPE >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<VT>, IsVolatile<VT>, IsReference<VT> >
+ , TSVecTransExprTrait< Decay_<VT> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TSVecTransExprTrait class template.
+// \ingroup math_traits
+//
+// The TSVecTransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TSVecTransExprTrait class template. For instance, given the transpose sparse
+// vector type \a VT the following two type definitions are identical:
+
+ \code
+ using Type1 = typename TSVecTransExprTrait<VT>::Type;
+ using Type2 = TSVecTransExprTrait_<VT>;
+ \endcode
+*/
+template< typename VT > // Type of the sparse vector
+using TSVecTransExprTrait_ = typename TSVecTransExprTrait<VT>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/traits/Traits.h b/src/cpu/blaze/math/traits/Traits.h
new file mode 100644
index 00000000..55690966
--- /dev/null
+++ b/src/cpu/blaze/math/traits/Traits.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/Traits.h
+// \brief Mathematical expression traits module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TRAITS_H_
+#define _BLAZE_MATH_TRAITS_TRAITS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup math_traits Expression traits
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/traits/TransExprTrait.h b/src/cpu/blaze/math/traits/TransExprTrait.h
new file mode 100644
index 00000000..34344f39
--- /dev/null
+++ b/src/cpu/blaze/math/traits/TransExprTrait.h
@@ -0,0 +1,148 @@
+//=================================================================================================
+/*!
+// \file blaze/math/traits/TransExprTrait.h
+// \brief Header file for the TransExprTrait class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TRAITS_TRANSEXPRTRAIT_H_
+#define _BLAZE_MATH_TRAITS_TRANSEXPRTRAIT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/traits/DMatTransExprTrait.h>
+#include <blaze/math/traits/DVecTransExprTrait.h>
+#include <blaze/math/traits/SMatTransExprTrait.h>
+#include <blaze/math/traits/SVecTransExprTrait.h>
+#include <blaze/math/traits/TDMatTransExprTrait.h>
+#include <blaze/math/traits/TDVecTransExprTrait.h>
+#include <blaze/math/traits/TSMatTransExprTrait.h>
+#include <blaze/math/traits/TSVecTransExprTrait.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the return type of a transpose expression.
+// \ingroup math_traits
+//
+// Via this type trait it is possible to evaluate the return type of a transpose expression.
+// Given the type \a T, which must either be a vector or matrix type, the nested type \a Type
+// corresponds to the resulting return type. In case the type of \a T doesn't fit or if
+// no transpose operation exists for the type, the resulting data type \a Type is set to
+// \a INVALID_TYPE.
+*/
+template< typename T > // Type of the transpose operand
+struct TransExprTrait
+{
+ private:
+ //**struct Failure******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ struct Failure { using Type = INVALID_TYPE; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Tmp = If_< IsMatrix<T>
+ , If_< IsDenseMatrix<T>
+ , If_< IsRowMajorMatrix<T>
+ , DMatTransExprTrait<T>
+ , TDMatTransExprTrait<T> >
+ , If_< IsRowMajorMatrix<T>
+ , SMatTransExprTrait<T>
+ , TSMatTransExprTrait<T> > >
+ , If_< IsVector<T>
+ , If_< IsDenseVector<T>
+ , If_< IsRowVector<T>
+ , TDVecTransExprTrait<T>
+ , DVecTransExprTrait<T> >
+ , If_< IsRowVector<T>
+ , TSVecTransExprTrait<T>
+ , SVecTransExprTrait<T> > >
+ , Failure > >;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using Type = typename If_< Or< IsConst<T>, IsVolatile<T>, IsReference<T> >
+ , TransExprTrait< Decay_<T> >
+ , Tmp >::Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the TransExprTrait class template.
+// \ingroup math_traits
+//
+// The TransExprTrait_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the TransExprTrait class template. For instance, given the type \a T the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename TransExprTrait<T>::Type;
+ using Type2 = TransExprTrait_<T>;
+ \endcode
+*/
+template< typename T > // Type of the transpose operand
+using TransExprTrait_ = typename TransExprTrait<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/AreSIMDCombinable.h b/src/cpu/blaze/math/typetraits/AreSIMDCombinable.h
new file mode 100644
index 00000000..084101f9
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/AreSIMDCombinable.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/AreSIMDCombinable.h
+// \brief Header file for the AreSIMDCombinable type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ARESIMDCOMBINABLE_H_
+#define _BLAZE_MATH_TYPETRAITS_ARESIMDCOMBINABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the AreSIMDCombinable type trait.
+// \ingroup math_type_traits
+*/
+template< typename T1
+ , typename T2
+ , typename... Args >
+struct AreSIMDCombinableHelper
+{
+ enum : bool { value = AreSIMDCombinableHelper<T1,T2>::value &&
+ AreSIMDCombinableHelper<T2,Args...>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the AreSIMDCombinableHelper class template for two matching types.
+template< typename T >
+struct AreSIMDCombinableHelper<T,T>
+{
+ enum : bool { value = IsNumeric<T>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the AreSIMDCombinableHelper class template for two different types.
+template< typename T1, typename T2 >
+struct AreSIMDCombinableHelper<T1,T2>
+{
+ enum : bool { value = IsNumeric<T1>::value && IsIntegral<T1>::value &&
+ IsNumeric<T2>::value && IsIntegral<T2>::value &&
+ sizeof(T1) == sizeof(T2) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time check for data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given types can be combined in the context of SIMD
+// operations. By default, all numeric data types are considered combinable to themselves. Also,
+// different integral types of the same size can be combined. If the types are determined to be
+// SIMD combinable, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::AreSIMDCombinable< int, unsigned int >::value // Evaluates to 1
+ blaze::AreSIMDCombinable< double, double >::Type // Results in TrueType
+ blaze::AreSIMDCombinable< complex<float>, complex<float> > // Is derived from TrueType
+ blaze::AreSIMDCombinable< int, float >::value // Evaluates to 0
+ blaze::AreSIMDCombinable< double, float >::Type // Results in FalseType
+ blaze::AreSIMDCombinable< complex<int>, complex<float> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T1, typename T2, typename... Args >
+struct AreSIMDCombinable
+ : public BoolConstant< AreSIMDCombinableHelper< T1, T2, Decay_<Args>... >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/Columns.h b/src/cpu/blaze/math/typetraits/Columns.h
new file mode 100644
index 00000000..677d96ec
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/Columns.h
@@ -0,0 +1,118 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/Columns.h
+// \brief Header file for the Columns type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_COLUMNS_H_
+#define _BLAZE_MATH_TYPETRAITS_COLUMNS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time evaluation of the number of columns of a matrix.
+// \ingroup math_type_traits
+//
+// The Columns type trait evaluates the number of columns of the given matrix type at compile time.
+// In case the given type \a T is a matrix type with a fixed number of columns (e.g. StaticMatrix),
+// the \a value member constant is set to the according number of columns. In all other cases,
+// \a value is set to 0.
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::HybridMatrix;
+ using blaze::DynamicMatrix;
+
+ blaze::Columns< StaticMatrix<int,3UL,2UL> >::value // Evaluates to 2
+ blaze::Columns< HybridMatrix<int,3UL,2UL> >::value // Evaluates to 0; Only maximum number of columns is fixed!
+ blaze::Columns< DynamicMatrix<int> >::value // Evaluates to 0; Number of columns not fixed at compile time!
+ blaze::Columns< int >::value // Evaluates to 0
+ \endcode
+*/
+template< typename T >
+struct Columns : public SizeT<0UL>
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Columns type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Columns< const T > : public SizeT< Columns<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Columns type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Columns< volatile T > : public SizeT< Columns<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Columns type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Columns< const volatile T > : public SizeT< Columns<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasConstDataAccess.h b/src/cpu/blaze/math/typetraits/HasConstDataAccess.h
new file mode 100644
index 00000000..443973a6
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasConstDataAccess.h
@@ -0,0 +1,117 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasConstDataAccess.h
+// \brief Header file for the HasConstDataAccess type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASCONSTDATAACCESS_H_
+#define _BLAZE_MATH_TYPETRAITS_HASCONSTDATAACCESS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for low-level access to constant data.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type provides a low-level access to constant
+// data via a const 'data' member function. In case the according member function is provided,
+// the \a value member constant is set to \a true, the nested type definition \a Type is
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType, and the class derives from \a FalseType. Examples:
+
+ \code
+ blaze::HasConstDataAccess< StaticVector<float,3U> >::value // Evaluates to 1
+ blaze::HasConstDataAccess< const DynamicVector<double> >::Type // Results in TrueType
+ blaze::HasConstDataAccess< volatile DynamicMatrix<int> > // Is derived from TrueType
+ blaze::HasConstDataAccess< int >::value // Evaluates to 0
+ blaze::HasConstDataAccess< const CompressedVector<int> >::Type // Results in FalseType
+ blaze::HasConstDataAccess< volatile CompressedMatrix<int> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct HasConstDataAccess : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasConstDataAccess type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct HasConstDataAccess< const T > : public HasConstDataAccess<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasConstDataAccess type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct HasConstDataAccess< volatile T > : public HasConstDataAccess<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasConstDataAccess type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct HasConstDataAccess< const volatile T > : public HasConstDataAccess<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasMutableDataAccess.h b/src/cpu/blaze/math/typetraits/HasMutableDataAccess.h
new file mode 100644
index 00000000..9f8e5274
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasMutableDataAccess.h
@@ -0,0 +1,117 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasMutableDataAccess.h
+// \brief Header file for the HasMutableDataAccess type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASMUTABLEDATAACCESS_H_
+#define _BLAZE_MATH_TYPETRAITS_HASMUTABLEDATAACCESS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for low-level access to mutable data.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type provides a low-level access to mutable data
+// via a non-const 'data' member function. In case the according member function is provided,
+// the \a value member constant is set to \a true, the nested type definition \a Type is
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType, and the class derives from \a FalseType. Examples:
+
+ \code
+ blaze::HasMutableDataAccess< StaticVector<float,3U> >::value // Evaluates to 1
+ blaze::HasMutableDataAccess< const DynamicVector<double> >::Type // Results in TrueType
+ blaze::HasMutableDataAccess< volatile DynamicMatrix<int> > // Is derived from TrueType
+ blaze::HasMutableDataAccess< int >::value // Evaluates to 0
+ blaze::HasMutableDataAccess< const CompressedVector<int> >::Type // Results in FalseType
+ blaze::HasMutableDataAccess< volatile CompressedMatrix<int> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct HasMutableDataAccess : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasMutableDataAccess type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct HasMutableDataAccess< const T > : public HasMutableDataAccess<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasMutableDataAccess type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct HasMutableDataAccess< volatile T > : public HasMutableDataAccess<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasMutableDataAccess type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct HasMutableDataAccess< const volatile T > : public HasMutableDataAccess<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDAbs.h b/src/cpu/blaze/math/typetraits/HasSIMDAbs.h
new file mode 100644
index 00000000..aaebac11
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDAbs.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDAbs.h
+// \brief Header file for the HasSIMDAbs type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDABS_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDABS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSigned.h>
+#include <blaze/util/typetraits/IsUnsigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDAbsHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T >
+struct HasSIMDAbsHelper< T, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, IsSigned<T> > > >
+{
+ enum : bool { value = ( bool( BLAZE_SSSE3_MODE ) && sizeof(T) <= 4UL ) ||
+ ( bool( BLAZE_AVX2_MODE ) && sizeof(T) <= 4UL ) ||
+ ( bool( BLAZE_MIC_MODE ) && sizeof(T) >= 4UL ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD absolute value operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD absolute value
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDAbs< char >::value // Evaluates to 1
+ blaze::HasSIMDAbs< short >::Type // Results in TrueType
+ blaze::HasSIMDAbs< int > // Is derived from TrueType
+ blaze::HasSIMDAbs< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDAbs< double >::Type // Results in FalseType
+ blaze::HasSIMDAbs< complex<int> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDAbs : public BoolConstant< HasSIMDAbsHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDAcos.h b/src/cpu/blaze/math/typetraits/HasSIMDAcos.h
new file mode 100644
index 00000000..cab2439c
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDAcos.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDAcos.h
+// \brief Header file for the HasSIMDAcos type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDACOS_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDACOS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDAcosHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDAcosHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD inverse cosine operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD inverse cosine
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDAcos< float >::value // Evaluates to 1
+ blaze::HasSIMDAcos< double >::Type // Results in TrueType
+ blaze::HasSIMDAcos< const double > // Is derived from TrueType
+ blaze::HasSIMDAcos< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDAcos< long double >::Type // Results in FalseType
+ blaze::HasSIMDAcos< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDAcos : public BoolConstant< HasSIMDAcosHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDAcosh.h b/src/cpu/blaze/math/typetraits/HasSIMDAcosh.h
new file mode 100644
index 00000000..9c1ea868
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDAcosh.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDAcosh.h
+// \brief Header file for the HasSIMDAcosh type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDACOSH_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDACOSH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDAcoshHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDAcoshHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD inverse hyperbolic cosine operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD inverse hyperbolic
+// cosine operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the
+// SIMD operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDAcosh< float >::value // Evaluates to 1
+ blaze::HasSIMDAcosh< double >::Type // Results in TrueType
+ blaze::HasSIMDAcosh< const double > // Is derived from TrueType
+ blaze::HasSIMDAcosh< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDAcosh< long double >::Type // Results in FalseType
+ blaze::HasSIMDAcosh< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDAcosh : public BoolConstant< HasSIMDAcoshHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDAdd.h b/src/cpu/blaze/math/typetraits/HasSIMDAdd.h
new file mode 100644
index 00000000..25b54085
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDAdd.h
@@ -0,0 +1,168 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDAdd.h
+// \brief Header file for the HasSIMDAdd type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDADD_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDADD_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct HasSIMDAddHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, typename T2 >
+struct HasSIMDAddHelper< T1, T2, EnableIf_< And< IsNumeric<T1>, IsIntegral<T1>
+ , IsNumeric<T2>, IsIntegral<T2>
+ , Bool< sizeof(T1) == sizeof(T2) > > > >
+{
+ enum : bool { value = ( bool( BLAZE_SSE2_MODE ) ) ||
+ ( bool( BLAZE_AVX2_MODE ) ) ||
+ ( bool( BLAZE_MIC_MODE ) && sizeof(T1) >= 4UL ) };
+};
+
+template< typename T >
+struct HasSIMDAddHelper< complex<T>, complex<T>, EnableIf_< And< IsNumeric<T>, IsIntegral<T> > > >
+{
+ enum : bool { value = ( bool( BLAZE_SSE2_MODE ) ) ||
+ ( bool( BLAZE_AVX2_MODE ) ) ||
+ ( bool( BLAZE_MIC_MODE ) && sizeof(T) >= 4UL ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDAddHelper< float, float >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+
+template<>
+struct HasSIMDAddHelper< complex<float>, complex<float> >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDAddHelper< double, double >
+{
+ enum : bool { value = bool( BLAZE_SSE2_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+
+template<>
+struct HasSIMDAddHelper< complex<double>, complex<double> >
+{
+ enum : bool { value = bool( BLAZE_SSE2_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD addition for the given data types.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...), and
+// the used compiler, this type trait provides the information whether a SIMD addition operation
+// exists for the two given data types \a T1 and \a T2 (ignoring the cv-qualifiers). In case the
+// SIMD addition is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDAdd< int, int >::value // Evaluates to 1
+ blaze::HasSIMDAdd< float, float >::Type // Results in TrueType
+ blaze::HasSIMDAdd< double, double > // Is derived from TrueType
+ blaze::HasSIMDAdd< bool, bool >::value // Evaluates to 0
+ blaze::HasSIMDAdd< float, int >::Type // Results in FalseType
+ blaze::HasSIMDAdd< float, double > // Is derived from FalseType
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 > // Type of the right-hand side operand
+struct HasSIMDAdd : public BoolConstant< HasSIMDAddHelper< Decay_<T1>, Decay_<T2> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDAsin.h b/src/cpu/blaze/math/typetraits/HasSIMDAsin.h
new file mode 100644
index 00000000..661b2a09
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDAsin.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDAsin.h
+// \brief Header file for the HasSIMDAsin type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDASIN_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDASIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDAsinHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDAsinHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD inverse sine operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD inverse sine
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDAsin< float >::value // Evaluates to 1
+ blaze::HasSIMDAsin< double >::Type // Results in TrueType
+ blaze::HasSIMDAsin< const double > // Is derived from TrueType
+ blaze::HasSIMDAsin< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDAsin< long double >::Type // Results in FalseType
+ blaze::HasSIMDAsin< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDAsin : public BoolConstant< HasSIMDAsinHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDAsinh.h b/src/cpu/blaze/math/typetraits/HasSIMDAsinh.h
new file mode 100644
index 00000000..dae50df5
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDAsinh.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDAsinh.h
+// \brief Header file for the HasSIMDAsinh type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDASINH_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDASINH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDAsinhHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDAsinhHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD inverse hyperbolic sine operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD hyperbolic inverse
+// sine operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the
+// SIMD operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDAsinh< float >::value // Evaluates to 1
+ blaze::HasSIMDAsinh< double >::Type // Results in TrueType
+ blaze::HasSIMDAsinh< const double > // Is derived from TrueType
+ blaze::HasSIMDAsinh< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDAsinh< long double >::Type // Results in FalseType
+ blaze::HasSIMDAsinh< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDAsinh : public BoolConstant< HasSIMDAsinhHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDAtan.h b/src/cpu/blaze/math/typetraits/HasSIMDAtan.h
new file mode 100644
index 00000000..e55d2375
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDAtan.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDAtan.h
+// \brief Header file for the HasSIMDAtan type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDATAN_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDATAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDAtanHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDAtanHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD inverse tangent operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD inverse tangent
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDAtan< float >::value // Evaluates to 1
+ blaze::HasSIMDAtan< double >::Type // Results in TrueType
+ blaze::HasSIMDAtan< const double > // Is derived from TrueType
+ blaze::HasSIMDAtan< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDAtan< long double >::Type // Results in FalseType
+ blaze::HasSIMDAtan< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDAtan : public BoolConstant< HasSIMDAtanHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDAtanh.h b/src/cpu/blaze/math/typetraits/HasSIMDAtanh.h
new file mode 100644
index 00000000..a4cdbd8d
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDAtanh.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDAtanh.h
+// \brief Header file for the HasSIMDAtanh type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDATANH_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDATANH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDAtanhHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDAtanhHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD inverse hyperbolic tangent operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD inverse hyperbolic
+// tangent operation exists for the given data type \a T (ignoring the cv-qualifiers). In case
+// the SIMD operation is available, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+// The following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDAtanh< float >::value // Evaluates to 1
+ blaze::HasSIMDAtanh< double >::Type // Results in TrueType
+ blaze::HasSIMDAtanh< const double > // Is derived from TrueType
+ blaze::HasSIMDAtanh< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDAtanh< long double >::Type // Results in FalseType
+ blaze::HasSIMDAtanh< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDAtanh : public BoolConstant< HasSIMDAtanhHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDCbrt.h b/src/cpu/blaze/math/typetraits/HasSIMDCbrt.h
new file mode 100644
index 00000000..bcf0f244
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDCbrt.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDCbrt.h
+// \brief Header file for the HasSIMDCbrt type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDCBRT_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDCBRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDCbrtHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDCbrtHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD cubic root operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD cubic root operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDCbrt< float >::value // Evaluates to 1
+ blaze::HasSIMDCbrt< double >::Type // Results in TrueType
+ blaze::HasSIMDCbrt< const double > // Is derived from TrueType
+ blaze::HasSIMDCbrt< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDCbrt< long double >::Type // Results in FalseType
+ blaze::HasSIMDCbrt< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDCbrt : public BoolConstant< HasSIMDCbrtHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDCeil.h b/src/cpu/blaze/math/typetraits/HasSIMDCeil.h
new file mode 100644
index 00000000..19f717b5
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDCeil.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDCeil.h
+// \brief Header file for the HasSIMDCeil type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDCEIL_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDCEIL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDCeilHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T >
+struct HasSIMDCeilHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+#if BLAZE_SVML_MODE
+ enum : bool { value = bool( BLAZE_SSE4_MODE ) || bool( BLAZE_AVX_MODE ) || bool( BLAZE_MIC_MODE ) };
+#else
+ enum : bool { value = bool( BLAZE_SSE4_MODE ) || bool( BLAZE_AVX_MODE ) };
+#endif
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD ceil operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD ceil operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDCeil< float >::value // Evaluates to 1
+ blaze::HasSIMDCeil< double >::Type // Results in TrueType
+ blaze::HasSIMDCeil< const double > // Is derived from TrueType
+ blaze::HasSIMDCeil< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDCeil< long double >::Type // Results in FalseType
+ blaze::HasSIMDCeil< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDCeil : public BoolConstant< HasSIMDCeilHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDConj.h b/src/cpu/blaze/math/typetraits/HasSIMDConj.h
new file mode 100644
index 00000000..3cbce141
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDConj.h
@@ -0,0 +1,112 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDConj.h
+// \brief Header file for the HasSIMDConj type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDCONJ_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDCONJ_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDConjHelper
+{
+ enum : bool { value = IsNumeric<T>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T >
+struct HasSIMDConjHelper< complex<T> >
+{
+ enum : bool { value = IsNumeric<T>::value && IsSigned<T>::value && HasSIMDMult<T,T>::value &&
+ ( IsFloatingPoint<T>::value || sizeof(T) <= 4UL ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD conjugate operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD conjugate operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDConj< int >::value // Evaluates to 1
+ blaze::HasSIMDConj< double >::Type // Results in TrueType
+ blaze::HasSIMDConj< complex<float> > // Is derived from TrueType
+ blaze::HasSIMDConj< complex<bool> >::value // Evaluates to 0
+ blaze::HasSIMDConj< complex<int> >::Type // Results in FalseType
+ blaze::HasSIMDConj< complex<unsigned int> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDConj : public BoolConstant< HasSIMDConjHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDCos.h b/src/cpu/blaze/math/typetraits/HasSIMDCos.h
new file mode 100644
index 00000000..850a624a
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDCos.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDCos.h
+// \brief Header file for the HasSIMDCos type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDCOS_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDCOS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDCosHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDCosHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD cosine operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD cosine operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDCos< float >::value // Evaluates to 1
+ blaze::HasSIMDCos< double >::Type // Results in TrueType
+ blaze::HasSIMDCos< const double > // Is derived from TrueType
+ blaze::HasSIMDCos< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDCos< long double >::Type // Results in FalseType
+ blaze::HasSIMDCos< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDCos : public BoolConstant< HasSIMDCosHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDCosh.h b/src/cpu/blaze/math/typetraits/HasSIMDCosh.h
new file mode 100644
index 00000000..9ac37418
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDCosh.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDCosh.h
+// \brief Header file for the HasSIMDCosh type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDCOSH_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDCOSH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDCoshHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDCoshHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD hyperbolic cosine operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD hyperbolic cosine
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDCosh< float >::value // Evaluates to 1
+ blaze::HasSIMDCosh< double >::Type // Results in TrueType
+ blaze::HasSIMDCosh< const double > // Is derived from TrueType
+ blaze::HasSIMDCosh< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDCosh< long double >::Type // Results in FalseType
+ blaze::HasSIMDCosh< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDCosh : public BoolConstant< HasSIMDCoshHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDDiv.h b/src/cpu/blaze/math/typetraits/HasSIMDDiv.h
new file mode 100644
index 00000000..525d2f32
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDDiv.h
@@ -0,0 +1,150 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDDiv.h
+// \brief Header file for the HasSIMDDiv type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDDIV_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDDIV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsSigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct HasSIMDDivHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, typename T2 >
+struct HasSIMDDivHelper< T1, T2, EnableIf_< And< IsNumeric<T1>, IsIntegral<T1>, IsSigned<T1>
+ , IsNumeric<T2>, IsIntegral<T2>, IsSigned<T2>
+ , Bool< sizeof(T1) == sizeof(T2) > > > >
+{
+ enum : bool { value = bool( BLAZE_MIC_MODE ) && sizeof(T1) >= 4UL };
+};
+
+template< typename T >
+struct HasSIMDDivHelper< complex<T>, T, EnableIf_< And< IsNumeric<T>, IsIntegral<T>, IsSigned<T> > > >
+{
+ enum : bool { value = bool( BLAZE_MIC_MODE ) && sizeof(T) >= 4UL };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDDivHelper< float, float >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDDivHelper< double, double >
+{
+ enum : bool { value = bool( BLAZE_SSE2_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD division for the given data types.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD division operation
+// exists for the two given data types \a T1 and \a T2 (ignoring the cv-qualifiers). In case the
+// SIMD division is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDDiv< float, float >::value // Evaluates to 1
+ blaze::HasSIMDDiv< double, double >::Type // Results in TrueType
+ blaze::HasSIMDDiv< complex<float>, float > // Is derived from TrueType
+ blaze::HasSIMDDiv< int, int >::value // Evaluates to 0
+ blaze::HasSIMDDiv< float, int >::Type // Results in FalseType
+ blaze::HasSIMDDiv< double, float > // Is derived from FalseType
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct HasSIMDDiv : public BoolConstant< HasSIMDDivHelper< Decay_<T1>, Decay_<T2> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDErf.h b/src/cpu/blaze/math/typetraits/HasSIMDErf.h
new file mode 100644
index 00000000..e923ace7
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDErf.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDErf.h
+// \brief Header file for the HasSIMDErf type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDERF_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDERF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDErfHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDErfHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD error function (\c erf) operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD error function
+// (\c erf) operation exists for the given data type \a T (ignoring the cv-qualifiers). In case
+// the SIMD operation is available, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+// The following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDErf< float >::value // Evaluates to 1
+ blaze::HasSIMDErf< double >::Type // Results in TrueType
+ blaze::HasSIMDErf< const double > // Is derived from TrueType
+ blaze::HasSIMDErf< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDErf< long double >::Type // Results in FalseType
+ blaze::HasSIMDErf< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDErf : public BoolConstant< HasSIMDErfHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDErfc.h b/src/cpu/blaze/math/typetraits/HasSIMDErfc.h
new file mode 100644
index 00000000..b10bd23d
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDErfc.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDErfc.h
+// \brief Header file for the HasSIMDErfc type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDERFC_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDERFC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDErfcHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDErfcHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD complementary error function (\c erfc) operation for the given
+// data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD complementary error
+// function (\c erfc) operation exists for the given data type \a T (ignoring the cv-qualifiers).
+// In case the SIMD operation is available, the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+// The following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDErfc< float >::value // Evaluates to 1
+ blaze::HasSIMDErfc< double >::Type // Results in TrueType
+ blaze::HasSIMDErfc< const double > // Is derived from TrueType
+ blaze::HasSIMDErfc< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDErfc< long double >::Type // Results in FalseType
+ blaze::HasSIMDErfc< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDErfc : public BoolConstant< HasSIMDErfcHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDExp.h b/src/cpu/blaze/math/typetraits/HasSIMDExp.h
new file mode 100644
index 00000000..a44488b0
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDExp.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDExp.h
+// \brief Header file for the HasSIMDExp type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDEXP_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDEXP_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDExpHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDExpHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD exponent operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD exponent operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDExp< float >::value // Evaluates to 1
+ blaze::HasSIMDExp< double >::Type // Results in TrueType
+ blaze::HasSIMDExp< const double > // Is derived from TrueType
+ blaze::HasSIMDExp< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDExp< long double >::Type // Results in FalseType
+ blaze::HasSIMDExp< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDExp : public BoolConstant< HasSIMDExpHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDFloor.h b/src/cpu/blaze/math/typetraits/HasSIMDFloor.h
new file mode 100644
index 00000000..f5739236
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDFloor.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDFloor.h
+// \brief Header file for the HasSIMDFloor type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDFLOOR_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDFLOOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDFloorHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T >
+struct HasSIMDFloorHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+#if BLAZE_SVML_MODE
+ enum : bool { value = bool( BLAZE_SSE4_MODE ) || bool( BLAZE_AVX_MODE ) || bool( BLAZE_MIC_MODE ) };
+#else
+ enum : bool { value = bool( BLAZE_SSE4_MODE ) || bool( BLAZE_AVX_MODE ) };
+#endif
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD floor operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD floor operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDFloor< float >::value // Evaluates to 1
+ blaze::HasSIMDFloor< double >::Type // Results in TrueType
+ blaze::HasSIMDFloor< const double > // Is derived from TrueType
+ blaze::HasSIMDFloor< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDFloor< long double >::Type // Results in FalseType
+ blaze::HasSIMDFloor< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDFloor : public BoolConstant< HasSIMDFloorHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDInvCbrt.h b/src/cpu/blaze/math/typetraits/HasSIMDInvCbrt.h
new file mode 100644
index 00000000..1fb9c6f6
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDInvCbrt.h
@@ -0,0 +1,113 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDInvCbrt.h
+// \brief Header file for the HasSIMDInvCbrt type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDINVCBRT_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDINVCBRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDInvCbrtHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDInvCbrtHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) || bool( BLAZE_AVX_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD inverse cubic root operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD inverse cubic root
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDInvCbrt< float >::value // Evaluates to 1
+ blaze::HasSIMDInvCbrt< double >::Type // Results in TrueType
+ blaze::HasSIMDInvCbrt< const double > // Is derived from TrueType
+ blaze::HasSIMDInvCbrt< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDInvCbrt< long double >::Type // Results in FalseType
+ blaze::HasSIMDInvCbrt< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDInvCbrt : public BoolConstant< HasSIMDInvCbrtHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDInvSqrt.h b/src/cpu/blaze/math/typetraits/HasSIMDInvSqrt.h
new file mode 100644
index 00000000..fb7ee537
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDInvSqrt.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDInvSqrt.h
+// \brief Header file for the HasSIMDInvSqrt type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDINVSQRT_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDINVSQRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDInvSqrtHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDInvSqrtHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD inverse square root operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD inverse square root
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDInvSqrt< float >::value // Evaluates to 1
+ blaze::HasSIMDInvSqrt< double >::Type // Results in TrueType
+ blaze::HasSIMDInvSqrt< const double > // Is derived from TrueType
+ blaze::HasSIMDInvSqrt< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDInvSqrt< long double >::Type // Results in FalseType
+ blaze::HasSIMDInvSqrt< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDInvSqrt : public BoolConstant< HasSIMDInvSqrtHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDLog.h b/src/cpu/blaze/math/typetraits/HasSIMDLog.h
new file mode 100644
index 00000000..370b9488
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDLog.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDLog.h
+// \brief Header file for the HasSIMDLog type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDLOG_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDLOG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDLogHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDLogHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD natural logarithm operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD natural logarithm
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDLog< float >::value // Evaluates to 1
+ blaze::HasSIMDLog< double >::Type // Results in TrueType
+ blaze::HasSIMDLog< const double > // Is derived from TrueType
+ blaze::HasSIMDLog< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDLog< long double >::Type // Results in FalseType
+ blaze::HasSIMDLog< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDLog : public BoolConstant< HasSIMDLogHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDLog10.h b/src/cpu/blaze/math/typetraits/HasSIMDLog10.h
new file mode 100644
index 00000000..84bff1b0
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDLog10.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDLog10.h
+// \brief Header file for the HasSIMDLog10 type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDLOG10_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDLOG10_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDLog10Helper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDLog10Helper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD common logarithm operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD common logarithm
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDLog10< float >::value // Evaluates to 1
+ blaze::HasSIMDLog10< double >::Type // Results in TrueType
+ blaze::HasSIMDLog10< const double > // Is derived from TrueType
+ blaze::HasSIMDLog10< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDLog10< long double >::Type // Results in FalseType
+ blaze::HasSIMDLog10< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDLog10 : public BoolConstant< HasSIMDLog10Helper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDMult.h b/src/cpu/blaze/math/typetraits/HasSIMDMult.h
new file mode 100644
index 00000000..5164d008
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDMult.h
@@ -0,0 +1,168 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDMult.h
+// \brief Header file for the HasSIMDMult type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDMULT_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDMULT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct HasSIMDMultHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, typename T2 >
+struct HasSIMDMultHelper< T1, T2, EnableIf_< And< IsNumeric<T1>, IsIntegral<T1>
+ , IsNumeric<T2>, IsIntegral<T2>
+ , Bool< sizeof(T1) == sizeof(T2) > > > >
+{
+ enum : bool { value = ( bool( BLAZE_SSE2_MODE ) && sizeof(T1) == 2UL ) ||
+ ( bool( BLAZE_SSE4_MODE ) && sizeof(T1) >= 2UL && sizeof(T1) <= 4UL ) ||
+ ( bool( BLAZE_AVX2_MODE ) && sizeof(T1) >= 2UL && sizeof(T1) <= 4UL ) ||
+ ( bool( BLAZE_MIC_MODE ) && sizeof(T1) == 4UL ) };
+};
+
+template< typename T >
+struct HasSIMDMultHelper< complex<T>, complex<T>, EnableIf_< And< IsNumeric<T>, IsIntegral<T> > > >
+{
+ enum : bool { value = ( bool( BLAZE_SSE2_MODE ) && sizeof(T) == 2UL ) ||
+ ( bool( BLAZE_SSE4_MODE ) && sizeof(T) >= 2UL && sizeof(T) <= 4UL ) ||
+ ( bool( BLAZE_AVX2_MODE ) && sizeof(T) >= 2UL && sizeof(T) <= 4UL ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDMultHelper< float, float >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+
+template<>
+struct HasSIMDMultHelper< complex<float>, complex<float> >
+{
+ enum : bool { value = ( bool( BLAZE_SSE3_MODE ) && !bool( BLAZE_MIC_MODE ) ) ||
+ ( bool( BLAZE_AVX_MODE ) && !bool( BLAZE_MIC_MODE ) ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDMultHelper< double, double >
+{
+ enum : bool { value = bool( BLAZE_SSE2_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+
+template<>
+struct HasSIMDMultHelper< complex<double>, complex<double> >
+{
+ enum : bool { value = ( bool( BLAZE_SSE3_MODE ) && !bool( BLAZE_MIC_MODE ) ) ||
+ ( bool( BLAZE_AVX_MODE ) && !bool( BLAZE_MIC_MODE ) ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD multiplication for the given data types.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD multiplication
+// operation exists for the two given data types \a T1 and \a T2 (ignoring the cv-qualifiers).
+// In case the SIMD multiplication is available, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType. The following example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDMult< int, int >::value // Evaluates to 1
+ blaze::HasSIMDMult< double, double >::Type // Results in TrueType
+ blaze::HasSIMDMult< complex<float>, float > // Is derived from TrueType
+ blaze::HasSIMDMult< bool, bool >::value // Evaluates to 0
+ blaze::HasSIMDMult< float, int >::Type // Results in FalseType
+ blaze::HasSIMDMult< double, float > // Is derived from FalseType
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct HasSIMDMult : public BoolConstant< HasSIMDMultHelper< Decay_<T1>, Decay_<T2> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDPow.h b/src/cpu/blaze/math/typetraits/HasSIMDPow.h
new file mode 100644
index 00000000..ead13906
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDPow.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDPow.h
+// \brief Header file for the HasSIMDPow type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDPOW_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDPOW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDPowHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDPowHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD power operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD power operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDPow< float >::value // Evaluates to 1
+ blaze::HasSIMDPow< double >::Type // Results in TrueType
+ blaze::HasSIMDPow< const double > // Is derived from TrueType
+ blaze::HasSIMDPow< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDPow< long double >::Type // Results in FalseType
+ blaze::HasSIMDPow< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDPow : public BoolConstant< HasSIMDPowHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDSin.h b/src/cpu/blaze/math/typetraits/HasSIMDSin.h
new file mode 100644
index 00000000..0e505cc2
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDSin.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDSin.h
+// \brief Header file for the HasSIMDSin type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDSIN_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDSIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDSinHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDSinHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD sine operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD sine operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDSin< float >::value // Evaluates to 1
+ blaze::HasSIMDSin< double >::Type // Results in TrueType
+ blaze::HasSIMDSin< const double > // Is derived from TrueType
+ blaze::HasSIMDSin< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDSin< long double >::Type // Results in FalseType
+ blaze::HasSIMDSin< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDSin : public BoolConstant< HasSIMDSinHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDSinh.h b/src/cpu/blaze/math/typetraits/HasSIMDSinh.h
new file mode 100644
index 00000000..f34bdd9d
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDSinh.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDSinh.h
+// \brief Header file for the HasSIMDSinh type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDSINH_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDSINH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDSinhHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDSinhHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD hyperbolic sine operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD hyperbolic sine
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDSinh< float >::value // Evaluates to 1
+ blaze::HasSIMDSinh< double >::Type // Results in TrueType
+ blaze::HasSIMDSinh< const double > // Is derived from TrueType
+ blaze::HasSIMDSinh< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDSinh< long double >::Type // Results in FalseType
+ blaze::HasSIMDSinh< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDSinh : public BoolConstant< HasSIMDSinhHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDSqrt.h b/src/cpu/blaze/math/typetraits/HasSIMDSqrt.h
new file mode 100644
index 00000000..f8177897
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDSqrt.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDSqrt.h
+// \brief Header file for the HasSIMDSqrt type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDSQRT_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDSQRT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/Decay.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDSqrtHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDSqrtHelper< float >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDSqrtHelper< double >
+{
+ enum : bool { value = bool( BLAZE_SSE2_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD square root operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD square root
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDSqrt< float >::value // Evaluates to 1
+ blaze::HasSIMDSqrt< double >::Type // Results in TrueType
+ blaze::HasSIMDSqrt< const double > // Is derived from TrueType
+ blaze::HasSIMDSqrt< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDSqrt< long double >::Type // Results in FalseType
+ blaze::HasSIMDSqrt< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDSqrt : public BoolConstant< HasSIMDSqrtHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDSub.h b/src/cpu/blaze/math/typetraits/HasSIMDSub.h
new file mode 100644
index 00000000..bc9bb53a
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDSub.h
@@ -0,0 +1,169 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDSub.h
+// \brief Header file for the HasSIMDSub type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDSUB_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDSUB_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct HasSIMDSubHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T1, typename T2 >
+struct HasSIMDSubHelper< T1, T2, EnableIf_< And< IsNumeric<T1>, IsIntegral<T1>
+ , IsNumeric<T2>, IsIntegral<T2>
+ , Bool< sizeof(T1) == sizeof(T2) > > > >
+{
+ enum : bool { value = ( bool( BLAZE_SSE2_MODE ) ) ||
+ ( bool( BLAZE_AVX2_MODE ) ) ||
+ ( bool( BLAZE_MIC_MODE ) && sizeof(T1) >= 4UL ) };
+};
+
+template< typename T >
+struct HasSIMDSubHelper< complex<T>, complex<T>, EnableIf_< And< IsNumeric<T>, IsIntegral<T> > > >
+{
+ enum : bool { value = ( bool( BLAZE_SSE2_MODE ) ) ||
+ ( bool( BLAZE_AVX2_MODE ) ) ||
+ ( bool( BLAZE_MIC_MODE ) && sizeof(T) >= 4UL ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDSubHelper< float, float >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+
+template<>
+struct HasSIMDSubHelper< complex<float>, complex<float> >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template<>
+struct HasSIMDSubHelper< double, double >
+{
+ enum : bool { value = bool( BLAZE_SSE2_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+
+template<>
+struct HasSIMDSubHelper< complex<double>, complex<double> >
+{
+ enum : bool { value = bool( BLAZE_SSE2_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD subtraction for the given data types.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD subtraction operation
+// exists for the two given data types \a T1 and \a T2 (ignoring the cv-qualifiers). In case the
+// SIMD subtraction is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that AVX is available:
+
+ \code
+ blaze::HasSIMDSub< int, int >::value // Evaluates to 1
+ blaze::HasSIMDSub< float, float >::Type // Results in TrueType
+ blaze::HasSIMDSub< double, double > // Is derived from TrueType
+ blaze::HasSIMDSub< bool, bool >::value // Evaluates to 0
+ blaze::HasSIMDSub< float, int >::Type // Results in FalseType
+ blaze::HasSIMDSub< double, float > // Is derived from FalseType
+ \endcode
+*/
+template< typename T1 // Type of the left-hand side operand
+ , typename T2 // Type of the right-hand side operand
+ , typename = void > // Restricting condition
+struct HasSIMDSub : public BoolConstant< HasSIMDSubHelper< Decay_<T1>, Decay_<T2> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDTan.h b/src/cpu/blaze/math/typetraits/HasSIMDTan.h
new file mode 100644
index 00000000..b1ffd4f7
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDTan.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDTan.h
+// \brief Header file for the HasSIMDTan type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDTAN_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDTAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDTanHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDTanHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD tangent operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD tangent operation
+// exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD operation
+// is available, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The following
+// example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDTan< float >::value // Evaluates to 1
+ blaze::HasSIMDTan< double >::Type // Results in TrueType
+ blaze::HasSIMDTan< const double > // Is derived from TrueType
+ blaze::HasSIMDTan< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDTan< long double >::Type // Results in FalseType
+ blaze::HasSIMDTan< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDTan : public BoolConstant< HasSIMDTanHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/HasSIMDTanh.h b/src/cpu/blaze/math/typetraits/HasSIMDTanh.h
new file mode 100644
index 00000000..519129c1
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/HasSIMDTanh.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/HasSIMDTanh.h
+// \brief Header file for the HasSIMDTanh type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDTANH_H_
+#define _BLAZE_MATH_TYPETRAITS_HASSIMDTANH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename T // Type of the operand
+ , typename = void > // Restricting condition
+struct HasSIMDTanhHelper
+{
+ enum : bool { value = false };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_SVML_MODE
+template< typename T >
+struct HasSIMDTanhHelper< T, EnableIf_< Or< IsFloat<T>, IsDouble<T> > > >
+{
+ enum : bool { value = bool( BLAZE_SSE_MODE ) ||
+ bool( BLAZE_AVX_MODE ) ||
+ bool( BLAZE_MIC_MODE ) };
+};
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Availability of a SIMD hyperbolic tangent operation for the given data type.
+// \ingroup math_type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...) and
+// the used compiler, this type trait provides the information whether a SIMD hyperbolic tangent
+// operation exists for the given data type \a T (ignoring the cv-qualifiers). In case the SIMD
+// operation is available, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
+// following example assumes that the Intel SVML is available:
+
+ \code
+ blaze::HasSIMDTanh< float >::value // Evaluates to 1
+ blaze::HasSIMDTanh< double >::Type // Results in TrueType
+ blaze::HasSIMDTanh< const double > // Is derived from TrueType
+ blaze::HasSIMDTanh< unsigned int >::value // Evaluates to 0
+ blaze::HasSIMDTanh< long double >::Type // Results in FalseType
+ blaze::HasSIMDTanh< complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T > // Type of the operand
+struct HasSIMDTanh : public BoolConstant< HasSIMDTanhHelper< Decay_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsAdaptor.h b/src/cpu/blaze/math/typetraits/IsAdaptor.h
new file mode 100644
index 00000000..be8f8b9e
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsAdaptor.h
@@ -0,0 +1,130 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsAdaptor.h
+// \brief Header file for the IsAdaptor type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISADAPTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISADAPTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for adaptors.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given template parameter is an adaptor type (for instance
+// \a LowerMatrix, \a UpperMatrix, or \a SymmetricMatrix). In case the type is an adaptor type,
+// the \a value member constant is set to \a true, the nested type definition \a Type is
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType, and the class derives from \a FalseType. The following example
+// demonstrates this by means of the mentioned matrix adaptors:
+
+ \code
+ using blaze::rowMajor;
+
+ blaze::IsAdaptor
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::LowerMatrix<StaticMatrixType> LowerStaticType;
+ typedef blaze::UpperMatrix<DynamicMatrixType> UpperDynamicType;
+ typedef blaze::SymmetricMatrix<CompressedMatrixType> SymmetricCompressedType;
+
+ blaze::IsLower< LowerStaticType >::value // Evaluates to 1
+ blaze::IsLower< const UpperDynamicType >::Type // Results in TrueType
+ blaze::IsLower< volatile SymmetricCompressedType > // Is derived from TrueType
+ blaze::IsLower< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsLower< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsLower< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsAdaptor : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsAdaptor type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsAdaptor< const T > : public IsAdaptor<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsAdaptor type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsAdaptor< volatile T > : public IsAdaptor<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsAdaptor type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsAdaptor< const volatile T > : public IsAdaptor<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsAddExpr.h b/src/cpu/blaze/math/typetraits/IsAddExpr.h
new file mode 100644
index 00000000..8efba51b
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsAddExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsAddExpr.h
+// \brief Header file for the IsAddExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISADDEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/AddExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is an addition expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is an addition expression
+// template (i.e. an expression representing a vector addition or a matrix addition). In order
+// to qualify as a valid addition expression template, the given type has to derive (publicly
+// or privately) from the AddExpr base class. In case the given type is a valid addition
+// expression template, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsAddExpr
+ : public BoolConstant< And< IsBaseOf<AddExpr,T>, Not< IsBaseOf<T,AddExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsAligned.h b/src/cpu/blaze/math/typetraits/IsAligned.h
new file mode 100644
index 00000000..d794084d
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsAligned.h
@@ -0,0 +1,129 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsAligned.h
+// \brief Header file for the IsAligned type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISALIGNED_H_
+#define _BLAZE_MATH_TYPETRAITS_ISALIGNED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for the alignment of data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type guarantees to provide aligned data values
+// with respect to the requirements of the available instruction set. For instance, vectorizable
+// data types such as built-in and complex data types are required to be 16-bit aligned for SSE,
+// 32-bit aligned for AVX, and 64-bit aligned for MIC. In case the data type is properly aligned,
+// the \a value member constant is set to \a true, the nested type definition \a Type is
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType. Examples:
+
+ \code
+ using blaze::StaticVector;
+ using blaze::CustomVector;
+ using blaze::CompressedVector;
+ using blaze::DynamicMatrix;
+ using blaze::CustomMatrix;
+ using blaze::aligned;
+ using blaze::unaligned;
+ using blaze::padded;
+ using blaze::unpadded;
+
+ blaze::IsAligned< StaticVector<int,3UL> >::value // Evaluates to 1
+ blaze::IsAligned< const DynamicMatrix<double> >::Type // Results in TrueType
+ blaze::IsAligned< volatile CustomVector<float,aligned,unpadded> > // Is derived from TrueType
+ blaze::IsAligned< CompressedVector<int> >::value // Evaluates to 0
+ blaze::IsAligned< const CustomVector<double,unaligned,unpadded> >::Type // Results in FalseType
+ blaze::IsAligned< volatile CustomMatrix<float,unaligned,padded> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsAligned : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsAligned type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsAligned< const T > : public IsAligned<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsAligned type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsAligned< volatile T > : public IsAligned<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsAligned type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsAligned< const volatile T > : public IsAligned<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsBLASCompatible.h b/src/cpu/blaze/math/typetraits/IsBLASCompatible.h
new file mode 100644
index 00000000..a77e0faa
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsBLASCompatible.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsBLASCompatible.h
+// \brief Header file for the IsBLASCompatible type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISBLASCOMPATIBLE_H_
+#define _BLAZE_MATH_TYPETRAITS_ISBLASCOMPATIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a data type compatible
+// to the BLAS standard. The BLAS standard supports \c float, \c double, \c complex<float> and
+// \c complex<double> values. If the type is BLAS compatible, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsBLASCompatible< float >::value // Evaluates to 1
+ blaze::IsBLASCompatible< double >::Type // Results in TrueType
+ blaze::IsBLASCompatible< complex<float> > // Is derived from TrueType
+ blaze::IsBLASCompatible< int >::value // Evaluates to 0
+ blaze::IsBLASCompatible< unsigned long >::Type // Results in FalseType
+ blaze::IsBLASCompatible< long double > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsBLASCompatible
+ : public BoolConstant< Or< IsFloat<T>, IsDouble<T>, IsComplexFloat<T>, IsComplexDouble<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsColumn.h b/src/cpu/blaze/math/typetraits/IsColumn.h
new file mode 100644
index 00000000..040e29ec
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsColumn.h
@@ -0,0 +1,139 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsColumn.h
+// \brief Header file for the IsColumn type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISCOLUMN_H_
+#define _BLAZE_MATH_TYPETRAITS_ISCOLUMN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/views/Forward.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for columns.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a column (i.e. dense
+// or sparse column). In case the type is a column, the \a value member constant is set to
+// \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ typedef blaze::DynamicMatrix<double,columnMajor> DenseMatrixType1;
+ typedef blaze::Column<DenseMatrixType1> DenseColumnType1;
+
+ typedef blaze::StaticMatrix<float,3UL,4UL,rowMajor> DenseMatrixType2;
+ typedef blaze::Column<DenseMatrixType2> DenseColumnType2;
+
+ typedef blaze::CompressedMatrix<int,columnMajor> SparseMatrixType;
+ typedef blaze::Column<SparseMatrixType> SparseColumnType;
+
+ blaze::IsColumn< SparseColumnType >::value // Evaluates to 1
+ blaze::IsColumn< const DenseColumnType1 >::Type // Results in TrueType
+ blaze::IsColumn< volatile DenseColumnType2 > // Is derived from TrueType
+ blaze::IsColumn< DenseMatrixType1 >::value // Evaluates to 0
+ blaze::IsColumn< const SparseMatrixType >::Type // Results in FalseType
+ blaze::IsColumn< volatile long double > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsColumn : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsColumn type trait for 'Column'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsColumn< Column<MT,SO,DF,SF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsColumn type trait for 'const Column'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsColumn< const Column<MT,SO,DF,SF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsColumn type trait for 'volatile Column'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsColumn< volatile Column<MT,SO,DF,SF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsColumn type trait for 'const volatile Column'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsColumn< const volatile Column<MT,SO,DF,SF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsColumnMajorMatrix.h b/src/cpu/blaze/math/typetraits/IsColumnMajorMatrix.h
new file mode 100644
index 00000000..e2c90cc8
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsColumnMajorMatrix.h
@@ -0,0 +1,90 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsColumnMajorMatrix.h
+// \brief Header file for the IsColumnMajorMatrix type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISCOLUMNMAJORMATRIX_H_
+#define _BLAZE_MATH_TYPETRAITS_ISCOLUMNMAJORMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for column-major matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template argument is a column-major dense or
+// sparse matrix type (i.e., a matrix whose storage order is set to \a true). In case the type
+// is a column-major matrix type, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::columnMajor;
+ using blaze::rowMajor;
+
+ blaze::IsColumnMajorMatrix< StaticMatrix<float,3U,3U,columnMajor> >::value // Evaluates to 1
+ blaze::IsColumnMajorMatrix< const DynamicMatrix<double,columnMajor> >::Type // Results in TrueType
+ blaze::IsColumnMajorMatrix< volatile CompressedMatrix<int,columnMajor> > // Is derived from TrueType
+ blaze::IsColumnMajorMatrix< StaticMatrix<float,3U,3U,rowMajor> >::value // Evaluates to 0
+ blaze::IsColumnMajorMatrix< const DynamicMatrix<double,rowMajor> >::Type // Results in FalseType
+ blaze::IsColumnMajorMatrix< volatile CompressedMatrix<int,rowMajor> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsColumnMajorMatrix
+ : public BoolConstant< IsBaseOf<Matrix<RemoveCV_<T>,true>,T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsColumnVector.h b/src/cpu/blaze/math/typetraits/IsColumnVector.h
new file mode 100644
index 00000000..1b56f8d9
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsColumnVector.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsColumnVector.h
+// \brief Header file for the IsColumnVector type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISCOLUMNVECTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISCOLUMNVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Vector.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for column vector types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template argument is a column dense or sparse
+// vector type (i.e. a vector whose transposition flag is set to blaze::columnVector). In case
+// the type is a column vector type, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ blaze::IsColumnVector< StaticVector<float,3U,columnVector> >::value // Evaluates to 1
+ blaze::IsColumnVector< const DynamicVector<double,columnVector> >::Type // Results in TrueType
+ blaze::IsColumnVector< volatile CompressedVector<int,columnVector> > // Is derived from TrueType
+ blaze::IsColumnVector< StaticVector<float,3U,rowVector> >::value // Evaluates to 0
+ blaze::IsColumnVector< const DynamicVector<double,rowVector> >::Type // Results in FalseType
+ blaze::IsColumnVector< volatile CompressedVector<int,rowVector> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsColumnVector
+ : public BoolConstant< IsBaseOf<Vector<RemoveCV_<T>,false>,T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsComputation.h b/src/cpu/blaze/math/typetraits/IsComputation.h
new file mode 100644
index 00000000..c3cbcbb8
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsComputation.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsComputation.h
+// \brief Header file for the IsComputation type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISCOMPUTATION_H_
+#define _BLAZE_MATH_TYPETRAITS_ISCOMPUTATION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a computational expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a computational
+// expression template (i.e. a mathematical operation such as an addition, a subtraction,
+// a multiplication, a division, an absolute value calculation, ...). In order to qualify
+// as a valid computational expression template, the given type has to derive (publicly or
+// privately) from the Computation base class. In case the given type is a valid computational
+// expression template, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsComputation
+ : public BoolConstant< And< IsBaseOf<Computation,T>, Not< IsBaseOf<T,Computation> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsCrossExpr.h b/src/cpu/blaze/math/typetraits/IsCrossExpr.h
new file mode 100644
index 00000000..3ca798a1
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsCrossExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsCrossExpr.h
+// \brief Header file for the IsCrossExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISCROSSEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISCROSSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/CrossExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a cross product expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a cross product
+// expression template. In order to qualify as a valid cross product expression template,
+// the given type has to derive (publicly or privately) from the CrossExpr base class. In
+// case the given type is a valid cross product expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the
+// class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsCrossExpr
+ : public BoolConstant< And< IsBaseOf<CrossExpr,T>, Not< IsBaseOf<T,CrossExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsCustom.h b/src/cpu/blaze/math/typetraits/IsCustom.h
new file mode 100644
index 00000000..ccae5add
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsCustom.h
@@ -0,0 +1,126 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsCustom.h
+// \brief Header file for the IsCustom type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISCUSTOM_H_
+#define _BLAZE_MATH_TYPETRAITS_ISCUSTOM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for custom data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type is a custom data type, i.e. a custom vector
+// or a custom matrix. In case the data type a custom data type, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType. Examples:
+
+ \code
+ using blaze::CustomVector;
+ using blaze::aligned;
+ using blaze::unpadded;
+ using blaze::columnVector;
+ using blaze::rowMajor;
+
+ typedef CustomVector<int,aligned,unpadded,columnVector> CustomVectorType;
+ typedef CustomMatrix<double,aligned,unpadded,rowMajor> CustomMatrixType;
+
+ blaze::IsCustom< CustomVectorType >::value // Evaluates to 1
+ blaze::IsCustom< const CustomVectorType >::Type // Results in TrueType
+ blaze::IsCustom< volatile CustomMatrixType > // Is derived from TrueType
+ blaze::IsCustom< int >::value // Evaluates to 0
+ blaze::IsCustom< const DynamicVector<float,columnVector> >::Type // Results in FalseType
+ blaze::IsCustom< volatile DynamicMatrix<int,rowMajor> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsCustom : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsCustom type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsCustom< const T > : public IsCustom<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsCustom type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsCustom< volatile T > : public IsCustom<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsCustom type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsCustom< const volatile T > : public IsCustom<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsDenseMatrix.h b/src/cpu/blaze/math/typetraits/IsDenseMatrix.h
new file mode 100644
index 00000000..e69a615d
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsDenseMatrix.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsDenseMatrix.h
+// \brief Header file for the IsDenseMatrix type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISDENSEMATRIX_H_
+#define _BLAZE_MATH_TYPETRAITS_ISDENSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for dense matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a dense, N-dimensional
+// matrix type. In case the type is a dense matrix type, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a yes is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsDenseMatrix< DynamicMatrix<double,false> >::value // Evaluates to 1
+ blaze::IsDenseMatrix< const DynamicMatrix<float,true> >::Type // Results in TrueType
+ blaze::IsDenseMatrix< volatile DynamicMatrix<int,true> > // Is derived from TrueType
+ blaze::IsDenseMatrix< CompressedMatrix<double,false>::value // Evaluates to 0
+ blaze::IsDenseMatrix< CompressedVector<double,true> >::Type // Results in FalseType
+ blaze::IsDenseMatrix< DynamicVector<double,true> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsDenseMatrix
+ : public BoolConstant< Or< IsBaseOf<DenseMatrix<RemoveCV_<T>,false>,T>
+ , IsBaseOf<DenseMatrix<RemoveCV_<T>,true>,T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsDenseVector.h b/src/cpu/blaze/math/typetraits/IsDenseVector.h
new file mode 100644
index 00000000..7fac1a51
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsDenseVector.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsDenseVector.h
+// \brief Header file for the IsDenseVector type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISDENSEVECTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISDENSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for dense vector types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a dense, N-dimensional
+// vector type. In case the type is a dense vector type, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsDenseVector< DynamicVector<double,false> >::value // Evaluates to 1
+ blaze::IsDenseVector< const StaticVector<float,3U,true> >::Type // Results in TrueType
+ blaze::IsDenseVector< volatile StaticVector<int,6U,true> > // Is derived from TrueType
+ blaze::IsDenseVector< CompressedVector<double,false> >::value // Evaluates to 0
+ blaze::IsDenseVector< CompressedMatrix<double,true> >::Type // Results in FalseType
+ blaze::IsDenseVector< DynamicMatrix<double,true> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsDenseVector
+ : public BoolConstant< Or< IsBaseOf<DenseVector<RemoveCV_<T>,false>,T>
+ , IsBaseOf<DenseVector<RemoveCV_<T>,true>,T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsDiagonal.h b/src/cpu/blaze/math/typetraits/IsDiagonal.h
new file mode 100644
index 00000000..950710f6
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsDiagonal.h
@@ -0,0 +1,132 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsDiagonal.h
+// \brief Header file for the IsDiagonal type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISDIAGONAL_H_
+#define _BLAZE_MATH_TYPETRAITS_ISDIAGONAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for diagonal matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a diagonal matrix type
+// (i.e. a matrix type that is guaranteed to be diagonal at compile time). In case the type is
+// a diagonal matrix type, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::DiagonalMatrix<StaticMatrixType> DiagonalStaticType;
+ typedef blaze::DiagonalMatrix<DynamicMatrixType> DiagonalDynamicType;
+ typedef blaze::DiagonalMatrix<CompressedMatrixType> DiagonalCompressedType;
+
+ typedef blaze::LowerMatrix<StaticMatrixType> LowerStaticType;
+ typedef blaze::UpperMatrix<DynamicMatrixType> UpperDynamicType;
+
+ blaze::IsDiagonal< DiagonalStaticType >::value // Evaluates to 1
+ blaze::IsDiagonal< const DiagonalDynamicType >::Type // Results in TrueType
+ blaze::IsDiagonal< volatile DiagonalCompressedType > // Is derived from TrueType
+ blaze::IsDiagonal< LowerStaticMatrixType >::value // Evaluates to 0
+ blaze::IsDiagonal< const UpperDynamicMatrixType >::Type // Results in FalseType
+ blaze::IsDiagonal< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsDiagonal : public BoolConstant< And< IsLower<T>, IsUpper<T> >::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsDiagonal type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsDiagonal< const T > : public IsDiagonal<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsDiagonal type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsDiagonal< volatile T > : public IsDiagonal<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsDiagonal type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsDiagonal< const volatile T > : public IsDiagonal<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsDivExpr.h b/src/cpu/blaze/math/typetraits/IsDivExpr.h
new file mode 100644
index 00000000..5a240a32
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsDivExpr.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsDivExpr.h
+// \brief Header file for the IsDivExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISDIVEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/DivExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a division expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a division expression
+// template (i.e. an expression representing a vector/scalar division or a matrix/scalar
+// division). In order to qualify as a valid division expression template, the given type has
+// to derive (publicly or privately) from the DivExpr base class. In case the given type is a
+// valid division expression template, the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+*/
+template< typename T >
+struct IsDivExpr
+ : public BoolConstant< And< IsBaseOf<DivExpr,T>, Not< IsBaseOf<T,DivExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsEvalExpr.h b/src/cpu/blaze/math/typetraits/IsEvalExpr.h
new file mode 100644
index 00000000..e716febb
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsEvalExpr.h
@@ -0,0 +1,77 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsEvalExpr.h
+// \brief Header file for the IsEvalExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISEVALEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/EvalExpr.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is an evaluation expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is an evaluation expression
+// template. In order to qualify as a valid evaluation expression template, the given type has to
+// derive (publicly or privately) from the EvalExpr base class. In case the given type is a valid
+// evaluation expression template, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsEvalExpr
+ : public BoolConstant< And< IsBaseOf<EvalExpr,T>, Not< IsBaseOf<T,EvalExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsExpression.h b/src/cpu/blaze/math/typetraits/IsExpression.h
new file mode 100644
index 00000000..5cc2b913
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsExpression.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsExpression.h
+// \brief Header file for the IsExpression type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISEXPRESSION_H_
+#define _BLAZE_MATH_TYPETRAITS_ISEXPRESSION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Expression.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is an expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a Blaze expression
+// template. In order to qualify as a valid expression template, the given type has to
+// derive (publicly or privately) from the Expression base class. In case the given type
+// is a valid expression template, the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives
+// from \a FalseType.
+*/
+template< typename T >
+struct IsExpression
+ : public BoolConstant< And< IsBaseOf<Expression,T>, Not< IsBaseOf<T,Expression> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsForEachExpr.h b/src/cpu/blaze/math/typetraits/IsForEachExpr.h
new file mode 100644
index 00000000..b6e3206d
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsForEachExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsForEachExpr.h
+// \brief Header file for the IsForEachExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISFOREACHEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/ForEachExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a for-each expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a for-each expression
+// template. In order to qualify as a valid for-each expression template, the given type has
+// to derive (publicly or privately) from the ForEachExpr base class. In case the given type
+// is a valid for-each expression template, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives
+// from \a FalseType.
+*/
+template< typename T >
+struct IsForEachExpr
+ : public BoolConstant< And< IsBaseOf<ForEachExpr,T>, Not< IsBaseOf<T,ForEachExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsGeneral.h b/src/cpu/blaze/math/typetraits/IsGeneral.h
new file mode 100644
index 00000000..4359a8cc
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsGeneral.h
@@ -0,0 +1,133 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsGeneral.h
+// \brief Header file for the IsGeneral type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISGENERAL_H_
+#define _BLAZE_MATH_TYPETRAITS_ISGENERAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTriangular.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for general matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a general matrix type
+// (i.e. a matrix type that is neither symmetric, Hermitian, lower triangular or upper triangular
+// at compile time). In case the type is a general matrix type, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::SymmetricMatrix<StaticMatrixType> SymmetricStaticType;
+ typedef blaze::HermitianMatrix<DynamicMatrixType> HermitianDynamicType;
+ typedef blaze::LowerMatrix<CompressedMatrixType> LowerCompressedType;
+
+ blaze::IsGeneral< StaticMatrixType >::value // Evaluates to 1
+ blaze::IsGeneral< const DynamicMatrixType >::Type // Results in TrueType
+ blaze::IsGeneral< volatile CompressedMatrixType > // Is derived from TrueType
+ blaze::IsGeneral< SymmetricStaticType >::value // Evaluates to 0
+ blaze::IsGeneral< const HermitianDynamicType >::Type // Results in FalseType
+ blaze::IsGeneral< volatile LowerCompressedType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsGeneral
+ : public BoolConstant< And< Not< IsSymmetric<T> >, Not< IsHermitian<T> >, Not< IsTriangular<T> > >::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsGeneral type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsGeneral< const T > : public IsGeneral<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsGeneral type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsGeneral< volatile T > : public IsGeneral<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsGeneral type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsGeneral< const volatile T > : public IsGeneral<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsHermitian.h b/src/cpu/blaze/math/typetraits/IsHermitian.h
new file mode 100644
index 00000000..3b96dcbd
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsHermitian.h
@@ -0,0 +1,127 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsHermitian.h
+// \brief Header file for the IsHermitian type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISHERMITIAN_H_
+#define _BLAZE_MATH_TYPETRAITS_ISHERMITIAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for Hermitian matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is an Hermitian matrix type
+// (i.e. a matrix type that is guaranteed to be Hermitian at compile time). In case the type is
+// a Hermitian matrix type, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::HermitianMatrix<StaticMatrixType> HermitianStaticType;
+ typedef blaze::HermitianMatrix<DynamicMatrixType> HermitianDynamicType;
+ typedef blaze::HermitianMatrix<CompressedMatrixType> HermitianCompressedType;
+
+ blaze::IsHermitian< HermitianStaticType >::value // Evaluates to 1
+ blaze::IsHermitian< const HermitianDynamicType >::Type // Results in TrueType
+ blaze::IsHermitian< volatile HermitianCompressedType > // Is derived from TrueType
+ blaze::IsHermitian< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsHermitian< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsHermitian< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsHermitian : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsHermitian type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsHermitian< const T > : public IsHermitian<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsHermitian type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsHermitian< volatile T > : public IsHermitian<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsHermitian type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsHermitian< const volatile T > : public IsHermitian<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsIdentity.h b/src/cpu/blaze/math/typetraits/IsIdentity.h
new file mode 100644
index 00000000..0e1bae1e
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsIdentity.h
@@ -0,0 +1,132 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsIdentity.h
+// \brief Header file for the IsIdentity type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISIDENTITY_H_
+#define _BLAZE_MATH_TYPETRAITS_ISIDENTITY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for identity matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is an identity matrix type
+// (i.e. a matrix type that is guaranteed to be an identity matrix at compile time). In case the
+// type is an identity matrix type, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::IdentityMatrix<StaticMatrixType> IdentityStaticType;
+ typedef blaze::IdentityMatrix<DynamicMatrixType> IdentityDynamicType;
+ typedef blaze::IdentityMatrix<CompressedMatrixType> IdentityCompressedType;
+
+ typedef blaze::LowerMatrix<StaticMatrixType> LowerStaticType;
+ typedef blaze::UpperMatrix<DynamicMatrixType> UpperDynamicType;
+
+ blaze::IsIdentity< IdentityStaticType >::value // Evaluates to 1
+ blaze::IsIdentity< const IdentityDynamicType >::Type // Results in TrueType
+ blaze::IsIdentity< volatile IdentityCompressedType > // Is derived from TrueType
+ blaze::IsIdentity< LowerStaticMatrixType >::value // Evaluates to 0
+ blaze::IsIdentity< const UpperDynamicMatrixType >::Type // Results in FalseType
+ blaze::IsIdentity< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsIdentity : public BoolConstant< And< IsUniLower<T>, IsUniUpper<T> >::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsIdentity type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsIdentity< const T > : public IsIdentity<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsIdentity type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsIdentity< volatile T > : public IsIdentity<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsIdentity type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsIdentity< const volatile T > : public IsIdentity<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsInvertible.h b/src/cpu/blaze/math/typetraits/IsInvertible.h
new file mode 100644
index 00000000..12037f09
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsInvertible.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsInvertible.h
+// \brief Header file for the IsInvertible type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISINVERTIBLE_H_
+#define _BLAZE_MATH_TYPETRAITS_ISINVERTIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsBLASCompatible.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/UnderlyingElement.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsLongDouble.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is invertible. The type
+// is considered to be invertible if it is either BLAS compatible (i.e. \c float, \c double,
+// \c complex<float>, or \c complex<double>), <tt>long double</tt>, or any dense matrix type
+// with a BLAS compatible element type. If the given type is invertible, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the
+// class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsInvertible< float >::value // Evaluates to 1
+ blaze::IsInvertible< complex<double> >::Type // Results in TrueType
+ blaze::IsInvertible< blaze::DynamicMatrix<double> > // Is derived from TrueType
+ blaze::IsInvertible< int >::value // Evaluates to 0
+ blaze::IsInvertible< complex<int> >::Type // Results in FalseType
+ blaze::IsInvertible< blaze::DynamicVector<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsInvertible
+ : public BoolConstant< Or< IsBLASCompatible<T>
+ , IsLongDouble<T>
+ , And< IsDenseMatrix<T>
+ , IsBLASCompatible< UnderlyingElement_<T> > >
+ >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsLower.h b/src/cpu/blaze/math/typetraits/IsLower.h
new file mode 100644
index 00000000..5517cbcb
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsLower.h
@@ -0,0 +1,130 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsLower.h
+// \brief Header file for the IsLower type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISLOWER_H_
+#define _BLAZE_MATH_TYPETRAITS_ISLOWER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for lower triangular matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a lower triangular matrix
+// type (i.e. a matrix type that is guaranteed to be lower triangular at compile time). This also
+// includes lower unitriangular and strictly lower triangular matrices. In case the type is a
+// lower triangular matrix type, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::LowerMatrix<StaticMatrixType> LowerStaticType;
+ typedef blaze::LowerMatrix<DynamicMatrixType> LowerDynamicType;
+ typedef blaze::UniLowerMatrix<CompressedMatrixType> UniLowerCompressedType;
+
+ blaze::IsLower< LowerStaticType >::value // Evaluates to 1
+ blaze::IsLower< const LowerDynamicType >::Type // Results in TrueType
+ blaze::IsLower< volatile UniLowerCompressedType > // Is derived from TrueType
+ blaze::IsLower< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsLower< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsLower< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsLower : public BoolConstant< Or< IsUniLower<T>, IsStrictlyLower<T> >::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsLower type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsLower< const T > : public IsLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsLower type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsLower< volatile T > : public IsLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsLower type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsLower< const volatile T > : public IsLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatEvalExpr.h b/src/cpu/blaze/math/typetraits/IsMatEvalExpr.h
new file mode 100644
index 00000000..70e40fd7
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatEvalExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatEvalExpr.h
+// \brief Header file for the IsMatEvalExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATEVALEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatEvalExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix evaluation expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix evaluation
+// expression template. In order to qualify as a valid matrix evaluation expression template,
+// the given type has to derive (publicly or privately) from the MatEvalExpr base class. In
+// case the given type is a valid matrix evaluation expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType,
+// and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMatEvalExpr
+ : public BoolConstant< And< IsBaseOf<MatEvalExpr,T>, Not< IsBaseOf<T,MatEvalExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatForEachExpr.h b/src/cpu/blaze/math/typetraits/IsMatForEachExpr.h
new file mode 100644
index 00000000..3b6cacaf
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatForEachExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatForEachExpr.h
+// \brief Header file for the IsMatForEachExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATFOREACHEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatForEachExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix for-each expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix for-each
+// expression template. In order to qualify as a valid matrix for-each expression template,
+// the given type has to derive (publicly or privately) from the MatForEachExpr base class.
+// In case the given type is a valid matrix for-each expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType,
+// and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMatForEachExpr
+ : public BoolConstant< And< IsBaseOf<MatForEachExpr,T>, Not< IsBaseOf<T,MatForEachExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatInvExpr.h b/src/cpu/blaze/math/typetraits/IsMatInvExpr.h
new file mode 100644
index 00000000..30dd826f
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatInvExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatInvExpr.h
+// \brief Header file for the IsMatInvExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATINVEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATINVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatInvExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix inversion expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix inversion
+// expression template. In order to qualify as a valid matrix inversion expression template,
+// the given type has to derive (publicly or privately) from the MatInvExpr base class. In
+// case the given type is a valid matrix inversion expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the
+// class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMatInvExpr
+ : public BoolConstant< And< IsBaseOf<MatInvExpr,T>, Not< IsBaseOf<T,MatInvExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatMatAddExpr.h b/src/cpu/blaze/math/typetraits/IsMatMatAddExpr.h
new file mode 100644
index 00000000..1390df1a
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatMatAddExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatMatAddExpr.h
+// \brief Header file for the IsMatMatAddExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATMATADDEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATMATADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatMatAddExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix/matrix addition expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix/matrix addition
+// expression template. In order to qualify as a valid matrix addition expression template, the
+// given type has to derive (publicly or privately) from the MatMatAddExpr base class. In case
+// the given type is a valid matrix addition expression template, the \a value member constant
+// is set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMatMatAddExpr
+ : public BoolConstant< And< IsBaseOf<MatMatAddExpr,T>, Not< IsBaseOf<T,MatMatAddExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatMatMultExpr.h b/src/cpu/blaze/math/typetraits/IsMatMatMultExpr.h
new file mode 100644
index 00000000..a165669b
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatMatMultExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatMatMultExpr.h
+// \brief Header file for the IsMatMatMultExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATMATMULTEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatMatMultExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix/matrix multiplication expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix/matrix
+// multiplication expression template. In order to qualify as a valid matrix multiplication
+// expression template, the given type has to derive (publicly or privately) from the
+// MatMatMultExpr base class. In case the given type is a valid matrix multiplication
+// expression template, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+*/
+template< typename T >
+struct IsMatMatMultExpr
+ : public BoolConstant< And< IsBaseOf<MatMatMultExpr,T>, Not< IsBaseOf<T,MatMatMultExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatMatSubExpr.h b/src/cpu/blaze/math/typetraits/IsMatMatSubExpr.h
new file mode 100644
index 00000000..0329e1f6
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatMatSubExpr.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatMatSubExpr.h
+// \brief Header file for the IsMatMatSubExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATMATSUBEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATMATSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatMatSubExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix/matrix subtraction expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix/matrix
+// subtraction expression template. In order to qualify as a valid matrix subtraction
+// expression template, the given type has to derive (publicly or privately) from the
+// MatMatSubExpr base class. In case the given type is a valid matrix subtraction
+// expression template, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives
+// from \a FalseType.
+*/
+template< typename T >
+struct IsMatMatSubExpr
+ : public BoolConstant< And< IsBaseOf<MatMatSubExpr,T>, Not< IsBaseOf<T,MatMatSubExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatScalarDivExpr.h b/src/cpu/blaze/math/typetraits/IsMatScalarDivExpr.h
new file mode 100644
index 00000000..cc5d30be
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatScalarDivExpr.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatScalarDivExpr.h
+// \brief Header file for the IsMatScalarDivExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATSCALARDIVEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatScalarDivExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix/scalar division expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix/scalar division
+// expression template. In order to qualify as a valid matrix/scalar division expression template,
+// the given type has to derive (publicly or privately) from the MatScalarDivExpr base class. In
+// case the given type is a valid matrix/scalar division expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and
+// the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMatScalarDivExpr
+ : public BoolConstant< And< IsBaseOf<MatScalarDivExpr,T>, Not< IsBaseOf<T,MatScalarDivExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatScalarMultExpr.h b/src/cpu/blaze/math/typetraits/IsMatScalarMultExpr.h
new file mode 100644
index 00000000..ac65f22a
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatScalarMultExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatScalarMultExpr.h
+// \brief Header file for the IsMatScalarMultExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATSCALARMULTEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatScalarMultExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix/scalar multiplication expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix/scalar
+// multiplication expression template. In order to qualify as a valid matrix/scalar
+// multiplication expression template, the given type has to derive (publicly or privately)
+// from the MatScalarMultExpr base class. In case the given type is a valid matrix/scalar
+// multiplication expression template, the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives
+// from \a FalseType.
+*/
+template< typename T >
+struct IsMatScalarMultExpr
+ : public BoolConstant< And< IsBaseOf<MatScalarMultExpr,T>, Not< IsBaseOf<T,MatScalarMultExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatSerialExpr.h b/src/cpu/blaze/math/typetraits/IsMatSerialExpr.h
new file mode 100644
index 00000000..6e587f8d
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatSerialExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatSerialExpr.h
+// \brief Header file for the IsMatSerialExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATSERIALEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatSerialExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix serial evaluation expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix serial evaluation
+// expression template. In order to qualify as a valid matrix serial evaluation expression template,
+// the given type has to derive (publicly or privately) from the MatSerialExpr base class. In case
+// the given type is a valid matrix serial evaluation expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and
+// the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMatSerialExpr
+ : public BoolConstant< And< IsBaseOf<MatSerialExpr,T>, Not< IsBaseOf<T,MatSerialExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatTransExpr.h b/src/cpu/blaze/math/typetraits/IsMatTransExpr.h
new file mode 100644
index 00000000..92d822bf
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatTransExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatTransExpr.h
+// \brief Header file for the IsMatTransExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATTRANSEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatTransExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix transposition expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix transposition
+// expression template. In order to qualify as a valid matrix transposition expression template,
+// the given type has to derive (publicly or privately) from the MatTransExpr base class. In
+// case the given type is a valid matrix transposition expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and
+// the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMatTransExpr
+ : public BoolConstant< And< IsBaseOf<MatTransExpr,T>, Not< IsBaseOf<T,MatTransExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatVecMultExpr.h b/src/cpu/blaze/math/typetraits/IsMatVecMultExpr.h
new file mode 100644
index 00000000..8c2edf71
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatVecMultExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatVecMultExpr.h
+// \brief Header file for the IsMatVecMultExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATVECMULTEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MatVecMultExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a matrix/vector multiplication expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a matrix/vector
+// multiplication expression template. In order to qualify as a valid matrix/vector
+// multiplication expression template, the given type has to derive (publicly or privately)
+// from the MatVecMultExpr base class. In case the given type is a valid matrix/vector
+// multiplication expression template, the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives
+// from \a FalseType.
+*/
+template< typename T >
+struct IsMatVecMultExpr
+ : public BoolConstant< And< IsBaseOf<MatVecMultExpr,T>, Not< IsBaseOf<T,MatVecMultExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMatrix.h b/src/cpu/blaze/math/typetraits/IsMatrix.h
new file mode 100644
index 00000000..7b73eb2e
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMatrix.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMatrix.h
+// \brief Header file for the IsMatrix type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMATRIX_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a N-dimensional dense
+// or sparse matrix type. In case the type is a matrix type, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a yes is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsMatrix< StaticMatrix<float,3U,3U,false> >::value // Evaluates to 1
+ blaze::IsMatrix< const DynamicMatrix<double,true> >::Type // Results in TrueType
+ blaze::IsMatrix< volatile CompressedMatrix<int,true> > // Is derived from TrueType
+ blaze::IsMatrix< StaticVector<float,3U,false> >::value // Evaluates to 0
+ blaze::IsMatrix< const DynamicVector<double,true> >::Type // Results in FalseType
+ blaze::IsMatrix< volatile CompressedVector<int,true> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsMatrix
+ : public BoolConstant< Or< IsBaseOf<Matrix<RemoveCV_<T>,false>,T>
+ , IsBaseOf<Matrix<RemoveCV_<T>,true>,T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsMultExpr.h b/src/cpu/blaze/math/typetraits/IsMultExpr.h
new file mode 100644
index 00000000..35d87e12
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsMultExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsMultExpr.h
+// \brief Header file for the IsMultExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISMULTEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/MultExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a multiplication expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a multiplication
+// expression template (i.e. an expression representing an element-wise vector multiplication,
+// a matrix/vector multiplication, a vector/matrix multiplication, or a matrix multiplication).
+// In order to qualify as a valid multiplication expression template, the given type has to
+// derive (publicly or privately) from the MultExpr base class. In case the given type is a
+// valid multiplication expression template, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+*/
+template< typename T >
+struct IsMultExpr
+ : public BoolConstant< And< IsBaseOf<MultExpr,T>, Not< IsBaseOf<T,MultExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsNumericMatrix.h b/src/cpu/blaze/math/typetraits/IsNumericMatrix.h
new file mode 100644
index 00000000..fe351b3a
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsNumericMatrix.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsNumericMatrix.h
+// \brief Header file for the IsNumericMatrix type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISNUMERICMATRIX_H_
+#define _BLAZE_MATH_TYPETRAITS_ISNUMERICMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/UnderlyingElement.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for numeric matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a numeric matrix type,
+// i.e. a matrix with numeric element type. In case the type is a numeric matrix type, the
+// \a value member constant is set to \a true, the nested type definition \a Type is \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a yes is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ typedef DynamicMatrix<int> Type1;
+ typedef CompressedMatrix< complex<double> > Type2;
+ typedef LowerMatrix< DynamicMatrix<float> > Type3;
+
+ typedef double Type4;
+ typedef DynamicVector<int> Type5;
+ typedef DynamicMatrix< DynamicVector<int> > Type6;
+
+ blaze::IsNumericMatrix< Type1 >::value // Evaluates to 1
+ blaze::IsNumericMatrix< Type2 >::Type // Results in TrueType
+ blaze::IsNumericMatrix< Type3 > // Is derived from TrueType
+ blaze::IsNumericMatrix< Type4 >::value // Evaluates to 0
+ blaze::IsNumericMatrix< Type5 >::Type // Results in FalseType
+ blaze::IsNumericMatrix< Type6 > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsNumericMatrix
+ : public BoolConstant< And< IsMatrix<T>, IsNumeric< UnderlyingElement_<T> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsNumericVector.h b/src/cpu/blaze/math/typetraits/IsNumericVector.h
new file mode 100644
index 00000000..d4c2cda7
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsNumericVector.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsNumericVector.h
+// \brief Header file for the IsNumericVector type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISNUMERICVECTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISNUMERICVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/math/typetraits/UnderlyingElement.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for numeric vector types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a numeric vector type,
+// i.e. a vector with numeric element type. In case the type is a numeric vector type, the
+// \a value member constant is set to \a true, the nested type definition \a Type is \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a yes is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ typedef DynamicVector<int> Type1;
+ typedef StaticVector<float,3UL> Type2;
+ typedef HybridVector< complex<double> > Type3;
+
+ typedef double Type4;
+ typedef DynamicMatrix<int> Type5;
+ typedef DynamicVector< DynamicVector<int> > Type6;
+
+ blaze::IsNumericVector< Type1 >::value // Evaluates to 1
+ blaze::IsNumericVector< Type2 >::Type // Results in TrueType
+ blaze::IsNumericVector< Type3 > // Is derived from TrueType
+ blaze::IsNumericVector< Type4 >::value // Evaluates to 0
+ blaze::IsNumericVector< Type5 >::Type // Results in FalseType
+ blaze::IsNumericVector< Type6 > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsNumericVector
+ : public BoolConstant< And< IsVector<T>, IsNumeric< UnderlyingElement_<T> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsOpposedView.h b/src/cpu/blaze/math/typetraits/IsOpposedView.h
new file mode 100644
index 00000000..eb091755
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsOpposedView.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsOpposedView.h
+// \brief Header file for the IsOpposedView type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISOPPOSEDVIEW_H_
+#define _BLAZE_MATH_TYPETRAITS_ISOPPOSEDVIEW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for resizable data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type is an opposed view, i.e. a view that is
+// opposed to the natural storage order of its underlying type. In case the data type is an
+// opposed view, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. Examples:
+
+ \code
+ using blaze::Column;
+ using blaze::Row;
+
+ typedef blaze::DynamicMatrix<int,columnMajor> DenseColumnMajor;
+ typedef blaze::CompressedMatrix<int,rowMajor> SparseRowMajor;
+
+ blaze::IsOpposedView< Row<DenseColumnMajor> >::value // Evaluates to 1
+ blaze::IsOpposedView< Column<SparseRowMajor> >::Type // Results in TrueType
+ blaze::IsOpposedView< const volatile Row<DenseColumnMajor> > // Is derived from TrueType
+ blaze::IsOpposedView< Column<DenseColumnMajor> >::value // Evaluates to 0
+ blaze::IsOpposedView< Row<SparseRowMajor> >::Type // Results in FalseType
+ blaze::IsOpposedView< const volatile Row<SparseRowMajor> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsOpposedView : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsOpposedView type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsOpposedView< const T > : public IsOpposedView<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsOpposedView type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsOpposedView< volatile T > : public IsOpposedView<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsOpposedView type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsOpposedView< const volatile T > : public IsOpposedView<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsPadded.h b/src/cpu/blaze/math/typetraits/IsPadded.h
new file mode 100644
index 00000000..aa915462
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsPadded.h
@@ -0,0 +1,118 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsPadded.h
+// \brief Header file for the IsPadded type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISPADDED_H_
+#define _BLAZE_MATH_TYPETRAITS_ISPADDED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for data types with padding.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type employs or simulates padding such that no
+// special treatment of remainder elements is necessary for vectorized operations on the type.
+// In case the data type is padded, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+// Examples:
+
+ \code
+ blaze::IsPadded< blaze::StaticVector<int,3UL> >::value // Evaluates to 1
+ blaze::IsPadded< const blaze::HybridVector<float> >::Type // Results in TrueType
+ blaze::IsPadded< volatile blaze::DynamicMatrix<double> > // Is derived from TrueType
+ blaze::IsPadded< int >::value // Evaluates to 0
+ blaze::IsPadded< const CompressedVector<int> >::Type // Results in FalseType
+ blaze::IsPadded< volatile CompressedMatrix<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsPadded : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsPadded type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsPadded< const T > : public IsPadded<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsPadded type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsPadded< volatile T > : public IsPadded<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsPadded type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsPadded< const volatile T > : public IsPadded<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsProxy.h b/src/cpu/blaze/math/typetraits/IsProxy.h
new file mode 100644
index 00000000..16d84c64
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsProxy.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsProxy.h
+// \brief Header file for the IsProxy type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISPROXY_H_
+#define _BLAZE_MATH_TYPETRAITS_ISPROXY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+#include <blaze/math/proxy/Forward.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the IsProxy type trait.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsProxyHelper
+{
+ private:
+ //**********************************************************************************************
+ typedef char (&Yes)[1];
+ typedef char (&No) [2];
+
+ template< typename PT, typename RT >
+ static Yes test( const Proxy<PT,RT>& );
+
+ static No test( ... );
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ static constexpr bool value = ( sizeof( test( std::declval< RemoveCV_<T> >() ) ) == sizeof( Yes ) );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time check for proxy types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a proxy type (i.e.
+// derived from the blaze::Proxy class template). In case the type is a proxy, the \a value
+// member constant is set to \a true, the nested type definition \a Type is \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type
+// is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ class MyProxy1 : public Proxy<MyProxy1> {};
+ class MyProxy2 : public Proxy<MyProxy2,int> {};
+ class MyProxy3 : public Proxy<MyProxy3,double> {};
+ class MyProxy4 {};
+
+ blaze::IsProxy< MyProxy1 >::value // Evaluates to 1
+ blaze::IsProxy< const MyProxy2 >::Type // Results in TrueType
+ blaze::IsProxy< volatile MyProxy3 > // Is derived from TrueType
+ blaze::IsProxy< MyProxy4 >::value // Evaluates to 0
+ blaze::IsProxy< const MyProxy4 >::Type // Results in FalseType
+ blaze::IsProxy< volatile MyProxy4 > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsProxy : public BoolConstant< IsProxyHelper<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsResizable.h b/src/cpu/blaze/math/typetraits/IsResizable.h
new file mode 100644
index 00000000..52f6a0ff
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsResizable.h
@@ -0,0 +1,117 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsResizable.h
+// \brief Header file for the IsResizable type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISRESIZABLE_H_
+#define _BLAZE_MATH_TYPETRAITS_ISRESIZABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for resizable data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type is a resizable data type. In case the
+// data type can be resized (via the resize() function), the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType. Examples:
+
+ \code
+ blaze::IsResizable< DynamicVector<double,false> >::value // Evaluates to 1
+ blaze::IsResizable< const DynamicMatrix<double,false> >::Type // Results in TrueType
+ blaze::IsResizable< volatile CompressedMatrix<int,true> > // Is derived from TrueType
+ blaze::IsResizable< int >::value // Evaluates to 0
+ blaze::IsResizable< const complex<double> >::Type // Results in FalseType
+ blaze::IsResizable< volatile StaticVector<float,3U,false> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsResizable : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsResizable type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsResizable< const T > : public IsResizable<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsResizable type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsResizable< volatile T > : public IsResizable<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsResizable type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsResizable< const volatile T > : public IsResizable<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsRestricted.h b/src/cpu/blaze/math/typetraits/IsRestricted.h
new file mode 100644
index 00000000..b34940e5
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsRestricted.h
@@ -0,0 +1,124 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsRestricted.h
+// \brief Header file for the IsRestricted type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISRESTRICTED_H_
+#define _BLAZE_MATH_TYPETRAITS_ISRESTRICTED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for data types with restricted data access.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type has a restricted data access. Examples are
+// the LowerMatrix and UpperMatrix adaptors that don't allow write access to the elements in the
+// upper or lower part of the matrix, respectively. In case the data type has a restricted data
+// access, the \a value member constant is set to \a true, the nested type definition \a Type
+// is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType, and the class derives from \a FalseType. Examples:
+
+ \code
+ typedef blaze::StaticVector<int,3UL> VectorType;
+ typedef blaze::DynamicMatrix<double> MatrixType;
+
+ typedef blaze::LowerMatrix< blaze::DynamicMatrix<double> > Lower;
+ typedef blaze::LowerMatrix< blaze::CompressedMatrix<int> > Upper;
+
+ blaze::IsRestricted< Lower >::value // Evaluates to 1
+ blaze::IsRestricted< const Upper >::Type // Results in TrueType
+ blaze::IsRestricted< volatile Lower > // Is derived from TrueType
+ blaze::IsRestricted< int >::value // Evaluates to 0
+ blaze::IsRestricted< const VectorType >::Type // Results in FalseType
+ blaze::IsRestricted< volatile MatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsRestricted : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsRestricted type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsRestricted< const T > : public IsRestricted<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsRestricted type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsRestricted< volatile T > : public IsRestricted<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsRestricted type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsRestricted< const volatile T > : public IsRestricted<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsRow.h b/src/cpu/blaze/math/typetraits/IsRow.h
new file mode 100644
index 00000000..9b924942
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsRow.h
@@ -0,0 +1,139 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsRow.h
+// \brief Header file for the IsRow type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISROW_H_
+#define _BLAZE_MATH_TYPETRAITS_ISROW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/views/Forward.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for rows.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a row (i.e. dense or
+// sparse row). In case the type is a row, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ typedef blaze::DynamicMatrix<double,columnMajor> DenseMatrixType1;
+ typedef blaze::Row<DenseMatrixType1> DenseRowType1;
+
+ typedef blaze::StaticMatrix<float,3UL,4UL,rowMajor> DenseMatrixType2;
+ typedef blaze::Row<DenseMatrixType2> DenseRowType2;
+
+ typedef blaze::CompressedMatrix<int,columnMajor> SparseMatrixType;
+ typedef blaze::Row<SparseMatrixType> SparseRowType;
+
+ blaze::IsRow< SparseRowType >::value // Evaluates to 1
+ blaze::IsRow< const DenseRowType1 >::Type // Results in TrueType
+ blaze::IsRow< volatile DenseRowType2 > // Is derived from TrueType
+ blaze::IsRow< DenseMatrixType1 >::value // Evaluates to 0
+ blaze::IsRow< const SparseMatrixType >::Type // Results in FalseType
+ blaze::IsRow< volatile long double > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsRow : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsRow type trait for 'Row'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsRow< Row<MT,SO,DF,SF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsRow type trait for 'const Row'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsRow< const Row<MT,SO,DF,SF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsRow type trait for 'volatile Row'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsRow< volatile Row<MT,SO,DF,SF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsRow type trait for 'const volatile Row'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsRow< const volatile Row<MT,SO,DF,SF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsRowMajorMatrix.h b/src/cpu/blaze/math/typetraits/IsRowMajorMatrix.h
new file mode 100644
index 00000000..ee4381ce
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsRowMajorMatrix.h
@@ -0,0 +1,90 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsRowMajorMatrix.h
+// \brief Header file for the IsRowMajorMatrix type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISROWMAJORMATRIX_H_
+#define _BLAZE_MATH_TYPETRAITS_ISROWMAJORMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for row-major matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template argument is a row-major dense or
+// sparse matrix type (i.e., a matrix whose storage order is set to \a true). In case the type
+// is a row-major matrix type, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::DynamicMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ blaze::IsRowMajorMatrix< StaticMatrix<float,3U,3U,rowMajor> >::value // Evaluates to 1
+ blaze::IsRowMajorMatrix< const DynamicMatrix<double,rowMajor> >::Type // Results in TrueType
+ blaze::IsRowMajorMatrix< volatile CompressedMatrix<int,rowMajor> > // Is derived from TrueType
+ blaze::IsRowMajorMatrix< StaticMatrix<float,3U,3U,columnMajor> >::value // Evaluates to 0
+ blaze::IsRowMajorMatrix< const DynamicMatrix<double,columnMajor> >::Type // Results in FalseType
+ blaze::IsRowMajorMatrix< volatile CompressedMatrix<int,columnMajor> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsRowMajorMatrix
+ : public BoolConstant< IsBaseOf<Matrix<RemoveCV_<T>,false>,T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsRowVector.h b/src/cpu/blaze/math/typetraits/IsRowVector.h
new file mode 100644
index 00000000..e1e23139
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsRowVector.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsRowVector.h
+// \brief Header file for the IsRowVector type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISROWVECTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISROWVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Vector.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for row vector types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template argument is a row dense or sparse
+// vector type (i.e. a vector whose transposition flag is set to blaze::rowVector). In case
+// the type is a row vector type, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowVector;
+ using blaze::columnVector;
+
+ blaze::IsRowVector< StaticVector<float,3U,rowVector> >::value // Evaluates to 1
+ blaze::IsRowVector< const DynamicVector<double,rowVector> >::Type // Results in TrueType
+ blaze::IsRowVector< volatile CompressedVector<int,rowVector> > // Is derived from TrueType
+ blaze::IsRowVector< StaticVector<float,3U,columnVector> >::value // Evaluates to 0
+ blaze::IsRowVector< const DynamicVector<double,columnVector> >::Type // Results in FalseType
+ blaze::IsRowVector< volatile CompressedVector<int,columnVector> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsRowVector
+ : public BoolConstant< IsBaseOf<Vector<RemoveCV_<T>,true>,T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSIMDEnabled.h b/src/cpu/blaze/math/typetraits/IsSIMDEnabled.h
new file mode 100644
index 00000000..7d9abaa3
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSIMDEnabled.h
@@ -0,0 +1,106 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSIMDEnabled.h
+// \brief Header file for the IsSIMDEnabled type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSIMDENABLED_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSIMDENABLED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the IsSIMDEnabled type trait.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsSIMDEnabledHelper
+{
+ private:
+ //**struct HasNestedMember**********************************************************************
+ template< typename T2 >
+ struct UseNestedMember { static constexpr bool value = T2::simdEnabled; };
+ //**********************************************************************************************
+
+ //**struct NotSIMDEnabled***********************************************************************
+ template< typename T2 >
+ struct NotSIMDEnabled { static constexpr bool value = false; };
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ static constexpr bool value = If_< Or< IsVector<T>, IsMatrix<T> >
+ , UseNestedMember<T>
+ , NotSIMDEnabled<T>
+ >::value;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time check for data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given data type \a T is a SIMD-enabled data type
+// (i.e. provides the according SIMD-related member functions, such as \c load(), store(), etc).
+// If the type is SIMD-enabled, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsSIMDEnabled : public BoolConstant< IsSIMDEnabledHelper<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSIMDPack.h b/src/cpu/blaze/math/typetraits/IsSIMDPack.h
new file mode 100644
index 00000000..76532c79
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSIMDPack.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSIMDPack.h
+// \brief Header file for the IsSIMDPack type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSIMDPACK_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSIMDPACK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/simd/SIMDPack.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for SIMD data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether the given data type is a Blaze SIMD packed data type. The
+// following types are considered valid SIMD packed types:
+//
+// <ul>
+// <li>Basic SIMD packed data types:</li>
+// <ul>
+// <li>SIMDint8</li>
+// <li>SIMDint16</li>
+// <li>SIMDint32</li>
+// <li>SIMDint64</li>
+// <li>SIMDfloat</li>
+// <li>SIMDdouble</li>
+// <li>SIMDcint8</li>
+// <li>SIMDcint16</li>
+// <li>SIMDcint32</li>
+// <li>SIMDcint64</li>
+// <li>SIMDcfloat</li>
+// <li>SIMDcdouble</li>
+// </ul>
+// <li>Derived SIMD packed data types:</li>
+// <ul>
+// <li>SIMDshort</li>
+// <li>SIMDushort</li>
+// <li>SIMDint</li>
+// <li>SIMDuint</li>
+// <li>SIMDlong</li>
+// <li>SIMDulong</li>
+// <li>SIMDcshort</li>
+// <li>SIMDcushort</li>
+// <li>SIMDcint</li>
+// <li>SIMDcuint</li>
+// <li>SIMDclong</li>
+// <li>SIMDculong</li>
+// </ul>
+// </ul>
+//
+// In case the data type is a SIMD data type, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType. Examples:
+
+ \code
+ blaze::IsSIMDPack< SIMDint32 >::value // Evaluates to 1
+ blaze::IsSIMDPack< const SIMDdouble >::Type // Results in TrueType
+ blaze::IsSIMDPack< volatile SIMDint > // Is derived from TrueType
+ blaze::IsSIMDPack< int >::value // Evaluates to 0
+ blaze::IsSIMDPack< const double >::Type // Results in FalseType
+ blaze::IsSIMDPack< volatile complex<double> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSIMDPack
+ : public BoolConstant< Or< IsBaseOf<SIMDPack< RemoveCV_<T> >,T>
+ , IsBaseOf<SIMDPack< RemoveCV_<T> >,T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSMPAssignable.h b/src/cpu/blaze/math/typetraits/IsSMPAssignable.h
new file mode 100644
index 00000000..e0b954b4
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSMPAssignable.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSMPAssignable.h
+// \brief Header file for the IsSMPAssignable type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSMPASSIGNABLE_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSMPASSIGNABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the IsSMPAssignable type trait.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsSMPAssignableHelper
+{
+ private:
+ //**struct HasNestedMember**********************************************************************
+ template< typename T2 >
+ struct UseNestedMember { static constexpr bool value = T2::smpAssignable; };
+ //**********************************************************************************************
+
+ //**struct NoNestedMember***********************************************************************
+ template< typename T2 >
+ struct NotSMPAssignable { static constexpr bool value = false; };
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ static constexpr bool value = If_< Or< IsVector<T>, IsMatrix<T> >
+ , UseNestedMember<T>
+ , NotSMPAssignable<T>
+ >::value;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time check for data types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is an SMP-assignable data
+// type (i.e. if it is a data type that can possibly and efficiently be assigned by several
+// threads). In this context, built-in data types as well as complex numbers are non-SMP-assignable,
+// whereas several vector and matrix types (as for instance DynamicVector and DynamicMatrix) can be
+// SMP-assignable. If the type is SMP-assignable, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ using blaze::StaticVector;
+ using blaze::StaticMatrix;
+ using blaze::DynamicMatrix;
+
+ typedef blaze::DynamicVector<int,columnVector> VectorType;
+ typedef blaze::Subvector<VectorType> SubvectorType;
+
+ blaze::IsSMPAssignable< VectorType >::value // Evaluates to 1
+ blaze::IsSMPAssignable< SubvectorType >::Type // Results in TrueType
+ blaze::IsSMPAssignable< DynamicMatrix<int> > // Is derived from TrueType
+ blaze::IsSMPAssignable< int >::value // Evaluates to 0
+ blaze::IsSMPAssignable< StaticVector<int,3UL> >::Type // Results in FalseType
+ blaze::IsSMPAssignable< StaticMatrix<int,4UL,5UL> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSMPAssignable : public BoolConstant< IsSMPAssignableHelper<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSerialExpr.h b/src/cpu/blaze/math/typetraits/IsSerialExpr.h
new file mode 100644
index 00000000..0c0ddda3
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSerialExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSerialExpr.h
+// \brief Header file for the IsSerialExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSERIALEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SerialExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a serial evaluation expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a serial evaluation
+// expression template. In order to qualify as a valid serial evaluation expression template, the
+// given type has to derive (publicly or privately) from the SerialExpr base class. In case the
+// given type is a valid serial evaluation expression template, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+*/
+template< typename T >
+struct IsSerialExpr
+ : public BoolConstant< And< IsBaseOf<SerialExpr,T>, Not< IsBaseOf<T,SerialExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSparseElement.h b/src/cpu/blaze/math/typetraits/IsSparseElement.h
new file mode 100644
index 00000000..2e193e65
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSparseElement.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSparseElement.h
+// \brief Header file for the IsSparseElement type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSPARSEELEMENT_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSPARSEELEMENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a sparse element type.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a Blaze sparse element
+// type, i.e. if the type implements the sparse element concept by providing a value() and an
+// index() member function. In order to qualify as a valid sparse element type, the given type
+// has to derive (publicly or privately) from the SparseElement base class. In case the given
+// type is a valid sparse element, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsSparseElement
+ : public BoolConstant< And< IsBaseOf<SparseElement,T>, Not< IsBaseOf<T,SparseElement> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSparseMatrix.h b/src/cpu/blaze/math/typetraits/IsSparseMatrix.h
new file mode 100644
index 00000000..7ad8a519
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSparseMatrix.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSparseMatrix.h
+// \brief Header file for the IsSparseMatrix type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSPARSEMATRIX_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSPARSEMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for sparse matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a sparse, N-dimensional
+// matrix type. In case the type is a sparse matrix type, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsSparseMatrix< CompressedMatrix<double,false> >::value // Evaluates to 1
+ blaze::IsSparseMatrix< const CompressedMatrix<float,true> >::Type // Results in TrueType
+ blaze::IsSparseMatrix< volatile CompressedMatrix<int,true> > // Is derived from TrueType
+ blaze::IsSparseMatrix< DynamicVector<double,false> >::value // Evaluates to 0
+ blaze::IsSparseMatrix< const DynamicMatrix<double,true> >::Type // Results in FalseType
+ blaze::IsSparseMatrix< CompressedVector<double,true> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSparseMatrix
+ : public BoolConstant< Or< IsBaseOf<SparseMatrix<RemoveCV_<T>,false>,T>
+ , IsBaseOf<SparseMatrix<RemoveCV_<T>,true>,T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSparseVector.h b/src/cpu/blaze/math/typetraits/IsSparseVector.h
new file mode 100644
index 00000000..d8e6048f
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSparseVector.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSparseVector.h
+// \brief Header file for the IsSparseVector type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSPARSEVECTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSPARSEVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for sparse vector types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a sparse, N-dimensional
+// vector type. In case the type is a sparse vector type, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsSparseVector< CompressedVector<double,false> >::value // Evaluates to 1
+ blaze::IsSparseVector< const CompressedVector<float,true> >::Type // Results in TrueType
+ blaze::IsSparseVector< volatile CompressedVector<int,true> > // Is derived from TrueType
+ blaze::IsSparseVector< DynamicVector<double,false> >::value // Evaluates to 0
+ blaze::IsSparseVector< const DynamicMatrix<double,true> >::Type // Results in FalseType
+ blaze::IsSparseVector< CompressedMatrix<double,true> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSparseVector
+ : public BoolConstant< Or< IsBaseOf<SparseVector<RemoveCV_<T>,false>,T>
+ , IsBaseOf<SparseVector<RemoveCV_<T>,true>,T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSquare.h b/src/cpu/blaze/math/typetraits/IsSquare.h
new file mode 100644
index 00000000..3e9a7973
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSquare.h
@@ -0,0 +1,130 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSquare.h
+// \brief Header file for the IsSquare type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSQUARE_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSQUARE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for square matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a square matrix type
+// (i.e. a matrix type that is guaranteed to be square at compile time). In case the type is
+// a square matrix type, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ // Type definitions of square matrix types
+ typedef blaze::StaticMatrix<double,2UL,2UL,rowMajor> Mat2x2;
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> Mat3x3;
+ typedef blaze::StaticMatrix<double,4UL,4UL,rowMajor> Mat4x4;
+
+ // Type definitions of non-square matrix types
+ typedef blaze::StaticMatrix<double,2UL,3UL,rowMajor> Mat2x3;
+ typedef blaze::DynamicMatrix<double,rowMajor> DynamicMatrixType;
+ typedef blaze::HybridMatrix<double,3UL,3UL,rowMajor> HybridMatrixType;
+
+ blaze::IsSquare< Mat2x2 >::value // Evaluates to 1
+ blaze::IsSquare< const Mat3x3 >::Type // Results in TrueType
+ blaze::IsSquare< volatile Mat4x4 > // Is derived from TrueType
+ blaze::IsSquare< DynamicMatrixType >::value // Evaluates to 0
+ blaze::IsSquare< const Mat2x3 >::Type // Results in FalseType
+ blaze::IsSquare< volatile HybridMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSquare : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSquare type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsSquare< const T > : public IsSquare<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSquare type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsSquare< volatile T > : public IsSquare<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSquare type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsSquare< const volatile T > : public IsSquare<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsStrictlyLower.h b/src/cpu/blaze/math/typetraits/IsStrictlyLower.h
new file mode 100644
index 00000000..7efb20cd
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsStrictlyLower.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsStrictlyLower.h
+// \brief Header file for the IsStrictlyLower type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSTRICTLYLOWER_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSTRICTLYLOWER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for strictly lower triangular matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a strictly lower
+// triangular matrix type (i.e. a matrix type that is guaranteed to be strictly lower
+// triangular at compile time). In case the type is a strictly lower triangular matrix
+// type, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::StrictlyLowerMatrix<StaticMatrixType> StrictlyLowerStaticType;
+ typedef blaze::StrictlyLowerMatrix<DynamicMatrixType> StrictlyLowerDynamicType;
+ typedef blaze::StrictlyLowerMatrix<CompressedMatrixType> StrictlyLowerCompressedType;
+
+ blaze::IsStrictlyLower< StrictlyLowerStaticType >::value // Evaluates to 1
+ blaze::IsStrictlyLower< const StrictlyLowerDynamicType >::Type // Results in TrueType
+ blaze::IsStrictlyLower< volatile StrictlyLowerCompressedType > // Is derived from TrueType
+ blaze::IsStrictlyLower< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsStrictlyLower< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsStrictlyLower< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsStrictlyLower : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsStrictlyLower type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsStrictlyLower< const T > : public IsStrictlyLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsStrictlyLower type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsStrictlyLower< volatile T > : public IsStrictlyLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsStrictlyLower type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsStrictlyLower< const volatile T > : public IsStrictlyLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsStrictlyTriangular.h b/src/cpu/blaze/math/typetraits/IsStrictlyTriangular.h
new file mode 100644
index 00000000..dd31a75b
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsStrictlyTriangular.h
@@ -0,0 +1,94 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsStrictlyTriangular.h
+// \brief Header file for the IsStrictlyTriangular type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSTRICTLYTRIANGULAR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSTRICTLYTRIANGULAR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for strictly triangular matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a strictly lower or
+// upper triangular matrix type. In case the type is a triangular matrix type, the \a value
+// member constant is set to \a true, the nested type definition \a Type is \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a yes is set to \a false, \a Type
+// is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::StrictlyLowerMatrix<StaticMatrixType> StrictlyLowerStaticType;
+ typedef blaze::StrictlyUpperMatrix<DynamicMatrixType> StrictlyUpperDynamicType;
+ typedef blaze::StrictlyLowerMatrix<CompressedMatrixType> StrictlyLowerCompressedType;
+
+ blaze::IsStrictlyTriangular< StrictlyLowerStaticType >::value // Evaluates to 1
+ blaze::IsStrictlyTriangular< const StrictlyUpperDynamicType >::Type // Results in TrueType
+ blaze::IsStrictlyTriangular< volatile StrictlyLowerCompressedType > // Is derived from TrueType
+ blaze::IsStrictlyTriangular< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsStrictlyTriangular< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsStrictlyTriangular< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsStrictlyTriangular
+ : public BoolConstant< Or< IsStrictlyLower<T>, IsStrictlyUpper<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsStrictlyUpper.h b/src/cpu/blaze/math/typetraits/IsStrictlyUpper.h
new file mode 100644
index 00000000..83a11c06
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsStrictlyUpper.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsStrictlyUpper.h
+// \brief Header file for the IsStrictlyUpper type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSTRICTLYUPPER_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSTRICTLYUPPER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for strictly upper triangular matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a strictly upper
+// triangular matrix type (i.e. a matrix type that is guaranteed to be strictly upper
+// triangular at compile time). In case the type is a strictly upper triangular matrix
+// type, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is
+// set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::StrictlyUpperMatrix<StaticMatrixType> StrictlyUpperStaticType;
+ typedef blaze::StrictlyUpperMatrix<DynamicMatrixType> StrictlyUpperDynamicType;
+ typedef blaze::StrictlyUpperMatrix<CompressedMatrixType> StrictlyUpperCompressedType;
+
+ blaze::IsStrictlyUpper< StrictlyUpperStaticType >::value // Evaluates to 1
+ blaze::IsStrictlyUpper< const StrictlyUpperDynamicType >::Type // Results in TrueType
+ blaze::IsStrictlyUpper< volatile StrictlyUpperCompressedType > // Is derived from TrueType
+ blaze::IsStrictlyUpper< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsStrictlyUpper< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsStrictlyUpper< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsStrictlyUpper : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsStrictlyUpper type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsStrictlyUpper< const T > : public IsStrictlyUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsStrictlyUpper type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsStrictlyUpper< volatile T > : public IsStrictlyUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsStrictlyUpper type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsStrictlyUpper< const volatile T > : public IsStrictlyUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSubExpr.h b/src/cpu/blaze/math/typetraits/IsSubExpr.h
new file mode 100644
index 00000000..8b934fb2
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSubExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSubExpr.h
+// \brief Header file for the IsSubExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSUBEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/SubExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a subtraction expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a subtraction expression
+// template (i.e. an expression representing a vector subtraction or a matrix subtraction). In
+// order to qualify as a valid subtraction expression template, the given type has to derive
+// (publicly or privately) from the SubExpr base class. In case the given type is a valid
+// subtraction expression template, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsSubExpr
+ : public BoolConstant< And< IsBaseOf<SubExpr,T>, Not< IsBaseOf<T,SubExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSubmatrix.h b/src/cpu/blaze/math/typetraits/IsSubmatrix.h
new file mode 100644
index 00000000..04cdf7c9
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSubmatrix.h
@@ -0,0 +1,139 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSubmatrix.h
+// \brief Header file for the IsSubmatrix type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSUBMATRIX_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSUBMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/views/Forward.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for submatrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a submatrix (i.e. dense
+// or sparse submatrix). In case the type is a submatrix, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ typedef blaze::DynamicMatrix<double,columnMajor> DenseMatrixType1;
+ typedef blaze::Submatrix<DenseMatrixType1> DenseSubmatrixType1;
+
+ typedef blaze::StaticMatrix<float,3UL,4UL,rowMajor> DenseMatrixType2;
+ typedef blaze::Submatrix<DenseMatrixType2> DenseSubmatrixType2;
+
+ typedef blaze::CompressedMatrix<int,columnMajor> SparseMatrixType;
+ typedef blaze::Submatrix<SparseMatrixType> SparseSubmatrixType;
+
+ blaze::IsSubmatrix< SparseSubmatrixType >::value // Evaluates to 1
+ blaze::IsSubmatrix< const DenseSubmatrixType1 >::Type // Results in TrueType
+ blaze::IsSubmatrix< volatile DenseSubmatrixType2 > // Is derived from TrueType
+ blaze::IsSubmatrix< DenseMatrixType1 >::value // Evaluates to 0
+ blaze::IsSubmatrix< const SparseMatrixType >::Type // Results in FalseType
+ blaze::IsSubmatrix< volatile long double > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSubmatrix : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSubmatrix type trait for 'Submatrix'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool AF, bool SO, bool DF >
+struct IsSubmatrix< Submatrix<MT,AF,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSubmatrix type trait for 'const Submatrix'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool AF, bool SO, bool DF >
+struct IsSubmatrix< const Submatrix<MT,AF,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSubmatrix type trait for 'volatile Submatrix'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool AF, bool SO, bool DF >
+struct IsSubmatrix< volatile Submatrix<MT,AF,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSubmatrix type trait for 'const volatile Submatrix'.
+// \ingroup math_type_traits
+*/
+template< typename MT, bool AF, bool SO, bool DF >
+struct IsSubmatrix< const volatile Submatrix<MT,AF,SO,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSubvector.h b/src/cpu/blaze/math/typetraits/IsSubvector.h
new file mode 100644
index 00000000..a26b7c36
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSubvector.h
@@ -0,0 +1,139 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSubvector.h
+// \brief Header file for the IsSubvector type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSUBVECTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSUBVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/views/Forward.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for subvectors.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a subvector (i.e. dense
+// or sparse subvector). In case the type is a subvector, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ typedef blaze::DynamicVector<double,columnVector> DenseVectorType1;
+ typedef blaze::Subvector<DenseVectorType1> DenseSubvectorType1;
+
+ typedef blaze::StaticVector<float,3UL,rowVector> DenseVectorType2;
+ typedef blaze::Subvector<DenseVectorType2> DenseSubvectorType2;
+
+ typedef blaze::CompressedVector<int,columnVector> SparseVectorType;
+ typedef blaze::Subvector<SparseVectorType> SparseSubvectorType;
+
+ blaze::IsSubvector< SparseSubvectorType >::value // Evaluates to 1
+ blaze::IsSubvector< const DenseSubvectorType1 >::Type // Results in TrueType
+ blaze::IsSubvector< volatile DenseSubvectorType2 > // Is derived from TrueType
+ blaze::IsSubvector< DenseVectorType1 >::value // Evaluates to 0
+ blaze::IsSubvector< const SparseVectorType >::Type // Results in FalseType
+ blaze::IsSubvector< volatile long double > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSubvector : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSubvector type trait for 'Subvector'.
+// \ingroup math_type_traits
+*/
+template< typename VT, bool AF, bool TF, bool DF >
+struct IsSubvector< Subvector<VT,AF,TF,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSubvector type trait for 'const Subvector'.
+// \ingroup math_type_traits
+*/
+template< typename VT, bool AF, bool TF, bool DF >
+struct IsSubvector< const Subvector<VT,AF,TF,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSubvector type trait for 'volatile Subvector'.
+// \ingroup math_type_traits
+*/
+template< typename VT, bool AF, bool TF, bool DF >
+struct IsSubvector< volatile Subvector<VT,AF,TF,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSubvector type trait for 'const volatile Subvector'.
+// \ingroup math_type_traits
+*/
+template< typename VT, bool AF, bool TF, bool DF >
+struct IsSubvector< const volatile Subvector<VT,AF,TF,DF> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsSymmetric.h b/src/cpu/blaze/math/typetraits/IsSymmetric.h
new file mode 100644
index 00000000..08a792c9
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsSymmetric.h
@@ -0,0 +1,127 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsSymmetric.h
+// \brief Header file for the IsSymmetric type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISSYMMETRIC_H_
+#define _BLAZE_MATH_TYPETRAITS_ISSYMMETRIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for symmetric matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a symmetric matrix type
+// (i.e. a matrix type that is guaranteed to be symmetric at compile time). In case the type is
+// a symmetric matrix type, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::SymmetricMatrix<StaticMatrixType> SymmetricStaticType;
+ typedef blaze::SymmetricMatrix<DynamicMatrixType> SymmetricDynamicType;
+ typedef blaze::SymmetricMatrix<CompressedMatrixType> SymmetricCompressedType;
+
+ blaze::IsSymmetric< SymmetricStaticType >::value // Evaluates to 1
+ blaze::IsSymmetric< const SymmetricDynamicType >::Type // Results in TrueType
+ blaze::IsSymmetric< volatile SymmetricCompressedType > // Is derived from TrueType
+ blaze::IsSymmetric< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsSymmetric< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsSymmetric< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSymmetric : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSymmetric type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsSymmetric< const T > : public IsSymmetric<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSymmetric type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsSymmetric< volatile T > : public IsSymmetric<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsSymmetric type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsSymmetric< const volatile T > : public IsSymmetric<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsTVecMatMultExpr.h b/src/cpu/blaze/math/typetraits/IsTVecMatMultExpr.h
new file mode 100644
index 00000000..a7e734a9
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsTVecMatMultExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsTVecMatMultExpr.h
+// \brief Header file for the IsTVecMatMultExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISTVECMATMULTEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISTVECMATMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/TVecMatMultExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector/matrix multiplication expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector/matrix
+// multiplication expression template. In order to qualify as a valid vector/matrix
+// multiplication expression template, the given type has to derive (publicly or
+// privately) from the TVecMatMultExpr base class. In case the given type is a valid
+// vector/matrix multiplication expression template, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and
+// the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsTVecMatMultExpr
+ : public BoolConstant< And< IsBaseOf<TVecMatMultExpr,T>, Not< IsBaseOf<T,TVecMatMultExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsTemporary.h b/src/cpu/blaze/math/typetraits/IsTemporary.h
new file mode 100644
index 00000000..02ebee6f
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsTemporary.h
@@ -0,0 +1,77 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsTemporary.h
+// \brief Header file for the IsTemporary type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISTEMPORARY_H_
+#define _BLAZE_MATH_TYPETRAITS_ISTEMPORARY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a temporary vector or matrix type.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether the given type is a temporary vector or matrix type,
+// i.e. can be used for a temporary vector or matrix. In case the given type can be used as
+// temporary, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsTemporary
+ : public BoolConstant< And< Not< IsReference<T> >, Not< IsNumeric<T> >, Not< IsExpression<T> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsTransExpr.h b/src/cpu/blaze/math/typetraits/IsTransExpr.h
new file mode 100644
index 00000000..862be0c1
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsTransExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsTransExpr.h
+// \brief Header file for the IsTransExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISTRANSEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/TransExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a transposition expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a transposition expression
+// template (i.e. an expression representing a vector transposition or a matrix transposition).
+// In order to qualify as a valid transposition expression template, the given type has to derive
+// (publicly or privately) from the TransExpr base class. In case the given type is a valid
+// transposition expression template, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsTransExpr
+ : public BoolConstant< And< IsBaseOf<TransExpr,T>, Not< IsBaseOf<T,TransExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsTriangular.h b/src/cpu/blaze/math/typetraits/IsTriangular.h
new file mode 100644
index 00000000..2a6e2e71
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsTriangular.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsTriangular.h
+// \brief Header file for the IsTriangular type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISTRIANGULAR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISTRIANGULAR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for triangular matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a lower or upper triangular
+// matrix type. In case the type is a triangular matrix type, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a yes is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::LowerMatrix<StaticMatrixType> LowerStaticType;
+ typedef blaze::UpperMatrix<DynamicMatrixType> UpperDynamicType;
+ typedef blaze::LowerMatrix<CompressedMatrixType> LowerCompressedType;
+
+ blaze::IsLower< LowerStaticType >::value // Evaluates to 1
+ blaze::IsLower< const UpperDynamicType >::Type // Results in TrueType
+ blaze::IsLower< volatile LowerCompressedType > // Is derived from TrueType
+ blaze::IsLower< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsLower< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsLower< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsTriangular : public BoolConstant< Or< IsLower<T>, IsUpper<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsUniLower.h b/src/cpu/blaze/math/typetraits/IsUniLower.h
new file mode 100644
index 00000000..ddb1f20c
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsUniLower.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsUniLower.h
+// \brief Header file for the IsUniLower type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISUNILOWER_H_
+#define _BLAZE_MATH_TYPETRAITS_ISUNILOWER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for lower unitriangular matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a lower unitriangular
+// matrix type (i.e. a matrix type that is guaranteed to be lower unitriangular at compile time).
+// In case the type is a lower unitriangular matrix type, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::UniLowerMatrix<StaticMatrixType> UniLowerStaticType;
+ typedef blaze::UniLowerMatrix<DynamicMatrixType> UniLowerDynamicType;
+ typedef blaze::UniLowerMatrix<CompressedMatrixType> UniLowerCompressedType;
+
+ blaze::IsUniLower< UniLowerStaticType >::value // Evaluates to 1
+ blaze::IsUniLower< const UniLowerDynamicType >::Type // Results in TrueType
+ blaze::IsUniLower< volatile UniLowerCompressedType > // Is derived from TrueType
+ blaze::IsUniLower< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsUniLower< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsUniLower< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsUniLower : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUniLower type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUniLower< const T > : public IsUniLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUniLower type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUniLower< volatile T > : public IsUniLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUniLower type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUniLower< const volatile T > : public IsUniLower<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsUniTriangular.h b/src/cpu/blaze/math/typetraits/IsUniTriangular.h
new file mode 100644
index 00000000..89062530
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsUniTriangular.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsUniTriangular.h
+// \brief Header file for the IsUniTriangular type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISUNITRIANGULAR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISUNITRIANGULAR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for unitriangular matrix types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a lower or upper
+// unitriangular matrix type. In case the type is an unitriangular matrix type, the \a value
+// member constant is set to \a true, the nested type definition \a Type is \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a yes is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::UniLowerMatrix<StaticMatrixType> UniLowerStaticType;
+ typedef blaze::UniUpperMatrix<DynamicMatrixType> UniUpperDynamicType;
+ typedef blaze::UniLowerMatrix<CompressedMatrixType> UniLowerCompressedType;
+
+ blaze::IsUniTriangular< UniLowerStaticType >::value // Evaluates to 1
+ blaze::IsUniTriangular< const UniUpperDynamicType >::Type // Results in TrueType
+ blaze::IsUniTriangular< volatile UniLowerCompressedType > // Is derived from TrueType
+ blaze::IsUniTriangular< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsUniTriangular< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsUniTriangular< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsUniTriangular : public BoolConstant< Or< IsUniLower<T>, IsUniUpper<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsUniUpper.h b/src/cpu/blaze/math/typetraits/IsUniUpper.h
new file mode 100644
index 00000000..3d9a9800
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsUniUpper.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsUniUpper.h
+// \brief Header file for the IsUniUpper type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISUNIUPPER_H_
+#define _BLAZE_MATH_TYPETRAITS_ISUNIUPPER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for upper unitriangular matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is an upper unitriangular
+// matrix type (i.e. a matrix type that is guaranteed to be upper unitriangular at compile time).
+// In case the type is an upper unitriangular matrix type, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::UniUpperMatrix<StaticMatrixType> UniUpperStaticType;
+ typedef blaze::UniUpperMatrix<DynamicMatrixType> UniUpperDynamicType;
+ typedef blaze::UniUpperMatrix<CompressedMatrixType> UniUpperCompressedType;
+
+ blaze::IsUniUpper< UniUpperStaticType >::value // Evaluates to 1
+ blaze::IsUniUpper< const UniUpperDynamicType >::Type // Results in TrueType
+ blaze::IsUniUpper< volatile UniUpperCompressedType > // Is derived from TrueType
+ blaze::IsUniUpper< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsUniUpper< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsUniUpper< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsUniUpper : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUniUpper type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUniUpper< const T > : public IsUniUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUniUpper type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUniUpper< volatile T > : public IsUniUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUniUpper type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUniUpper< const volatile T > : public IsUniUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsUpper.h b/src/cpu/blaze/math/typetraits/IsUpper.h
new file mode 100644
index 00000000..a18abd03
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsUpper.h
@@ -0,0 +1,130 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsUpper.h
+// \brief Header file for the IsUpper type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISUPPER_H_
+#define _BLAZE_MATH_TYPETRAITS_ISUPPER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for upper triangular matrices.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is an upper triangular matrix
+// type (i.e. a matrix type that is guaranteed to be upper triangular at compile time). This also
+// includes upper unitriangular and strictly upper triangular matrices. In case the type is an
+// upper triangular matrix type, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::StaticMatrix<double,3UL,3UL,rowMajor> StaticMatrixType;
+ typedef blaze::DynamicMatrix<float,rowMajor> DynamicMatrixType;
+ typedef blaze::CompressedMatrix<int,rowMajor> CompressedMatrixType;
+
+ typedef blaze::UpperMatrix<StaticMatrixType> UpperStaticType;
+ typedef blaze::UpperMatrix<DynamicMatrixType> UpperDynamicType;
+ typedef blaze::UniUpperMatrix<CompressedMatrixType> UniUpperCompressedType;
+
+ blaze::IsUpper< UpperStaticType >::value // Evaluates to 1
+ blaze::IsUpper< const UpperDynamicType >::Type // Results in TrueType
+ blaze::IsUpper< volatile UniUpperCompressedType > // Is derived from TrueType
+ blaze::IsUpper< StaticMatrixType >::value // Evaluates to 0
+ blaze::IsUpper< const DynamicMatrixType >::Type // Results in FalseType
+ blaze::IsUpper< volatile CompressedMatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsUpper : public BoolConstant< Or< IsUniUpper<T>, IsStrictlyUpper<T> >::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUpper type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUpper< const T > : public IsUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUpper type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUpper< volatile T > : public IsUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsUpper type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct IsUpper< const volatile T > : public IsUpper<T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecEvalExpr.h b/src/cpu/blaze/math/typetraits/IsVecEvalExpr.h
new file mode 100644
index 00000000..ed582971
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecEvalExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecEvalExpr.h
+// \brief Header file for the IsVecEvalExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECEVALEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECEVALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecEvalExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector evaluation expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector evaluation
+// expression template. In order to qualify as a valid vector evaluation expression template,
+// the given type has to derive (publicly or privately) from the VecEvalExpr base class. In
+// case the given type is a valid vector evaluation expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and
+// the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsVecEvalExpr
+ : public BoolConstant< And< IsBaseOf<VecEvalExpr,T>, Not< IsBaseOf<T,VecEvalExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecForEachExpr.h b/src/cpu/blaze/math/typetraits/IsVecForEachExpr.h
new file mode 100644
index 00000000..0e7775b7
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecForEachExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecForEachExpr.h
+// \brief Header file for the IsVecForEachExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECFOREACHEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECFOREACHEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecForEachExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector for-each expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector for-each
+// expression template. In order to qualify as a valid vector for-each expression template,
+// the given type has to derive (publicly or privately) from the VecForEachExpr base class.
+// In case the given type is a valid vector for-each expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType,
+// and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsVecForEachExpr
+ : public BoolConstant< And< IsBaseOf<VecForEachExpr,T>, Not< IsBaseOf<T,VecForEachExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecScalarDivExpr.h b/src/cpu/blaze/math/typetraits/IsVecScalarDivExpr.h
new file mode 100644
index 00000000..4402bfaf
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecScalarDivExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecScalarDivExpr.h
+// \brief Header file for the IsVecScalarDivExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECSCALARDIVEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECSCALARDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecScalarDivExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector/scalar division expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector/scalar
+// division expression template. In order to qualify as a valid vector/scalar division
+// expression template, the given type has to derive (publicly or privately) from the
+// VecScalarDivExpr base class. In case the given type is a valid vector/scalar division
+// expression template, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+*/
+template< typename T >
+struct IsVecScalarDivExpr
+ : public BoolConstant< And< IsBaseOf<VecScalarDivExpr,T>, Not< IsBaseOf<T,VecScalarDivExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecScalarMultExpr.h b/src/cpu/blaze/math/typetraits/IsVecScalarMultExpr.h
new file mode 100644
index 00000000..84209df3
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecScalarMultExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecScalarMultExpr.h
+// \brief Header file for the IsVecScalarMultExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECSCALARMULTEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECSCALARMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecScalarMultExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector/scalar multiplication expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector/scalar
+// multiplication expression template. In order to qualify as a valid vector/scalar
+// multiplication expression template, the given type has to derive (publicly or privately)
+// from the VecScalarMultExpr base class. In case the given type is a valid vector/scalar
+// multiplication expression template, the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives
+// from \a FalseType.
+*/
+template< typename T >
+struct IsVecScalarMultExpr
+ : public BoolConstant< And< IsBaseOf<VecScalarMultExpr,T>, Not< IsBaseOf<T,VecScalarMultExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecSerialExpr.h b/src/cpu/blaze/math/typetraits/IsVecSerialExpr.h
new file mode 100644
index 00000000..d7acc316
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecSerialExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecSerialExpr.h
+// \brief Header file for the IsVecSerialExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECSERIALEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECSERIALEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecSerialExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector serial evaluation expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector serial evaluation
+// expression template. In order to qualify as a valid vector serial evaluation expression template,
+// the given type has to derive (publicly or privately) from the VecSerialExpr base class. In case
+// the given type is a valid vector serial evaluation expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and
+// the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsVecSerialExpr
+ : public BoolConstant< And< IsBaseOf<VecSerialExpr,T>, Not< IsBaseOf<T,VecSerialExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecTVecMultExpr.h b/src/cpu/blaze/math/typetraits/IsVecTVecMultExpr.h
new file mode 100644
index 00000000..dda69199
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecTVecMultExpr.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecTVecMultExpr.h
+// \brief Header file for the IsVecTVecMultExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECTVECMULTEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECTVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecTVecMultExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is an outer product expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is an outer product
+// expression template (i.e. an expression representing the multiplication between a column
+// vector and a row vector). In order to qualify as a valid outer product expression template,
+// the given type has to derive (publicly or privately) from the VecTVecMultExpr base class.
+// In case the given type is a valid outer product expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the
+// class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsVecTVecMultExpr
+ : public BoolConstant< And< IsBaseOf<VecTVecMultExpr,T>, Not< IsBaseOf<T,VecTVecMultExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecTransExpr.h b/src/cpu/blaze/math/typetraits/IsVecTransExpr.h
new file mode 100644
index 00000000..47f23d17
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecTransExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecTransExpr.h
+// \brief Header file for the IsVecTransExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECTRANSEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECTRANSEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecTransExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector transposition expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector transposition
+// expression template. In order to qualify as a valid vector transposition expression template,
+// the given type has to derive (publicly or privately) from the VecTransExpr base class. In
+// case the given type is a valid vector transposition expression template, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType,
+// and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsVecTransExpr
+ : public BoolConstant< And< IsBaseOf<VecTransExpr,T>, Not< IsBaseOf<T,VecTransExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecVecAddExpr.h b/src/cpu/blaze/math/typetraits/IsVecVecAddExpr.h
new file mode 100644
index 00000000..5b430e0a
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecVecAddExpr.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecVecAddExpr.h
+// \brief Header file for the IsVecVecAddExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECVECADDEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECVECADDEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecVecAddExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector/vector addition expression template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector/vector addition
+// expression template. In order to qualify as a valid vector addition expression template, the
+// given type has to derive (publicly or privately) from the VecVecAddExpr base class. In case
+// the given type is a valid vector addition expression template, the \a value member constant
+// is set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+*/
+template< typename T >
+struct IsVecVecAddExpr
+ : public BoolConstant< And< IsBaseOf<VecVecAddExpr,T>, Not< IsBaseOf<T,VecVecAddExpr> > >::value>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecVecDivExpr.h b/src/cpu/blaze/math/typetraits/IsVecVecDivExpr.h
new file mode 100644
index 00000000..10c1d226
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecVecDivExpr.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecVecDivExpr.h
+// \brief Header file for the IsVecVecDivExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECVECDIVEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECVECDIVEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecVecDivExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector/vector division expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector/vector division
+// expression template. In order to qualify as a valid vector division expression template, the
+// given type has to derive (publicly or privately) from the VecVecDivExpr base class. In case
+// the given type is a valid vector division expression template, the \a value member constant
+// is set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+*/
+template< typename T >
+struct IsVecVecDivExpr
+ : public BoolConstant< And< IsBaseOf<VecVecDivExpr,T>, Not< IsBaseOf<T,VecVecDivExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecVecMultExpr.h b/src/cpu/blaze/math/typetraits/IsVecVecMultExpr.h
new file mode 100644
index 00000000..3ec7f06f
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecVecMultExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecVecMultExpr.h
+// \brief Header file for the IsVecVecMultExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECVECMULTEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECVECMULTEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecVecMultExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector/vector multiplication expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector/vector
+// multiplication expression template. In order to qualify as a valid vector multiplication
+// expression template, the given type has to derive (publicly or privately) from the
+// VecVecMultExpr base class. In case the given type is a valid vector multiplication
+// expression template, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+*/
+template< typename T >
+struct IsVecVecMultExpr
+ : public BoolConstant< And< IsBaseOf<VecVecMultExpr,T>, Not< IsBaseOf<T,VecVecMultExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVecVecSubExpr.h b/src/cpu/blaze/math/typetraits/IsVecVecSubExpr.h
new file mode 100644
index 00000000..fe7cb2c0
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVecVecSubExpr.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVecVecSubExpr.h
+// \brief Header file for the IsVecVecSubExpr type trait class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECVECSUBEXPR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECVECSUBEXPR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/VecVecSubExpr.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether the given type is a vector/vector subtraction expression
+// template.
+// \ingroup math_type_traits
+//
+// This type trait class tests whether or not the given type \a Type is a vector/vector
+// subtraction expression template. In order to qualify as a valid vector subtraction
+// expression template, the given type has to derive (publicly or privately) from the
+// VecVecSubExpr base class. In case the given type is a valid vector subtraction
+// expression template, the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives
+// from \a FalseType.
+*/
+template< typename T >
+struct IsVecVecSubExpr
+ : public BoolConstant< And< IsBaseOf<VecVecSubExpr,T>, Not< IsBaseOf<T,VecVecSubExpr> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsVector.h b/src/cpu/blaze/math/typetraits/IsVector.h
new file mode 100644
index 00000000..2eab0df7
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsVector.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsVector.h
+// \brief Header file for the IsVector type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVECTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Vector.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for vector types.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a N-dimensional dense
+// or sparse vector type. In case the type is a vector type, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsVector< StaticVector<float,3U,false> >::value // Evaluates to 1
+ blaze::IsVector< const DynamicVector<double,true> >::Type // Results in TrueType
+ blaze::IsVector< volatile CompressedVector<int,true> > // Is derived from TrueType
+ blaze::IsVector< StaticMatrix<double,3U,3U,false> >::value // Evaluates to 0
+ blaze::IsVector< const DynamicMatrix<double,true> >::Type // Results in FalseType
+ blaze::IsVector< volatile CompressedMatrix<int,true> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsVector
+ : public BoolConstant< Or< IsBaseOf<Vector<RemoveCV_<T>,false>,T>
+ , IsBaseOf<Vector<RemoveCV_<T>,true>,T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/IsView.h b/src/cpu/blaze/math/typetraits/IsView.h
new file mode 100644
index 00000000..ad3a893b
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/IsView.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/IsView.h
+// \brief Header file for the IsView type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ISVIEW_H_
+#define _BLAZE_MATH_TYPETRAITS_ISVIEW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/View.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for views.
+// \ingroup math_type_traits
+//
+// This type trait tests whether or not the given template parameter is a view (i.e. subvector,
+// submatrix, row, column, ...). In case the type is a view, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ using blaze::columnVector;
+
+ typedef blaze::DynamicVector<double,columnVector> VectorType;
+ typedef blaze::Subvector<VectorType> SubvectorType;
+
+ typedef blaze::CompressedMatrix<int,rowMajor> MatrixType;
+ typedef blaze::Row<MatrixType> RowType;
+ typedef blaze::Column<MatrixType> ColumnType;
+
+ blaze::IsView< SubvectorType >::value // Evaluates to 1
+ blaze::IsView< const RowType >::Type // Results in TrueType
+ blaze::IsView< volatile ColumnType > // Is derived from TrueType
+ blaze::IsView< float >::value // Evaluates to 0
+ blaze::IsView< const VectorType >::Type // Results in FalseType
+ blaze::IsView< volatile MatrixType > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsView : public BoolConstant< And< IsBaseOf<View,T>, Not< IsBaseOf<T,View> > >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/RemoveAdaptor.h b/src/cpu/blaze/math/typetraits/RemoveAdaptor.h
new file mode 100644
index 00000000..de73b9ab
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/RemoveAdaptor.h
@@ -0,0 +1,158 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/RemoveAdaptor.h
+// \brief Header file for the RemoveAdaptor type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_REMOVEADAPTOR_H_
+#define _BLAZE_MATH_TYPETRAITS_REMOVEADAPTOR_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Removal of top level adaptor types.
+// \ingroup math_type_traits
+//
+// In case the given type is an adaptor type (SymmetricMatrix, LowerMatrix, UpperMatrix, ...),
+// the RemoveAdaptor type trait removes the adaptor and extracts the contained general matrix
+// type. Else the given type is returned as is. Note that cv-qualifiers are preserved.
+
+ \code
+ using blaze::DynamicVector;
+ using blaze::DynamicMatrix;
+ using blaze::CompressedMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::LowerMatrix;
+ using blaze::UpperMatrix;
+
+ typedef SymmetricMatrix< DynamicMatrix<int> > SymmetricDynamic;
+ typedef LowerMatrix< CompressedMatrix<float> > LowerCompressed;
+ typedef UpperMatrix< DynamicMatrix<double> > UpperDynamic;
+
+ blaze::RemoveAdaptor< SymmetricDynamic >::Type // Results in 'DynamicMatrix<int>'
+ blaze::RemoveAdaptor< const LowerCompressed >::Type // Results in 'const CompressedMatrix<float>'
+ blaze::RemoveAdaptor< volatile UpperDynamic >::Type // Results in 'volatile DynamicMatrix<double>'
+ blaze::RemoveAdaptor< int >::Type // Results in 'int'
+ blaze::RemoveAdaptor< const DynamicVector<int> >::Type // Results in 'const DynamicVector<int>'
+ blaze::RemoveAdaptor< volatile DynamicMatrix<int> >::Type // Results in 'volatile DynamicMatrix<int>'
+ \endcode
+*/
+template< typename T >
+struct RemoveAdaptor
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef T Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the RemoveAdaptor type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct RemoveAdaptor< const T >
+{
+ public:
+ //**********************************************************************************************
+ typedef const typename RemoveAdaptor<T>::Type Type;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the RemoveAdaptor type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct RemoveAdaptor< volatile T >
+{
+ public:
+ //**********************************************************************************************
+ typedef volatile typename RemoveAdaptor<T>::Type Type;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the RemoveAdaptor type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct RemoveAdaptor< const volatile T >
+{
+ public:
+ //**********************************************************************************************
+ typedef const volatile typename RemoveAdaptor<T>::Type Type;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RemoveAdaptor type trait.
+// \ingroup type_traits
+//
+// The RemoveAdaptor_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the RemoveAdaptor class template. For instance, given the type \a T the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename RemoveAdaptor<T>::Type;
+ using Type2 = RemoveAdaptor_<T>;
+ \endcode
+*/
+template< typename T >
+using RemoveAdaptor_ = typename RemoveAdaptor<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/RequiresEvaluation.h b/src/cpu/blaze/math/typetraits/RequiresEvaluation.h
new file mode 100644
index 00000000..b1002863
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/RequiresEvaluation.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/RequiresEvaluation.h
+// \brief Header file for the RequiresEvaluation type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_REQUIRESEVALUATION_H_
+#define _BLAZE_MATH_TYPETRAITS_REQUIRESEVALUATION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/typetraits/IsReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check to query the requirement to evaluate an expression.
+// \ingroup math_type_traits
+//
+// Via this type trait it is possible to determine whether a given vector or matrix expression
+// type requires an intermediate evaluation in the context of a compound expression. In case
+// the given type requires an evaluation, the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives
+// from \a FalseType.
+//
+// \note that this type trait can only be applied to Blaze vector or matrix expressions
+// or any other type providing the nested type \a CompositeType. In case this nested type
+// is not available, applying the type trait results in a compile time error!
+*/
+template< typename T >
+struct RequiresEvaluation
+ : public BoolConstant< Not< IsReference<typename T::CompositeType> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/Rows.h b/src/cpu/blaze/math/typetraits/Rows.h
new file mode 100644
index 00000000..ba33b91a
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/Rows.h
@@ -0,0 +1,118 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/Rows.h
+// \brief Header file for the Rows type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_ROWS_H_
+#define _BLAZE_MATH_TYPETRAITS_ROWS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time evaluation of the number of rows of a matrix.
+// \ingroup math_type_traits
+//
+// The Rows type trait evaluates the number of rows of the given matrix type at compile time. In
+// case the given type \a T is a matrix type with a fixed number of rows (e.g. StaticMatrix), the
+// \a value member constant is set to the according number of rows. In all other cases, \a value
+// is set to 0.
+
+ \code
+ using blaze::StaticMatrix;
+ using blaze::HybridMatrix;
+ using blaze::DynamicMatrix;
+
+ blaze::Rows< StaticMatrix<int,3UL,2UL> >::value // Evaluates to 3
+ blaze::Rows< HybridMatrix<int,3UL,2UL> >::value // Evaluates to 0; Only maximum number of rows is fixed!
+ blaze::Rows< DynamicMatrix<int> >::value // Evaluates to 0; Number of rows not fixed at compile time!
+ blaze::Rows< int >::value // Evaluates to 0
+ \endcode
+*/
+template< typename T >
+struct Rows : public SizeT<0UL>
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rows type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Rows< const T > : public SizeT< Rows<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rows type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Rows< volatile T > : public SizeT< Rows<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rows type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Rows< const volatile T > : public SizeT< Rows<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/Size.h b/src/cpu/blaze/math/typetraits/Size.h
new file mode 100644
index 00000000..7fa8d252
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/Size.h
@@ -0,0 +1,117 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/Size.h
+// \brief Header file for the Size type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_SIZE_H_
+#define _BLAZE_MATH_TYPETRAITS_SIZE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time evaluation of the size of a vector.
+// \ingroup math_type_traits
+//
+// The Size type trait evaluates the size of the given vector type at compile time. In case the
+// given type \a T is a vector type with a fixed size (e.g. StaticVector), the \a value member
+// constant is set to the according size. In all other cases, \a value is set to 0.
+
+ \code
+ using blaze::StaticVector;
+ using blaze::HybridVector;
+ using blaze::DynamicVector;
+
+ blaze::Size< StaticVector<int,3UL> >::value // Evaluates to 3
+ blaze::Size< HybridVector<int,3UL> >::value // Evaluates to 0; Only maximum size is fixed!
+ blaze::Size< DynamicVector<int> >::value // Evaluates to 0; Size not fixed at compile time!
+ blaze::Size< int >::value // Evaluates to 0
+ \endcode
+*/
+template< typename T >
+struct Size : public SizeT<0UL>
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Size type trait for const types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Size< const T > : public SizeT< Size<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Size type trait for volatile types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Size< volatile T > : public SizeT< Size<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Size type trait for cv qualified types.
+// \ingroup math_type_traits
+*/
+template< typename T >
+struct Size< const volatile T > : public SizeT< Size<T>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/StorageOrder.h b/src/cpu/blaze/math/typetraits/StorageOrder.h
new file mode 100644
index 00000000..44d6fcc6
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/StorageOrder.h
@@ -0,0 +1,83 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/StorageOrder.h
+// \brief Header file for the StorageOrder type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_STORAGEORDER_H_
+#define _BLAZE_MATH_TYPETRAITS_STORAGEORDER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/StorageOrder.h>
+#include <blaze/math/typetraits/IsMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the storage order of a given matrix type.
+// \ingroup math_type_traits
+//
+// Via this type trait it is possible to evaluate the storage order of a given matrix type.
+// In case the given type is a row-major matrix type the nested boolean \a value is set to
+// \a rowMajor, in case it is a column-major matrix type it is set to \a columnMajor. If the
+// given type is not a matrix type a compilation error is created.
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> RowMajorMatrix;
+ typedef blaze::DynamicMatrix<int,blaze::columnMajor> ColumnMajorMatrix;
+
+ blaze::StorageOrder<RowMajorMatrix>::value // Evaluates to blaze::rowMajor
+ blaze::StorageOrder<ColumnMajorMatrix>::value // Evaluates to blaze::columnMajor
+ blaze::StorageOrder<int>::value // Compilation error!
+ \endcode
+*/
+template< typename T, typename = EnableIf_< IsMatrix<T> > >
+struct StorageOrder : public BoolConstant< ( IsRowMajorMatrix<T>::value ? rowMajor : columnMajor ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/TransposeFlag.h b/src/cpu/blaze/math/typetraits/TransposeFlag.h
new file mode 100644
index 00000000..052a4ac9
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/TransposeFlag.h
@@ -0,0 +1,83 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/TransposeFlag.h
+// \brief Header file for the TransposeFlag type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_TRANSPOSEFLAG_H_
+#define _BLAZE_MATH_TYPETRAITS_TRANSPOSEFLAG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/TransposeFlag.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+#include <blaze/math/typetraits/IsVector.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the transpose flag of a given matrix type.
+// \ingroup math_type_traits
+//
+// Via this type trait it is possible to evaluate the transpose flag of a given vector type. In
+// case the given type is a row vector type the nested boolean \a value is set to \a rowVector,
+// in case it is a column vector type it is set to \a columnVector. If the given type is not a
+// vector type a compilation error is created.
+
+ \code
+ typedef blaze::DynamicVector<int,blaze::rowVector> RowVector;
+ typedef blaze::DynamicVector<int,blaze::columnVector> ColumnVector;
+
+ blaze::TransposeFlag<RowVector>::value // Evaluates to blaze::rowVector
+ blaze::TransposeFlag<ColumnVector>::value // Evaluates to blaze::columnVector
+ blaze::TransposeFlag<int>::value // Compilation error!
+ \endcode
+*/
+template< typename T, typename = EnableIf_< IsVector<T> > >
+struct TransposeFlag : public BoolConstant< ( IsRowVector<T>::value ? rowVector : columnVector ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/TypeTraits.h b/src/cpu/blaze/math/typetraits/TypeTraits.h
new file mode 100644
index 00000000..1302ad5e
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/TypeTraits.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/TypeTraits.h
+// \brief Mathematical type traits module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_TYPETRAITS_H_
+#define _BLAZE_MATH_TYPETRAITS_TYPETRAITS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup math_type_traits Type traits
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/UnderlyingBuiltin.h b/src/cpu/blaze/math/typetraits/UnderlyingBuiltin.h
new file mode 100644
index 00000000..40a39202
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/UnderlyingBuiltin.h
@@ -0,0 +1,138 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/UnderlyingBuiltin.h
+// \brief Header file for the UnderlyingBuiltin type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_UNDERLYINGBUILTIN_H_
+#define _BLAZE_MATH_TYPETRAITS_UNDERLYINGBUILTIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the underlying builtin element type of a given data type.
+// \ingroup math_type_traits
+//
+// Via this type trait it is possible to evaluate the underlying fundamental element type at the
+// heart of a given data type. Examples:
+
+ \code
+ typedef double Type1; // Built-in data type
+ typedef complex<float> Type2; // Complex data type
+ typedef StaticVector<int,3UL> Type3; // Vector with built-in element type
+ typedef CompressedVector< DynamicVector<float> > Type4; // Vector with vector element type
+
+ blaze::UnderlyingBuiltin< Type1 >::Type // corresponds to double
+ blaze::UnderlyingBuiltin< Type2 >::Type // corresponds to float
+ blaze::UnderlyingBuiltin< Type3 >::Type // corresponds to int
+ blaze::UnderlyingBuiltin< Type4 >::Type // corresponds to float
+ \endcode
+
+// Note that per default UnderlyingBuiltin only supports fundamental/built-in data types, complex,
+// and data types with the nested type definition \a ElementType. Support for other data types can
+// be added by specializing the UnderlyingBuiltin class template.
+*/
+template< typename T >
+struct UnderlyingBuiltin
+{
+ private:
+ //**struct Builtin******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2 >
+ struct Builtin { typedef T2 Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Complex******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2 >
+ struct Complex { typedef typename UnderlyingBuiltin<typename T2::value_type>::Type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Other********************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2 >
+ struct Other { typedef typename UnderlyingBuiltin<typename T2::ElementType>::Type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename If_< IsBuiltin<T>
+ , Builtin<T>
+ , If_< IsComplex<T>
+ , Complex<T>
+ , Other<T> >
+ >::Type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the UnderlyingBuiltin type trait.
+// \ingroup type_traits
+//
+// The UnderlyingBuiltin_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the UnderlyingBuiltin class template. For instance, given the type \a T
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename UnderlyingBuiltin<T>::Type;
+ using Type2 = UnderlyingBuiltin_<T>;
+ \endcode
+*/
+template< typename T >
+using UnderlyingBuiltin_ = typename UnderlyingBuiltin<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/UnderlyingElement.h b/src/cpu/blaze/math/typetraits/UnderlyingElement.h
new file mode 100644
index 00000000..f57428c7
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/UnderlyingElement.h
@@ -0,0 +1,138 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/UnderlyingElement.h
+// \brief Header file for the UnderlyingElement type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_UNDERLYINGELEMENT_H_
+#define _BLAZE_MATH_TYPETRAITS_UNDERLYINGELEMENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the element type of a given data type.
+// \ingroup math_type_traits
+//
+// Via this type trait it is possible to evaluate the element type of a given data type. Examples:
+
+ \code
+ typedef double Type1; // Built-in data type
+ typedef complex<float> Type2; // Complex data type
+ typedef StaticVector<int,3UL> Type3; // Vector with built-in element type
+ typedef CompressedMatrix< DynamicVector<float> > Type4; // Matrix with vector element type
+
+ blaze::UnderlyingElement< Type1 >::Type // corresponds to double
+ blaze::UnderlyingElement< Type2 >::Type // corresponds to float
+ blaze::UnderlyingElement< Type3 >::Type // corresponds to int
+ blaze::UnderlyingElement< Type4 >::Type // corresponds to DynamicVector<float>
+ \endcode
+
+// Note that per default UnderlyingElement only supports fundamental/built-in data types, complex,
+// and data types with the nested type definition \a ElementType. Support for other data types can
+// be added by specializing the UnderlyingElement class template.
+*/
+template< typename T >
+struct UnderlyingElement
+{
+ private:
+ //**struct Builtin******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2 >
+ struct Builtin { typedef T2 Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Complex******************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2 >
+ struct Complex { typedef typename T2::value_type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Other********************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2 >
+ struct Other { typedef typename T2::ElementType Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename If_< IsBuiltin<T>
+ , Builtin<T>
+ , If_< IsComplex<T>
+ , Complex<T>
+ , Other<T> >
+ >::Type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the UnderlyingElement type trait.
+// \ingroup type_traits
+//
+// The UnderlyingElement_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the UnderlyingElement class template. For instance, given the type \a T
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename UnderlyingElement<T>::Type;
+ using Type2 = UnderlyingElement_<T>;
+ \endcode
+*/
+template< typename T >
+using UnderlyingElement_ = typename UnderlyingElement<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/typetraits/UnderlyingNumeric.h b/src/cpu/blaze/math/typetraits/UnderlyingNumeric.h
new file mode 100644
index 00000000..b72ca388
--- /dev/null
+++ b/src/cpu/blaze/math/typetraits/UnderlyingNumeric.h
@@ -0,0 +1,130 @@
+//=================================================================================================
+/*!
+// \file blaze/math/typetraits/UnderlyingNumeric.h
+// \brief Header file for the UnderlyingNumeric type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_TYPETRAITS_UNDERLYINGNUMERIC_H_
+#define _BLAZE_MATH_TYPETRAITS_UNDERLYINGNUMERIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Evaluation of the underlying numeric element type of a given data type.
+// \ingroup math_type_traits
+//
+// Via this type trait it is possible to evaluate the underlying numeric (fundamental or complex)
+// element type at the heart of a given data type. Examples:
+
+ \code
+ typedef double Type1; // Built-in data type
+ typedef complex<float> Type2; // Complex data type
+ typedef StaticVector<int,3UL> Type3; // Vector with built-in element type
+ typedef CompressedVector< DynamicVector<float> > Type4; // Vector with vector element type
+
+ blaze::UnderlyingNumeric< Type1 >::Type // corresponds to double
+ blaze::UnderlyingNumeric< Type2 >::Type // corresponds to complex<float>
+ blaze::UnderlyingNumeric< Type3 >::Type // corresponds to int
+ blaze::UnderlyingNumeric< Type4 >::Type // corresponds to float
+ \endcode
+
+// Note that per default UnderlyingNumeric only supports fundamental/built-in data types, complex,
+// and data types with the nested type definition \a ElementType. Support for other data types can
+// be added by specializing the UnderlyingNumeric class template.
+*/
+template< typename T >
+struct UnderlyingNumeric
+{
+ private:
+ //**struct BuiltinOrComplex*********************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2 >
+ struct BuiltinOrComplex { typedef T2 Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**struct Other********************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2 >
+ struct Other { typedef typename UnderlyingNumeric<typename T2::ElementType>::Type Type; };
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename If_< Or< IsBuiltin<T>, IsComplex<T> >
+ , BuiltinOrComplex<T>
+ , Other<T>
+ >::Type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the UnderlyingNumeric type trait.
+// \ingroup type_traits
+//
+// The UnderlyingNumeric_ alias declaration provides a convenient shortcut to access the
+// nested \a Type of the UnderlyingNumeric class template. For instance, given the type \a T
+// the following two type definitions are identical:
+
+ \code
+ using Type1 = typename UnderlyingNumeric<T>::Type;
+ using Type2 = UnderlyingNumeric_<T>;
+ \endcode
+*/
+template< typename T >
+using UnderlyingNumeric_ = typename UnderlyingNumeric<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/Column.h b/src/cpu/blaze/math/views/Column.h
new file mode 100644
index 00000000..69f22270
--- /dev/null
+++ b/src/cpu/blaze/math/views/Column.h
@@ -0,0 +1,1074 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/Column.h
+// \brief Header file for all restructuring column functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_COLUMN_H_
+#define _BLAZE_MATH_VIEWS_COLUMN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnExprTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsMatEvalExpr.h>
+#include <blaze/math/typetraits/IsMatForEachExpr.h>
+#include <blaze/math/typetraits/IsMatMatAddExpr.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsMatMatSubExpr.h>
+#include <blaze/math/typetraits/IsMatScalarDivExpr.h>
+#include <blaze/math/typetraits/IsMatScalarMultExpr.h>
+#include <blaze/math/typetraits/IsMatSerialExpr.h>
+#include <blaze/math/typetraits/IsMatTransExpr.h>
+#include <blaze/math/typetraits/IsOpposedView.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/typetraits/IsVecTVecMultExpr.h>
+#include <blaze/math/views/column/BaseTemplate.h>
+#include <blaze/math/views/column/Dense.h>
+#include <blaze/math/views/column/Sparse.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific column of the given matrix.
+// \ingroup views
+//
+// \param matrix The matrix containing the column.
+// \param index The index of the column.
+// \return View on the specified column of the matrix.
+// \exception std::invalid_argument Invalid column access index.
+//
+// This function returns an expression representing the specified column of the given matrix.
+
+ \code
+ using blaze::columnMajor;
+
+ typedef blaze::DynamicMatrix<double,columnMajor> DenseMatrix;
+ typedef blaze::CompressedMatrix<double,columnMajor> SparseMatrix;
+
+ DenseMatrix D;
+ SparseMatrix S;
+ // ... Resizing and initialization
+
+ // Creating a view on the 3rd column of the dense matrix D
+ blaze::Column<DenseMatrix> = column( D, 3UL );
+
+ // Creating a view on the 4th column of the sparse matrix S
+ blaze::Column<SparseMatrix> = column( S, 4UL );
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline DisableIf_< Or< IsComputation<MT>, IsTransExpr<MT> >, ColumnExprTrait_<MT> >
+ column( Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ColumnExprTrait_<MT>( ~matrix, index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific column of the given constant matrix.
+// \ingroup views
+//
+// \param matrix The constant matrix containing the column.
+// \param index The index of the column.
+// \return View on the specified column of the matrix.
+// \exception std::invalid_argument Invalid column access index.
+//
+// This function returns an expression representing the specified column of the given matrix.
+
+ \code
+ using blaze::columnMajor;
+
+ typedef blaze::DynamicMatrix<double,columnMajor> DenseMatrix;
+ typedef blaze::CompressedMatrix<double,columnMajor> SparseMatrix;
+
+ DenseMatrix D;
+ SparseMatrix S;
+ // ... Resizing and initialization
+
+ // Creating a view on the 3rd column of the dense matrix D
+ blaze::Column<DenseMatrix> = column( D, 3UL );
+
+ // Creating a view on the 4th column of the sparse matrix S
+ blaze::Column<SparseMatrix> = column( S, 4UL );
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline DisableIf_< Or< IsComputation<MT>, IsTransExpr<MT> >, ColumnExprTrait_<const MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return ColumnExprTrait_<const MT>( ~matrix, index );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix/matrix addition.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix addition.
+// \param index The index of the column.
+// \return View on the specified column of the addition.
+//
+// This function returns an expression representing the specified column of the given matrix/matrix
+// addition.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatAddExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return column( (~matrix).leftOperand(), index ) + column( (~matrix).rightOperand(), index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix/matrix subtraction.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix subtraction.
+// \param index The index of the column.
+// \return View on the specified column of the subtraction.
+//
+// This function returns an expression representing the specified column of the given matrix/matrix
+// subtraction.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatSubExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return column( (~matrix).leftOperand(), index ) - column( (~matrix).rightOperand(), index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix/matrix multiplication.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix multiplication.
+// \param index The index of the column.
+// \return View on the specified column of the multiplication.
+//
+// This function returns an expression representing the specified column of the given matrix/matrix
+// multiplication.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatMultExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return (~matrix).leftOperand() * column( (~matrix).rightOperand(), index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given outer product.
+// \ingroup views
+//
+// \param matrix The constant outer product.
+// \param index The index of the column.
+// \return View on the specified column of the outer product.
+//
+// This function returns an expression representing the specified column of the given outer
+// product.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsVecTVecMultExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return (~matrix).leftOperand() * (~matrix).rightOperand()[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix/scalar multiplication.
+// \ingroup views
+//
+// \param matrix The constant matrix/scalar multiplication.
+// \param index The index of the column.
+// \return View on the specified column of the multiplication.
+//
+// This function returns an expression representing the specified column of the given matrix/scalar
+// multiplication.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatScalarMultExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return column( (~matrix).leftOperand(), index ) * (~matrix).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix/scalar division.
+// \ingroup views
+//
+// \param matrix The constant matrix/scalar division.
+// \param index The index of the column.
+// \return View on the specified column of the division.
+//
+// This function returns an expression representing the specified column of the given matrix/scalar
+// division.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatScalarDivExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return column( (~matrix).leftOperand(), index ) / (~matrix).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix custom operation.
+// \ingroup views
+//
+// \param matrix The constant matrix custom operation.
+// \param index The index of the column.
+// \return View on the specified column of the custom operation.
+//
+// This function returns an expression representing the specified column of the given matrix
+// custom operation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatForEachExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return forEach( column( (~matrix).operand(), index ), (~matrix).operation() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix evaluation operation.
+// \ingroup views
+//
+// \param matrix The constant matrix evaluation operation.
+// \param index The index of the column.
+// \return View on the specified column of the evaluation operation.
+//
+// This function returns an expression representing the specified column of the given matrix
+// evaluation operation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatEvalExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return eval( column( (~matrix).operand(), index ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix serialization operation.
+// \ingroup views
+//
+// \param matrix The constant matrix serialization operation.
+// \param index The index of the column.
+// \return View on the specified column of the serialization operation.
+//
+// This function returns an expression representing the specified column of the given matrix
+// serialization operation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatSerialExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return serial( column( (~matrix).operand(), index ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific column of the given matrix transpose operation.
+// \ingroup views
+//
+// \param matrix The constant matrix transpose operation.
+// \param index The index of the column.
+// \return View on the specified column of the transpose operation.
+//
+// This function returns an expression representing the specified column of the given matrix
+// transpose operation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatTransExpr<MT>, ColumnExprTrait_<MT> >
+ column( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return trans( row( (~matrix).operand(), index ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// COLUMN OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Column operators */
+//@{
+template< typename MT, bool SO, bool DF, bool SF >
+inline void reset( Column<MT,SO,DF,SF>& column );
+
+template< typename MT, bool SO, bool DF, bool SF >
+inline void clear( Column<MT,SO,DF,SF>& column );
+
+template< typename MT, bool SO, bool DF, bool SF >
+inline bool isDefault( const Column<MT,SO,DF,SF>& column );
+
+template< typename MT, bool SO, bool DF, bool SF >
+inline bool isIntact( const Column<MT,SO,DF,SF>& column ) noexcept;
+
+template< typename MT, bool SO, bool DF, bool SF >
+inline bool isSame( const Column<MT,SO,DF,SF>& a, const Column<MT,SO,DF,SF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given column.
+// \ingroup column
+//
+// \param column The column to be resetted.
+// \return void
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline void reset( Column<MT,SO,DF,SF>& column )
+{
+ column.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given column.
+// \ingroup column
+//
+// \param column The column to be cleared.
+// \return void
+//
+// Clearing a column is equivalent to resetting it via the reset() function.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline void clear( Column<MT,SO,DF,SF>& column )
+{
+ column.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given column is in default state.
+// \ingroup column
+//
+// \param column The column to be tested for its default state.
+// \return \a true in case the given column is component-wise zero, \a false otherwise.
+//
+// This function checks whether the column is in default state. For instance, in case the
+// column is instantiated for a built-in integral or floating point data type, the function
+// returns \a true in case all column elements are 0 and \a false in case any column element
+// is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::DynamicMatrix<int,columnMajor> A;
+ // ... Resizing and initialization
+ if( isDefault( column( A, 0UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline bool isDefault( const Column<MT,SO,DF,SF>& column )
+{
+ for( size_t i=0UL; i<column.size(); ++i )
+ if( !isDefault( column[i] ) ) return false;
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given sparse column is in default state.
+// \ingroup sparse_column
+//
+// \param column The sparse column to be tested for its default state.
+// \return \a true in case the given column is component-wise zero, \a false otherwise.
+//
+// This function checks whether the sparse column is in default state. For instance, in case
+// the column is instantiated for a built-in integral or floating point data type, the function
+// returns \a true in case all column elements are 0 and \a false in case any vector element is
+// not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::CompressedMatrix<double,columnMajor> A;
+ // ... Resizing and initialization
+ if( isDefault( column( A, 0UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+inline bool isDefault( const Column<MT,SO,false,SF>& column )
+{
+ typedef ConstIterator_< Column<MT,SO,false,SF> > ConstIterator;
+
+ const ConstIterator end( column.end() );
+ for( ConstIterator element=column.begin(); element!=end; ++element )
+ if( !isDefault( element->value() ) ) return false;
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given column are intact.
+// \ingroup column
+//
+// \param column The column to be tested.
+// \return \a true in case the given column's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the column are intact, i.e. if its state is
+// valid. In case the invariants are intact, the function returns \a true, else it will return
+// \a false. The following example demonstrates the use of the \a isIntact() function:
+
+ \code
+ blaze::DynamicMatrix<int,columnMajor> A;
+ // ... Resizing and initialization
+ if( isIntact( column( A, 0UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline bool isIntact( const Column<MT,SO,DF,SF>& column ) noexcept
+{
+ return ( column.col_ <= column.matrix_.columns() &&
+ isIntact( column.matrix_ ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the two given columns represent the same observable state.
+// \ingroup column
+//
+// \param a The first column to be tested for its state.
+// \param b The second column to be tested for its state.
+// \return \a true in case the two columns share a state, \a false otherwise.
+//
+// This overload of the isSame function tests if the two given columns refer to exactly the
+// same range of the same matrix. In case both columns represent the same observable state,
+// the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline bool isSame( const Column<MT,SO,DF,SF>& a, const Column<MT,SO,DF,SF>& b ) noexcept
+{
+ return ( isSame( a.matrix_, b.matrix_ ) && ( a.col_ == b.col_ ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a vector to a column.
+// \ingroup column
+//
+// \param lhs The target left-hand side column.
+// \param rhs The right-hand side vector to be assigned.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryAssign( const Column<MT,SO,DF,SF>& lhs, const Vector<VT,false>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryAssign( lhs.matrix_, ~rhs, index, lhs.col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a column.
+// \ingroup column
+//
+// \param lhs The target left-hand side column.
+// \param rhs The right-hand side vector to be added.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryAddAssign( const Column<MT,SO,DF,SF>& lhs, const Vector<VT,false>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryAddAssign( lhs.matrix_, ~rhs, index, lhs.col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a column.
+// \ingroup column
+//
+// \param lhs The target left-hand side column.
+// \param rhs The right-hand side vector to be subtracted.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool trySubAssign( const Column<MT,SO,DF,SF>& lhs, const Vector<VT,false>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return trySubAssign( lhs.matrix_, ~rhs, index, lhs.col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to a column.
+// \ingroup column
+//
+// \param lhs The target left-hand side column.
+// \param rhs The right-hand side vector to be multiplied.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryMultAssign( const Column<MT,SO,DF,SF>& lhs, const Vector<VT,false>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryMultAssign( lhs.matrix_, ~rhs, index, lhs.col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the division assignment of a vector to a column.
+// \ingroup column
+//
+// \param lhs The target left-hand side column.
+// \param rhs The right-hand side vector divisor.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryDivAssign( const Column<MT,SO,DF,SF>& lhs, const Vector<VT,false>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryDivAssign( lhs.matrix_, ~rhs, index, lhs.col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removal of all restrictions on the data access to the given column.
+// \ingroup column
+//
+// \param column The column to be derestricted.
+// \return Column without access restrictions.
+//
+// This function removes all restrictions on the data access to the given column. It returns a
+// column object that does provide the same interface but does not have any restrictions on the
+// data access.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline DerestrictTrait_< Column<MT,SO,DF,SF> > derestrict( Column<MT,SO,DF,SF>& column )
+{
+ typedef DerestrictTrait_< Column<MT,SO,DF,SF> > ReturnType;
+ return ReturnType( derestrict( column.matrix_ ), column.col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsRestricted< Column<MT,SO,DF,SF> > : public BoolConstant< IsRestricted<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF >
+struct DerestrictTrait< Column<MT,SO,DF,SF> >
+{
+ using Type = Column< RemoveReference_< DerestrictTrait_<MT> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool SF >
+struct HasConstDataAccess< Column<MT,SO,true,SF> >
+ : public BoolConstant< HasConstDataAccess<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool SF >
+struct HasMutableDataAccess< Column<MT,SO,true,SF> >
+ : public BoolConstant< HasMutableDataAccess<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool SF >
+struct IsAligned< Column<MT,SO,true,SF> >
+ : public BoolConstant< And< IsAligned<MT>, Or< IsColumnMajorMatrix<MT>, IsSymmetric<MT> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool SF >
+struct IsPadded< Column<MT,SO,true,SF> >
+ : public BoolConstant< And< IsPadded<MT>, Or< IsColumnMajorMatrix<MT>, IsSymmetric<MT> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISOPPOSEDVIEW SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool DF >
+struct IsOpposedView< Column<MT,false,DF,false> >
+ : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct AddTrait< Column<MT,SO,DF,SF>, T >
+{
+ using Type = AddTrait_< ColumnTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct AddTrait< T, Column<MT,SO,DF,SF> >
+{
+ using Type = AddTrait_< T, ColumnTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct SubTrait< Column<MT,SO,DF,SF>, T >
+{
+ using Type = SubTrait_< ColumnTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct SubTrait< T, Column<MT,SO,DF,SF> >
+{
+ using Type = SubTrait_< T, ColumnTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct MultTrait< Column<MT,SO,DF,SF>, T >
+{
+ using Type = MultTrait_< ColumnTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct MultTrait< T, Column<MT,SO,DF,SF> >
+{
+ using Type = MultTrait_< T, ColumnTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CROSSTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct CrossTrait< Column<MT,SO,DF,SF>, T >
+{
+ using Type = CrossTrait_< ColumnTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct CrossTrait< T, Column<MT,SO,DF,SF> >
+{
+ using Type = CrossTrait_< T, ColumnTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct DivTrait< Column<MT,SO,DF,SF>, T >
+{
+ using Type = DivTrait_< ColumnTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct DivTrait< T, Column<MT,SO,DF,SF> >
+{
+ using Type = DivTrait_< T, ColumnTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF >
+struct SubvectorTrait< Column<MT,SO,DF,SF> >
+{
+ using Type = SubvectorTrait_< ResultType_< Column<MT,SO,DF,SF> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/Forward.h b/src/cpu/blaze/math/views/Forward.h
new file mode 100644
index 00000000..5ec5847d
--- /dev/null
+++ b/src/cpu/blaze/math/views/Forward.h
@@ -0,0 +1,54 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/Forward.h
+// \brief Header file for all forward declarations for views
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_FORWARD_H_
+#define _BLAZE_MATH_VIEWS_FORWARD_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+template< typename, bool, bool, bool > class Column;
+template< typename, bool, bool, bool > class Row;
+template< typename, bool, bool, bool > class Submatrix;
+template< typename, bool, bool, bool > class Subvector;
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/Row.h b/src/cpu/blaze/math/views/Row.h
new file mode 100644
index 00000000..9c8cba34
--- /dev/null
+++ b/src/cpu/blaze/math/views/Row.h
@@ -0,0 +1,1072 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/Row.h
+// \brief Header file for the implementation of the Row view
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_ROW_H_
+#define _BLAZE_MATH_VIEWS_ROW_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowExprTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsMatEvalExpr.h>
+#include <blaze/math/typetraits/IsMatForEachExpr.h>
+#include <blaze/math/typetraits/IsMatMatAddExpr.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsMatMatSubExpr.h>
+#include <blaze/math/typetraits/IsMatScalarDivExpr.h>
+#include <blaze/math/typetraits/IsMatScalarMultExpr.h>
+#include <blaze/math/typetraits/IsMatSerialExpr.h>
+#include <blaze/math/typetraits/IsMatTransExpr.h>
+#include <blaze/math/typetraits/IsOpposedView.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/typetraits/IsVecTVecMultExpr.h>
+#include <blaze/math/views/row/BaseTemplate.h>
+#include <blaze/math/views/row/Dense.h>
+#include <blaze/math/views/row/Sparse.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL FUNCTION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific row of the given matrix.
+// \ingroup views
+//
+// \param matrix The matrix containing the row.
+// \param index The index of the row.
+// \return View on the specified row of the matrix.
+// \exception std::invalid_argument Invalid row access index.
+//
+// This function returns an expression representing the specified row of the given matrix.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> DenseMatrix;
+ typedef blaze::CompressedMatrix<double,rowMajor> SparseMatrix;
+
+ DenseMatrix D;
+ SparseMatrix S;
+ // ... Resizing and initialization
+
+ // Creating a view on the 3rd row of the dense matrix D
+ blaze::Row<DenseMatrix> = row( D, 3UL );
+
+ // Creating a view on the 4th row of the sparse matrix S
+ blaze::Row<SparseMatrix> = row( S, 4UL );
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline DisableIf_< Or< IsComputation<MT>, IsTransExpr<MT> >, RowExprTrait_<MT> >
+ row( Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return RowExprTrait_<MT>( ~matrix, index );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific row of the given constant matrix.
+// \ingroup views
+//
+// \param matrix The constant matrix containing the row.
+// \param index The index of the row.
+// \return View on the specified row of the matrix.
+// \exception std::invalid_argument Invalid row access index.
+//
+// This function returns an expression representing the specified row of the given matrix.
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> DenseMatrix;
+ typedef blaze::CompressedMatrix<double,rowMajor> SparseMatrix;
+
+ DenseMatrix D;
+ SparseMatrix S;
+ // ... Resizing and initialization
+
+ // Creating a view on the 3rd row of the dense matrix D
+ blaze::Row<DenseMatrix> = row( D, 3UL );
+
+ // Creating a view on the 4th row of the sparse matrix S
+ blaze::Row<SparseMatrix> = row( S, 4UL );
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline DisableIf_< Or< IsComputation<MT>, IsTransExpr<MT> >, RowExprTrait_<const MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return RowExprTrait_<const MT>( ~matrix, index );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix/matrix addition.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix addition.
+// \param index The index of the row.
+// \return View on the specified row of the addition.
+//
+// This function returns an expression representing the specified row of the given matrix/matrix
+// addition.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatAddExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return row( (~matrix).leftOperand(), index ) + row( (~matrix).rightOperand(), index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix/matrix subtraction.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix subtraction.
+// \param index The index of the row.
+// \return View on the specified row of the subtraction.
+//
+// This function returns an expression representing the specified row of the given matrix/matrix
+// subtraction.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatSubExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return row( (~matrix).leftOperand(), index ) - row( (~matrix).rightOperand(), index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix/matrix multiplication.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix multiplication.
+// \param index The index of the row.
+// \return View on the specified row of the multiplication.
+//
+// This function returns an expression representing the specified row of the given matrix/matrix
+// multiplication.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatMultExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return row( (~matrix).leftOperand(), index ) * (~matrix).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given outer product.
+// \ingroup views
+//
+// \param matrix The constant outer product.
+// \param index The index of the row.
+// \return View on the specified row of the outer product.
+//
+// This function returns an expression representing the specified row of the given outer product.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsVecTVecMultExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return (~matrix).leftOperand()[index] * (~matrix).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix/scalar multiplication.
+// \ingroup views
+//
+// \param matrix The constant matrix/scalar multiplication.
+// \param index The index of the row.
+// \return View on the specified row of the multiplication.
+//
+// This function returns an expression representing the specified row of the given matrix/scalar
+// multiplication.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatScalarMultExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return row( (~matrix).leftOperand(), index ) * (~matrix).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix/scalar division.
+// \ingroup views
+//
+// \param matrix The constant matrix/scalar division.
+// \param index The index of the row.
+// \return View on the specified row of the division.
+//
+// This function returns an expression representing the specified row of the given matrix/scalar
+// division.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatScalarDivExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return row( (~matrix).leftOperand(), index ) / (~matrix).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix custom operation.
+// \ingroup views
+//
+// \param matrix The constant matrix custom operation.
+// \param index The index of the row.
+// \return View on the specified row of the custom operation.
+//
+// This function returns an expression representing the specified row of the given matrix
+// custom operation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatForEachExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return forEach( row( (~matrix).operand(), index ), (~matrix).operation() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix evaluation operation.
+// \ingroup views
+//
+// \param matrix The constant matrix evaluation operation.
+// \param index The index of the row.
+// \return View on the specified row of the evaluation operation.
+//
+// This function returns an expression representing the specified row of the given matrix
+// evaluation operation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatEvalExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return eval( row( (~matrix).operand(), index ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix serialization operation.
+// \ingroup views
+//
+// \param matrix The constant matrix serialization operation.
+// \param index The index of the row.
+// \return View on the specified row of the serialization operation.
+//
+// This function returns an expression representing the specified row of the given matrix
+// serialization operation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatSerialExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return serial( row( (~matrix).operand(), index ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific row of the given matrix transpose operation.
+// \ingroup views
+//
+// \param matrix The constant matrix transpose operation.
+// \param index The index of the row.
+// \return View on the specified row of the transpose operation.
+//
+// This function returns an expression representing the specified row of the given matrix
+// transpose operation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatTransExpr<MT>, RowExprTrait_<MT> >
+ row( const Matrix<MT,SO>& matrix, size_t index )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return trans( column( (~matrix).operand(), index ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// ROW OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Row operators */
+//@{
+template< typename MT, bool SO, bool DF, bool SF >
+inline void reset( Row<MT,SO,DF,SF>& row );
+
+template< typename MT, bool SO, bool DF, bool SF >
+inline void clear( Row<MT,SO,DF,SF>& row );
+
+template< typename MT, bool SO, bool DF, bool SF >
+inline bool isDefault( const Row<MT,SO,DF,SF>& row );
+
+template< typename MT, bool SO, bool DF, bool SF >
+inline bool isIntact( const Row<MT,SO,DF,SF>& row ) noexcept;
+
+template< typename MT, bool SO, bool DF, bool SF >
+inline bool isSame( const Row<MT,SO,DF,SF>& a, const Row<MT,SO,DF,SF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given row.
+// \ingroup row
+//
+// \param row The row to be resetted.
+// \return void
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline void reset( Row<MT,SO,DF,SF>& row )
+{
+ row.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given row.
+// \ingroup row
+//
+// \param row The row to be cleared.
+// \return void
+//
+// Clearing a row is equivalent to resetting it via the reset() function.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline void clear( Row<MT,SO,DF,SF>& row )
+{
+ row.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given row is in default state.
+// \ingroup row
+//
+// \param row The row to be tested for its default state.
+// \return \a true in case the given row is component-wise zero, \a false otherwise.
+//
+// This function checks whether the row is in default state. For instance, in case the row
+// is instantiated for a built-in integral or floating point data type, the function returns
+// \a true in case all row elements are 0 and \a false in case any row element is not 0. The
+// following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::DynamicMatrix<int,rowMajor> A;
+ // ... Resizing and initialization
+ if( isDefault( row( A, 0UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline bool isDefault( const Row<MT,SO,DF,SF>& row )
+{
+ for( size_t i=0UL; i<row.size(); ++i )
+ if( !isDefault( row[i] ) ) return false;
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given sparse row is in default state.
+// \ingroup sparse_row
+//
+// \param row The sparse row to be tested for its default state.
+// \return \a true in case the given row is component-wise zero, \a false otherwise.
+//
+// This function checks whether the sparse row is in default state. For instance, in case the
+// row is instantiated for a built-in integral or floating point data type, the function returns
+// \a true in case all row elements are 0 and \a false in case any vector element is not 0. The
+// following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::CompressedMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ if( isDefault( row( A, 0UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SO // Storage order
+ , bool SF > // Symmetry flag
+inline bool isDefault( const Row<MT,SO,false,SF>& row )
+{
+ typedef ConstIterator_< Row<MT,SO,false,SF> > ConstIterator;
+
+ const ConstIterator end( row.end() );
+ for( ConstIterator element=row.begin(); element!=end; ++element )
+ if( !isDefault( element->value() ) ) return false;
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given row are intact.
+// \ingroup row
+//
+// \param row The row to be tested.
+// \return \a true in case the given row's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the row are intact, i.e. if its state is valid.
+// In case the invariants are intact, the function returns \a true, else it will return \a false.
+// The following example demonstrates the use of the \a isIntact() function:
+
+ \code
+ blaze::DynamicMatrix<int,rowMajor> A;
+ // ... Resizing and initialization
+ if( isIntact( row( A, 0UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline bool isIntact( const Row<MT,SO,DF,SF>& row ) noexcept
+{
+ return ( row.row_ <= row.matrix_.rows() &&
+ isIntact( row.matrix_ ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the two given rows represent the same observable state.
+// \ingroup row
+//
+// \param a The first row to be tested for its state.
+// \param b The second row to be tested for its state.
+// \return \a true in case the two rows share a state, \a false otherwise.
+//
+// This overload of the isSame function tests if the two given rows refer to exactly the same
+// range of the same matrix. In case both rows represent the same observable state, the function
+// returns \a true, otherwise it returns \a false.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline bool isSame( const Row<MT,SO,DF,SF>& a, const Row<MT,SO,DF,SF>& b ) noexcept
+{
+ return ( isSame( a.matrix_, b.matrix_ ) && ( a.row_ == b.row_ ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a vector to a row.
+// \ingroup row
+//
+// \param lhs The target left-hand side row.
+// \param rhs The right-hand side vector to be assigned.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryAssign( const Row<MT,SO,DF,SF>& lhs, const Vector<VT,true>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryAssign( lhs.matrix_, ~rhs, lhs.row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a row.
+// \ingroup row
+//
+// \param lhs The target left-hand side row.
+// \param rhs The right-hand side vector to be added.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryAddAssign( const Row<MT,SO,DF,SF>& lhs, const Vector<VT,true>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryAddAssign( lhs.matrix_, ~rhs, lhs.row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a row.
+// \ingroup row
+//
+// \param lhs The target left-hand side row.
+// \param rhs The right-hand side vector to be subtracted.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool trySubAssign( const Row<MT,SO,DF,SF>& lhs, const Vector<VT,true>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return trySubAssign( lhs.matrix_, ~rhs, lhs.row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to a row.
+// \ingroup row
+//
+// \param lhs The target left-hand side row.
+// \param rhs The right-hand side vector to be multiplied.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryMultAssign( const Row<MT,SO,DF,SF>& lhs, const Vector<VT,true>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryMultAssign( lhs.matrix_, ~rhs, lhs.row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the division assignment of a vector to a row.
+// \ingroup row
+//
+// \param lhs The target left-hand side row.
+// \param rhs The right-hand side vector divisor.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF // Symmetry flag
+ , typename VT > // Type of the right-hand side vector
+inline bool tryDivAssign( const Row<MT,SO,DF,SF>& lhs, const Vector<VT,true>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryDivAssign( lhs.matrix_, ~rhs, lhs.row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removal of all restrictions on the data access to the given row.
+// \ingroup row
+//
+// \param row The row to be derestricted.
+// \return Row without access restrictions.
+//
+// This function removes all restrictions on the data access to the given row. It returns a row
+// object that does provide the same interface but does not have any restrictions on the data
+// access.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the matrix
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , bool SF > // Symmetry flag
+inline DerestrictTrait_< Row<MT,SO,DF,SF> > derestrict( Row<MT,SO,DF,SF>& row )
+{
+ typedef DerestrictTrait_< Row<MT,SO,DF,SF> > ReturnType;
+ return ReturnType( derestrict( row.matrix_ ), row.row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF >
+struct IsRestricted< Row<MT,SO,DF,SF> >
+ : public BoolConstant< IsRestricted<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF >
+struct DerestrictTrait< Row<MT,SO,DF,SF> >
+{
+ using Type = Row< RemoveReference_< DerestrictTrait_<MT> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool SF >
+struct HasConstDataAccess< Row<MT,SO,true,SF> >
+ : public BoolConstant< HasConstDataAccess<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool SF >
+struct HasMutableDataAccess< Row<MT,SO,true,SF> >
+ : public BoolConstant< HasMutableDataAccess<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool SF >
+struct IsAligned< Row<MT,SO,true,SF> >
+ : public BoolConstant< And< IsAligned<MT>, Or< IsRowMajorMatrix<MT>, IsSymmetric<MT> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISPADDED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool SF >
+struct IsPadded< Row<MT,SO,true,SF> >
+ : public BoolConstant< And< IsPadded<MT>, Or< IsRowMajorMatrix<MT>, IsSymmetric<MT> > >::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISOPPOSEDVIEW SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool DF >
+struct IsOpposedView< Row<MT,false,DF,false> >
+ : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct AddTrait< Row<MT,SO,DF,SF>, T >
+{
+ using Type = AddTrait_< RowTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct AddTrait< T, Row<MT,SO,DF,SF> >
+{
+ using Type = AddTrait_< T, RowTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct SubTrait< Row<MT,SO,DF,SF>, T >
+{
+ using Type = SubTrait_< RowTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct SubTrait< T, Row<MT,SO,DF,SF> >
+{
+ using Type = SubTrait_< T, RowTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct MultTrait< Row<MT,SO,DF,SF>, T >
+{
+ using Type = MultTrait_< RowTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct MultTrait< T, Row<MT,SO,DF,SF> >
+{
+ using Type = MultTrait_< T, RowTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CROSSTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct CrossTrait< Row<MT,SO,DF,SF>, T >
+{
+ using Type = CrossTrait_< RowTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct CrossTrait< T, Row<MT,SO,DF,SF> >
+{
+ using Type = CrossTrait_< T, RowTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF, typename T >
+struct DivTrait< Row<MT,SO,DF,SF>, T >
+{
+ using Type = DivTrait_< RowTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool SO, bool DF, bool SF >
+struct DivTrait< T, Row<MT,SO,DF,SF> >
+{
+ using Type = DivTrait_< T, RowTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO, bool DF, bool SF >
+struct SubvectorTrait< Row<MT,SO,DF,SF> >
+{
+ using Type = SubvectorTrait_< ResultType_< Row<MT,SO,DF,SF> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/Submatrix.h b/src/cpu/blaze/math/views/Submatrix.h
new file mode 100644
index 00000000..5444f59d
--- /dev/null
+++ b/src/cpu/blaze/math/views/Submatrix.h
@@ -0,0 +1,2159 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/Submatrix.h
+// \brief Header file for the implementation of the Submatrix view
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_SUBMATRIX_H_
+#define _BLAZE_MATH_VIEWS_SUBMATRIX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/MutableDataAccess.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/expressions/Matrix.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InversionFlag.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubmatrixExprTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsMatEvalExpr.h>
+#include <blaze/math/typetraits/IsMatForEachExpr.h>
+#include <blaze/math/typetraits/IsMatMatAddExpr.h>
+#include <blaze/math/typetraits/IsMatMatMultExpr.h>
+#include <blaze/math/typetraits/IsMatMatSubExpr.h>
+#include <blaze/math/typetraits/IsMatScalarDivExpr.h>
+#include <blaze/math/typetraits/IsMatScalarMultExpr.h>
+#include <blaze/math/typetraits/IsMatSerialExpr.h>
+#include <blaze/math/typetraits/IsMatTransExpr.h>
+#include <blaze/math/typetraits/IsMatVecMultExpr.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/typetraits/IsTVecMatMultExpr.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/IsVecTVecMultExpr.h>
+#include <blaze/math/views/submatrix/BaseTemplate.h>
+#include <blaze/math/views/submatrix/Dense.h>
+#include <blaze/math/views/submatrix/Sparse.h>
+#include <blaze/math/views/Subvector.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL FUNCTION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific submatrix of the given matrix.
+// \ingroup views
+//
+// \param matrix The matrix containing the submatrix.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specific submatrix of the matrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// This function returns an expression representing the specified submatrix of the given matrix.
+// The following example demonstrates the creation of a dense and sparse submatrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> DenseMatrix;
+ typedef blaze::CompressedMatrix<int,columnMajor> SparseMatrix;
+
+ DenseMatrix D;
+ SparseMatrix S;
+ // ... Resizing and initialization
+
+ // Creating a dense submatrix of size 8x4, starting in row 0 and column 16
+ blaze::Submatrix<DenseMatrix> dsm = submatrix( D, 0UL, 16UL, 8UL, 4UL );
+
+ // Creating a sparse submatrix of size 7x3, starting in row 2 and column 4
+ blaze::Submatrix<SparseMatrix> ssm = submatrix( S, 2UL, 4UL, 7UL, 3UL );
+ \endcode
+
+// In case the submatrix is not properly specified (i.e. if the specified row or column is larger
+// than the total number of rows or columns of the given matrix or the submatrix is specified
+// beyond the number of rows or columns of the matrix) a \a std::invalid_argument exception is
+// thrown.
+//
+// Please note that this function creates an unaligned dense or sparse submatrix. For instance,
+// the creation of the dense submatrix is equivalent to the following three function calls:
+
+ \code
+ blaze::Submatrix<DenseMatrix> dsm = submatrix<unaligned>( D, 0UL, 16UL, 8UL, 4UL );
+ blaze::Submatrix<DenseMatrix,unaligned> dsm = submatrix ( D, 0UL, 16UL, 8UL, 4UL );
+ blaze::Submatrix<DenseMatrix,unaligned> dsm = submatrix<unaligned>( D, 0UL, 16UL, 8UL, 4UL );
+ \endcode
+
+// In contrast to unaligned submatrices, which provide full flexibility, aligned submatrices pose
+// additional alignment restrictions. However, especially in case of dense submatrices this may
+// result in considerable performance improvements. In order to create an aligned submatrix the
+// following function call has to be used:
+
+ \code
+ blaze::Submatrix<DenseMatrix,aligned> dsm = submatrix<aligned>( D, 0UL, 16UL, 8UL, 4UL );
+ \endcode
+
+// Note however that in this case the given arguments \a row, \a columns, \a m, and \a n are
+// subject to additional checks to guarantee proper alignment.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline SubmatrixExprTrait_<MT,unaligned>
+ submatrix( Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return submatrix<unaligned>( ~matrix, row, column, m, n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific submatrix of the given matrix.
+// \ingroup views
+//
+// \param matrix The matrix containing the submatrix.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specific submatrix of the matrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// This function returns an expression representing the specified submatrix of the given matrix.
+// The following example demonstrates the creation of a dense and sparse submatrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> DenseMatrix;
+ typedef blaze::CompressedMatrix<int,columnMajor> SparseMatrix;
+
+ DenseMatrix D;
+ SparseMatrix S;
+ // ... Resizing and initialization
+
+ // Creating a dense submatrix of size 8x4, starting in row 0 and column 16
+ blaze::Submatrix<DenseMatrix> dsm = submatrix( D, 0UL, 16UL, 8UL, 4UL );
+
+ // Creating a sparse submatrix of size 7x3, starting in row 2 and column 4
+ blaze::Submatrix<SparseMatrix> ssm = submatrix( S, 2UL, 4UL, 7UL, 3UL );
+ \endcode
+
+// In case the submatrix is not properly specified (i.e. if the specified row or column is larger
+// than the total number of rows or columns of the given matrix or the submatrix is specified
+// beyond the number of rows or columns of the matrix) a \a std::invalid_argument exception is
+// thrown.
+//
+// Please note that this function creates an unaligned dense or sparse submatrix. For instance,
+// the creation of the dense submatrix is equivalent to the following three function calls:
+
+ \code
+ blaze::Submatrix<DenseMatrix> dsm = submatrix<unaligned>( D, 0UL, 16UL, 8UL, 4UL );
+ blaze::Submatrix<DenseMatrix,unaligned> dsm = submatrix ( D, 0UL, 16UL, 8UL, 4UL );
+ blaze::Submatrix<DenseMatrix,unaligned> dsm = submatrix<unaligned>( D, 0UL, 16UL, 8UL, 4UL );
+ \endcode
+
+// In contrast to unaligned submatrices, which provide full flexibility, aligned submatrices pose
+// additional alignment restrictions. However, especially in case of dense submatrices this may
+// result in considerable performance improvements. In order to create an aligned submatrix the
+// following function call has to be used:
+
+ \code
+ blaze::Submatrix<DenseMatrix,aligned> dsm = submatrix<aligned>( D, 0UL, 16UL, 8UL, 4UL );
+ \endcode
+
+// Note however that in this case the given arguments \a row, \a columns, \a m, and \a n are
+// subject to additional checks to guarantee proper alignment.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline SubmatrixExprTrait_<const MT,unaligned>
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return submatrix<unaligned>( ~matrix, row, column, m, n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific submatrix of the given matrix.
+// \ingroup views
+//
+// \param matrix The matrix containing the submatrix.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specific submatrix of the matrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// This function returns an expression representing an aligned or unaligned submatrix of the
+// given dense or sparse matrix, based on the specified alignment flag \a AF. The following
+// example demonstrates the creation of both an aligned and unaligned submatrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> DenseMatrix;
+ typedef blaze::CompressedMatrix<int,columnMajor> SparseMatrix;
+
+ DenseMatrix D;
+ SparseMatrix S;
+ // ... Resizing and initialization
+
+ // Creating an aligned dense submatrix of size 8x4, starting in row 0 and column 16
+ blaze::Submatrix<DenseMatrix,aligned> dsm = submatrix<aligned>( D, 0UL, 16UL, 8UL, 4UL );
+
+ // Creating an unaligned sparse submatrix of size 7x3, starting in row 2 and column 4
+ blaze::Submatrix<SparseMatrix,unaligned> ssm = submatrix<unaligned>( S, 2UL, 4UL, 7UL, 3UL );
+ \endcode
+
+// In case the submatrix is not properly specified (i.e. if the specified row or column is larger
+// than the total number of rows or columns of the given matrix or the submatrix is specified
+// beyond the number of rows or columns of the matrix) a \a std::invalid_argument exception is
+// thrown.
+//
+// In contrast to unaligned submatrices, which provide full flexibility, aligned submatrices pose
+// additional alignment restrictions and the given \a row, and \a column arguments are subject to
+// additional checks to guarantee proper alignment. However, especially in case of dense submatrices
+// this may result in considerable performance improvements.
+//
+// The alignment restrictions refer to system dependent address restrictions for the used element
+// type and the available vectorization mode (SSE, AVX, ...). In order to be properly aligned the
+// first element of each row/column of the submatrix must be aligned. The following source code
+// gives some examples for a double precision row-major dynamic matrix, assuming that padding is
+// enabled and that AVX is available, which packs 4 \c double values into a SIMD vector:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType,aligned> SubmatrixType;
+
+ MatrixType D( 13UL, 17UL );
+ // ... Resizing and initialization
+
+ // OK: Starts at position (0,0), i.e. the first element of each row is aligned (due to padding)
+ SubmatrixType dsm1 = submatrix<aligned>( D, 0UL, 0UL, 7UL, 11UL );
+
+ // OK: First column is a multiple of 4, i.e. the first element of each row is aligned (due to padding)
+ SubmatrixType dsm2 = submatrix<aligned>( D, 3UL, 12UL, 8UL, 16UL );
+
+ // OK: First column is a multiple of 4 and the submatrix includes the last row and column
+ SubmatrixType dsm3 = submatrix<aligned>( D, 4UL, 0UL, 9UL, 17UL );
+
+ // Error: First column is not a multiple of 4, i.e. the first element is not aligned
+ SubmatrixType dsm4 = submatrix<aligned>( D, 2UL, 3UL, 12UL, 12UL );
+ \endcode
+
+// In case any alignment restrictions are violated, a \a std::invalid_argument exception is thrown.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline DisableIf_< Or< IsComputation<MT>, IsTransExpr<MT> >, SubmatrixExprTrait_<MT,AF> >
+ submatrix( Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SubmatrixExprTrait_<MT,AF>( ~matrix, row, column, m, n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific submatrix of the given matrix.
+// \ingroup views
+//
+// \param matrix The matrix containing the submatrix.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specific submatrix of the matrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// This function returns an expression representing an aligned or unaligned submatrix of the
+// given dense or sparse matrix, based on the specified alignment flag \a AF. The following
+// example demonstrates the creation of both an aligned and unaligned submatrix:
+
+ \code
+ using blaze::rowMajor;
+ using blaze::columnMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> DenseMatrix;
+ typedef blaze::CompressedMatrix<int,columnMajor> SparseMatrix;
+
+ DenseMatrix D;
+ SparseMatrix S;
+ // ... Resizing and initialization
+
+ // Creating an aligned dense submatrix of size 8x4, starting in row 0 and column 16
+ blaze::Submatrix<DenseMatrix,aligned> dsm = submatrix<aligned>( D, 0UL, 16UL, 8UL, 4UL );
+
+ // Creating an unaligned sparse submatrix of size 7x3, starting in row 2 and column 4
+ blaze::Submatrix<SparseMatrix,unaligned> ssm = submatrix<unaligned>( S, 2UL, 4UL, 7UL, 3UL );
+ \endcode
+
+// In case the submatrix is not properly specified (i.e. if the specified row or column is larger
+// than the total number of rows or columns of the given matrix or the submatrix is specified
+// beyond the number of rows or columns of the matrix) a \a std::invalid_argument exception is
+// thrown.
+//
+// In contrast to unaligned submatrices, which provide full flexibility, aligned submatrices pose
+// additional alignment restrictions and the given \a row, and \a column arguments are subject to
+// additional checks to guarantee proper alignment. However, especially in case of dense submatrices
+// this may result in considerable performance improvements.
+//
+// The alignment restrictions refer to system dependent address restrictions for the used element
+// type and the available vectorization mode (SSE, AVX, ...). In order to be properly aligned the
+// first element of each row/column of the submatrix must be aligned. The following source code
+// gives some examples for a double precision row-major dynamic matrix, assuming that padding is
+// enabled and that AVX is available, which packs 4 \c double values into a SIMD vector:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::DynamicMatrix<double,rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType,aligned> SubmatrixType;
+
+ MatrixType D( 13UL, 17UL );
+ // ... Resizing and initialization
+
+ // OK: Starts at position (0,0), i.e. the first element of each row is aligned (due to padding)
+ SubmatrixType dsm1 = submatrix<aligned>( D, 0UL, 0UL, 7UL, 11UL );
+
+ // OK: First column is a multiple of 4, i.e. the first element of each row is aligned (due to padding)
+ SubmatrixType dsm2 = submatrix<aligned>( D, 3UL, 12UL, 8UL, 16UL );
+
+ // OK: First column is a multiple of 4 and the submatrix includes the last row and column
+ SubmatrixType dsm3 = submatrix<aligned>( D, 4UL, 0UL, 9UL, 17UL );
+
+ // Error: First column is not a multiple of 4, i.e. the first element is not aligned
+ SubmatrixType dsm4 = submatrix<aligned>( D, 2UL, 3UL, 12UL, 12UL );
+ \endcode
+
+// In case any alignment restrictions are violated, a \a std::invalid_argument exception is thrown.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the dense matrix
+ , bool SO > // Storage order
+inline DisableIf_< Or< IsComputation<MT>, IsTransExpr<MT> >, SubmatrixExprTrait_<const MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SubmatrixExprTrait_<const MT,AF>( ~matrix, row, column, m, n );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given matrix/vector multiplication.
+// \ingroup views
+//
+// \param vector The constant matrix/vector multiplication.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the multiplication.
+//
+// This function returns an expression representing the specified subvector of the given
+// matrix/vector multiplication.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsMatVecMultExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef RemoveReference_< LeftOperand_<VT> > MT;
+
+ LeftOperand_<VT> left ( (~vector).leftOperand() );
+ RightOperand_<VT> right( (~vector).rightOperand() );
+
+ const size_t column( ( IsUpper<MT>::value )
+ ?( ( !AF && IsStrictlyUpper<MT>::value )?( index + 1UL ):( index ) )
+ :( 0UL ) );
+ const size_t n( ( IsLower<MT>::value )
+ ?( ( IsUpper<MT>::value )?( size )
+ :( ( IsStrictlyLower<MT>::value && size > 0UL )
+ ?( index + size - 1UL )
+ :( index + size ) ) )
+ :( ( IsUpper<MT>::value )?( left.columns() - column )
+ :( left.columns() ) ) );
+
+ return submatrix<AF>( left, index, column, size, n ) * subvector<AF>( right, column, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector/matrix multiplication.
+// \ingroup views
+//
+// \param vector The constant vector/matrix multiplication.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the multiplication.
+//
+// This function returns an expression representing the specified subvector of the given
+// vector/matrix multiplication.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsTVecMatMultExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef RemoveReference_< RightOperand_<VT> > MT;
+
+ LeftOperand_<VT> left ( (~vector).leftOperand() );
+ RightOperand_<VT> right( (~vector).rightOperand() );
+
+ const size_t row( ( IsLower<MT>::value )
+ ?( ( !AF && IsStrictlyLower<MT>::value )?( index + 1UL ):( index ) )
+ :( 0UL ) );
+ const size_t m( ( IsUpper<MT>::value )
+ ?( ( IsLower<MT>::value )?( size )
+ :( ( IsStrictlyUpper<MT>::value && size > 0UL )
+ ?( index + size - 1UL )
+ :( index + size ) ) )
+ :( ( IsLower<MT>::value )?( right.rows() - row )
+ :( right.rows() ) ) );
+
+ return subvector<AF>( left, row, m ) * submatrix<AF>( right, row, index, m, size );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix/matrix addition.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix addition.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the addition.
+//
+// This function returns an expression representing the specified submatrix of the given
+// matrix/matrix addition.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatAddExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return submatrix<AF>( (~matrix).leftOperand() , row, column, m, n ) +
+ submatrix<AF>( (~matrix).rightOperand(), row, column, m, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix/matrix subtraction.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix subtraction.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the subtraction.
+//
+// This function returns an expression representing the specified submatrix of the given
+// matrix/matrix subtraction.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatSubExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return submatrix<AF>( (~matrix).leftOperand() , row, column, m, n ) -
+ submatrix<AF>( (~matrix).rightOperand(), row, column, m, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix/matrix multiplication.
+// \ingroup views
+//
+// \param matrix The constant matrix/matrix multiplication.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the multiplication.
+//
+// This function returns an expression representing the specified submatrix of the given
+// matrix/matrix multiplication.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatMatMultExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ typedef RemoveReference_< LeftOperand_<MT> > MT1;
+ typedef RemoveReference_< RightOperand_<MT> > MT2;
+
+ LeftOperand_<MT> left ( (~matrix).leftOperand() );
+ RightOperand_<MT> right( (~matrix).rightOperand() );
+
+ const size_t begin( max( ( IsUpper<MT1>::value )
+ ?( ( !AF && IsStrictlyUpper<MT1>::value )?( row + 1UL ):( row ) )
+ :( 0UL )
+ , ( IsLower<MT2>::value )
+ ?( ( !AF && IsStrictlyLower<MT2>::value )?( column + 1UL ):( column ) )
+ :( 0UL ) ) );
+ const size_t end( min( ( IsLower<MT1>::value )
+ ?( ( IsStrictlyLower<MT1>::value && m > 0UL )?( row + m - 1UL ):( row + m ) )
+ :( left.columns() )
+ , ( IsUpper<MT2>::value )
+ ?( ( IsStrictlyUpper<MT2>::value && n > 0UL )?( column + n - 1UL ):( column + n ) )
+ :( left.columns() ) ) );
+
+ const size_t diff( ( begin < end )?( end - begin ):( 0UL ) );
+
+ return submatrix<AF>( left, row, begin, m, diff ) *
+ submatrix<AF>( right, begin, column, diff, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given outer product.
+// \ingroup views
+//
+// \param matrix The constant outer product.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the outer product.
+//
+// This function returns an expression representing the specified submatrix of the given
+// outer product.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsVecTVecMultExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<AF>( (~matrix).leftOperand(), row, m ) *
+ subvector<AF>( (~matrix).rightOperand(), column, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix/scalar multiplication.
+// \ingroup views
+//
+// \param matrix The constant matrix/scalar multiplication.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the multiplication.
+//
+// This function returns an expression representing the specified submatrix of the given
+// matrix/scalar multiplication.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatScalarMultExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return submatrix<AF>( (~matrix).leftOperand(), row, column, m, n ) * (~matrix).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix/scalar division.
+// \ingroup views
+//
+// \param matrix The constant matrix/scalar division.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the division.
+//
+// This function returns an expression representing the specified submatrix of the given
+// matrix/scalar division.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatScalarDivExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return submatrix<AF>( (~matrix).leftOperand(), row, column, m, n ) / (~matrix).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix custom operation.
+// \ingroup views
+//
+// \param matrix The constant matrix custom operation.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the custom operation.
+//
+// This function returns an expression representing the specified submatrix of the given matrix
+// custom operation.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatForEachExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return forEach( submatrix<AF>( (~matrix).operand(), row, column, m, n ), (~matrix).operation() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix evaluation operation.
+// \ingroup views
+//
+// \param matrix The constant matrix evaluation operation.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the evaluation operation.
+//
+// This function returns an expression representing the specified submatrix of the given matrix
+// evaluation operation.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatEvalExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return eval( submatrix<AF>( (~matrix).operand(), row, column, m, n ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix serialization operation.
+// \ingroup views
+//
+// \param matrix The constant matrix serialization operation.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the serialization operation.
+//
+// This function returns an expression representing the specified submatrix of the given matrix
+// serialization operation.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatSerialExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return serial( submatrix<AF>( (~matrix).operand(), row, column, m, n ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of the given matrix transpose operation.
+// \ingroup views
+//
+// \param matrix The constant matrix transpose operation.
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the transpose operation.
+//
+// This function returns an expression representing the specified submatrix of the given matrix
+// transpose operation.
+*/
+template< bool AF // Alignment flag
+ , typename MT // Type of the matrix
+ , bool SO > // Storage order
+inline EnableIf_< IsMatTransExpr<MT>, SubmatrixExprTrait_<MT,AF> >
+ submatrix( const Matrix<MT,SO>& matrix, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return trans( submatrix<AF>( (~matrix).operand(), column, row, n, m ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific submatrix of another submatrix.
+// \ingroup views
+//
+// \param sm The constant submatrix
+// \param row The index of the first row of the submatrix.
+// \param column The index of the first column of the submatrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \return View on the specified submatrix of the other submatrix.
+//
+// This function returns an expression representing the specified submatrix of the given submatrix.
+*/
+template< bool AF1 // Required alignment flag
+ , typename MT // Type of the sparse submatrix
+ , bool AF2 // Present alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline const Submatrix<MT,AF1,SO,DF>
+ submatrix( const Submatrix<MT,AF2,SO,DF>& sm, size_t row, size_t column, size_t m, size_t n )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( ( row + m > sm.rows() ) || ( column + n > sm.columns() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
+ }
+
+ return Submatrix<MT,AF1,SO,DF>( sm.matrix_, sm.row_ + row, sm.column_ + column, m, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIX OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Submatrix operators */
+//@{
+template< typename MT, bool AF, bool SO, bool DF >
+inline void reset( Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline void reset( Submatrix<MT,AF,SO,DF>& sm, size_t i );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline void clear( Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isDefault( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isIntact( const Submatrix<MT,AF,SO,DF>& sm ) noexcept;
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isSymmetric( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isHermitian( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isLower( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isUniLower( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isStrictlyLower( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isUpper( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isUniUpper( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isStrictlyUpper( const Submatrix<MT,AF,SO,DF>& sm );
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isSame( const Submatrix<MT,AF,SO,DF>& a, const Matrix<MT,SO>& b ) noexcept;
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isSame( const Matrix<MT,SO>& a, const Submatrix<MT,AF,SO,DF>& b ) noexcept;
+
+template< typename MT, bool AF, bool SO, bool DF >
+inline bool isSame( const Submatrix<MT,AF,SO,DF>& a, const Submatrix<MT,AF,SO,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given submatrix.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be resetted.
+// \return void
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline void reset( Submatrix<MT,AF,SO,DF>& sm )
+{
+ sm.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reset the specified row/column of the given submatrix.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be resetted.
+// \param i The index of the row/column to be resetted.
+// \return void
+//
+// This function resets the values in the specified row/column of the given submatrix to their
+// default value. In case the given submatrix is a \a rowMajor matrix the function resets the
+// values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
+// \a i. Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline void reset( Submatrix<MT,AF,SO,DF>& sm, size_t i )
+{
+ sm.reset( i );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given matrix.
+// \ingroup submatrix
+//
+// \param sm The matrix to be cleared.
+// \return void
+//
+// Clearing a submatrix is equivalent to resetting it via the reset() function.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline void clear( Submatrix<MT,AF,SO,DF>& sm )
+{
+ sm.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given submatrix is in default state.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be tested for its default state.
+// \return \a true in case the given submatrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the submatrix is in default state. For instance, in
+// case the submatrix is instantiated for a built-in integral or floating point data type, the
+// function returns \a true in case all submatrix elements are 0 and \a false in case any submatrix
+// element is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::DynamicMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ if( isDefault( submatrix( A, 12UL, 13UL, 22UL, 33UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isDefault( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using blaze::isDefault;
+
+ if( SO == rowMajor ) {
+ for( size_t i=0UL; i<(~sm).rows(); ++i )
+ for( size_t j=0UL; j<(~sm).columns(); ++j )
+ if( !isDefault( (~sm)(i,j) ) )
+ return false;
+ }
+ else {
+ for( size_t j=0UL; j<(~sm).columns(); ++j )
+ for( size_t i=0UL; i<(~sm).rows(); ++i )
+ if( !isDefault( (~sm)(i,j) ) )
+ return false;
+ }
+
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given sparse submatrix is in default state.
+// \ingroup submatrix
+//
+// \param sm The sparse submatrix to be tested for its default state.
+// \return \a true in case the given submatrix is component-wise zero, \a false otherwise.
+//
+// This function checks whether the submatrix is in default state. For instance, in
+// case the submatrix is instantiated for a built-in integral or floating point data type, the
+// function returns \a true in case all submatrix elements are 0 and \a false in case any submatrix
+// element is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::CompressedMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ if( isDefault( submatrix( A, 12UL, 13UL, 22UL, 33UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+inline bool isDefault( const Submatrix<MT,AF,SO,false>& sm )
+{
+ using blaze::isDefault;
+
+ typedef ConstIterator_< Submatrix<MT,AF,SO,false> > ConstIterator;
+
+ const size_t iend( ( SO == rowMajor)?( sm.rows() ):( sm.columns() ) );
+
+ for( size_t i=0UL; i<iend; ++i ) {
+ for( ConstIterator element=sm.begin(i); element!=sm.end(i); ++element )
+ if( !isDefault( element->value() ) ) return false;
+ }
+
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given submatrix are intact.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be tested.
+// \return \a true in case the given submatrix's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the submatrix are intact, i.e. if its
+// state is valid. In case the invariants are intact, the function returns \a true, else it
+// will return \a false. The following example demonstrates the use of the \a isIntact()
+// function:
+
+ \code
+ blaze::DynamicMatrix<double,rowMajor> A;
+ // ... Resizing and initialization
+ if( isIntact( submatrix( A, 12UL, 13UL, 22UL, 33UL ) ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isIntact( const Submatrix<MT,AF,SO,DF>& sm ) noexcept
+{
+ return ( sm.row_ + sm.m_ <= sm.matrix_.rows() &&
+ sm.column_ + sm.n_ <= sm.matrix_.columns() &&
+ isIntact( sm.matrix_ ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given submatrix is symmetric.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be checked.
+// \return \a true if the submatrix is symmetric, \a false if not.
+//
+// This function checks if the given submatrix is symmetric. The submatrix is considered to
+// be symmetric if it is a square matrix whose transpose is equal to itself (\f$ A = A^T \f$). The
+// following code example demonstrates the use of the function:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> Matrix;
+
+ Matrix A( 32UL, 16UL );
+ // ... Initialization
+
+ blaze::Submatrix<Matrix> sm( A, 8UL, 8UL, 16UL, 16UL );
+
+ if( isSymmetric( sm ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isSymmetric( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using BaseType = BaseType_< Submatrix<MT,AF,SO,DF> >;
+
+ if( IsSymmetric<MT>::value && sm.row() == sm.column() && sm.rows() == sm.columns() )
+ return true;
+ else return isSymmetric( static_cast<const BaseType&>( sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given submatrix is Hermitian.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be checked.
+// \return \a true if the submatrix is Hermitian, \a false if not.
+//
+// This function checks if the given submatrix is Hermitian. The submatrix is considered to
+// be Hermitian if it is a square matrix whose transpose is equal to its conjugate transpose
+// (\f$ A = \overline{A^T} \f$). The following code example demonstrates the use of the function:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> Matrix;
+
+ Matrix A( 32UL, 16UL );
+ // ... Initialization
+
+ blaze::Submatrix<Matrix> sm( A, 8UL, 8UL, 16UL, 16UL );
+
+ if( isHermitian( sm ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isHermitian( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using BaseType = BaseType_< Submatrix<MT,AF,SO,DF> >;
+
+ if( IsHermitian<MT>::value && sm.row() == sm.column() && sm.rows() == sm.columns() )
+ return true;
+ else return isHermitian( static_cast<const BaseType&>( sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given submatrix is a lower triangular matrix.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be checked.
+// \return \a true if the submatrix is a lower triangular matrix, \a false if not.
+//
+// This function checks if the given submatrix is a lower triangular matrix. The matrix is
+// considered to be lower triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ l_{0,0} & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & l_{1,1} & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & l_{2,2} & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & l_{N,N} \\
+ \end{array}\right).\f]
+
+// \f$ 0 \times 0 \f$ or \f$ 1 \times 1 \f$ matrices are considered as trivially lower triangular.
+// The following code example demonstrates the use of the function:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> Matrix;
+
+ Matrix A( 32UL, 16UL );
+ // ... Initialization
+
+ blaze::Submatrix<Matrix> sm( A, 8UL, 8UL, 16UL, 16UL );
+
+ if( isLower( sm ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isLower( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using BaseType = BaseType_< Submatrix<MT,AF,SO,DF> >;
+
+ if( IsLower<MT>::value && sm.row() == sm.column() && sm.rows() == sm.columns() )
+ return true;
+ else return isLower( static_cast<const BaseType&>( sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given submatrix is a lower unitriangular matrix.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be checked.
+// \return \a true if the submatrix is a lower unitriangular matrix, \a false if not.
+//
+// This function checks if the given submatrix is a lower unitriangular matrix. The matrix is
+// considered to be lower triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & 1 & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & 1 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & 1 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> Matrix;
+
+ Matrix A( 32UL, 16UL );
+ // ... Initialization
+
+ blaze::Submatrix<Matrix> sm( A, 8UL, 8UL, 16UL, 16UL );
+
+ if( isUniLower( sm ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isUniLower( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using BaseType = BaseType_< Submatrix<MT,AF,SO,DF> >;
+
+ if( IsUniLower<MT>::value && sm.row() == sm.column() && sm.rows() == sm.columns() )
+ return true;
+ else return isUniLower( static_cast<const BaseType&>( sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given submatrix is a strictly lower triangular matrix.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be checked.
+// \return \a true if the submatrix is a strictly lower triangular matrix, \a false if not.
+//
+// This function checks if the given submatrix is a strictly lower triangular matrix. The
+// matrix is considered to be lower triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 0 & 0 & \cdots & 0 \\
+ l_{1,0} & 0 & 0 & \cdots & 0 \\
+ l_{2,0} & l_{2,1} & 0 & \cdots & 0 \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ l_{N,0} & l_{N,1} & l_{N,2} & \cdots & 0 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> Matrix;
+
+ Matrix A( 32UL, 16UL );
+ // ... Initialization
+
+ blaze::Submatrix<Matrix> sm( A, 8UL, 8UL, 16UL, 16UL );
+
+ if( isStrictlyLower( sm ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isStrictlyLower( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using BaseType = BaseType_< Submatrix<MT,AF,SO,DF> >;
+
+ if( IsStrictlyLower<MT>::value && sm.row() == sm.column() && sm.rows() == sm.columns() )
+ return true;
+ else return isStrictlyLower( static_cast<const BaseType&>( sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given submatrix is an upper triangular matrix.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be checked.
+// \return \a true if the submatrix is an upper triangular matrix, \a false if not.
+//
+// This function checks if the given sparse submatrix is an upper triangular matrix. The matrix
+// is considered to be upper triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ u_{0,0} & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & u_{1,1} & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & u_{2,2} & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & u_{N,N} \\
+ \end{array}\right).\f]
+
+// \f$ 0 \times 0 \f$ or \f$ 1 \times 1 \f$ matrices are considered as trivially upper triangular.
+// The following code example demonstrates the use of the function:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> Matrix;
+
+ Matrix A( 32UL, 16UL );
+ // ... Initialization
+
+ blaze::Submatrix<Matrix> sm( A, 8UL, 8UL, 16UL, 16UL );
+
+ if( isUpper( sm ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isUpper( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using BaseType = BaseType_< Submatrix<MT,AF,SO,DF> >;
+
+ if( IsUpper<MT>::value && sm.row() == sm.column() && sm.rows() == sm.columns() )
+ return true;
+ else return isUpper( static_cast<const BaseType&>( sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given submatrix is an upper unitriangular matrix.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be checked.
+// \return \a true if the submatrix is an upper unitriangular matrix, \a false if not.
+//
+// This function checks if the given sparse submatrix is an upper triangular matrix. The matrix
+// is considered to be upper triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 1 & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & 1 & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & 1 & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & 1 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> Matrix;
+
+ Matrix A( 32UL, 16UL );
+ // ... Initialization
+
+ blaze::Submatrix<Matrix> sm( A, 8UL, 8UL, 16UL, 16UL );
+
+ if( isUniUpper( sm ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isUniUpper( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using BaseType = BaseType_< Submatrix<MT,AF,SO,DF> >;
+
+ if( IsUniUpper<MT>::value && sm.row() == sm.column() && sm.rows() == sm.columns() )
+ return true;
+ else return isUniUpper( static_cast<const BaseType&>( sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if the given submatrix is a strictly upper triangular matrix.
+// \ingroup submatrix
+//
+// \param sm The submatrix to be checked.
+// \return \a true if the submatrix is a strictly upper triangular matrix, \a false if not.
+//
+// This function checks if the given sparse submatrix is a strictly upper triangular matrix. The
+// matrix is considered to be upper triangular if it is a square matrix of the form
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & u_{0,1} & u_{0,2} & \cdots & u_{0,N} \\
+ 0 & 0 & u_{1,2} & \cdots & u_{1,N} \\
+ 0 & 0 & 0 & \cdots & u_{2,N} \\
+ \vdots & \vdots & \vdots & \ddots & \vdots \\
+ 0 & 0 & 0 & \cdots & 0 \\
+ \end{array}\right).\f]
+
+// The following code example demonstrates the use of the function:
+
+ \code
+ typedef blaze::DynamicMatrix<int,blaze::rowMajor> Matrix;
+
+ Matrix A( 32UL, 16UL );
+ // ... Initialization
+
+ blaze::Submatrix<Matrix> sm( A, 8UL, 8UL, 16UL, 16UL );
+
+ if( isStrictlyUpper( sm ) ) { ... }
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isStrictlyUpper( const Submatrix<MT,AF,SO,DF>& sm )
+{
+ using BaseType = BaseType_< Submatrix<MT,AF,SO,DF> >;
+
+ if( IsStrictlyUpper<MT>::value && sm.row() == sm.column() && sm.rows() == sm.columns() )
+ return true;
+ else return isStrictlyUpper( static_cast<const BaseType&>( sm ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given matrix and submatrix represent the same observable state.
+// \ingroup submatrix
+//
+// \param a The submatrix to be tested for its state.
+// \param b The matrix to be tested for its state.
+// \return \a true in case the submatrix and matrix share a state, \a false otherwise.
+//
+// This overload of the isSame function tests if the given submatrix refers to the full given
+// matrix and by that represents the same observable state. In this case, the function returns
+// \a true, otherwise it returns \a false.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isSame( const Submatrix<MT,AF,SO,DF>& a, const Matrix<MT,SO>& b ) noexcept
+{
+ return ( isSame( a.matrix_, ~b ) && ( a.rows() == (~b).rows() ) && ( a.columns() == (~b).columns() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given matrix and submatrix represent the same observable state.
+// \ingroup submatrix
+//
+// \param a The matrix to be tested for its state.
+// \param b The submatrix to be tested for its state.
+// \return \a true in case the matrix and submatrix share a state, \a false otherwise.
+//
+// This overload of the isSame function tests if the given submatrix refers to the full given
+// matrix and by that represents the same observable state. In this case, the function returns
+// \a true, otherwise it returns \a false.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isSame( const Matrix<MT,SO>& a, const Submatrix<MT,AF,SO,DF>& b ) noexcept
+{
+ return ( isSame( ~a, b.matrix_ ) && ( (~a).rows() == b.rows() ) && ( (~a).columns() == b.columns() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the two given submatrices represent the same observable state.
+// \ingroup submatrix
+//
+// \param a The first submatrix to be tested for its state.
+// \param b The second submatrix to be tested for its state.
+// \return \a true in case the two submatrices share a state, \a false otherwise.
+//
+// This overload of the isSame function tests if the two given submatrices refer to exactly the
+// same part of the same matrix. In case both submatrices represent the same observable state,
+// the function returns \a true, otherwise it returns \a false.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline bool isSame( const Submatrix<MT,AF,SO,DF>& a, const Submatrix<MT,AF,SO,DF>& b ) noexcept
+{
+ return ( isSame( a.matrix_, b.matrix_ ) &&
+ ( a.row_ == b.row_ ) && ( a.column_ == b.column_ ) &&
+ ( a.m_ == b.m_ ) && ( a.n_ == b.n_ ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place inversion of the given submatrix.
+// \ingroup submatrix
+//
+// \param sm The dense submatrix to be inverted.
+// \return void
+// \exception std::invalid_argument Inversion of singular matrix failed.
+//
+// This function inverts the given dense submatrix by means of the specified matrix decomposition
+// algorithm \a IF:
+
+ \code
+ invert<byLU>( A ); // Inversion of a general matrix
+ invert<byLDLT>( A ); // Inversion of a symmetric indefinite matrix
+ invert<byLDLH>( A ); // Inversion of a Hermitian indefinite matrix
+ invert<byLLH>( A ); // Inversion of a Hermitian positive definite matrix
+ \endcode
+
+// The matrix inversion fails if ...
+//
+// - ... the given submatrix is not a square matrix;
+// - ... the given submatrix is singular and not invertible.
+//
+// In all failure cases either a compilation error is created if the failure can be predicted at
+// compile time or a \a std::invalid_argument exception is thrown.
+//
+// \note This function can only be used if the fitting LAPACK library is available and linked to
+// the executable. Otherwise a linker error will be created.
+//
+// \note This function does only provide the basic exception safety guarantee, i.e. in case of an
+// exception \a sm may already have been modified.
+*/
+template< InversionFlag IF // Inversion algorithm
+ , typename MT // Type of the dense matrix
+ , bool AF // Alignment flag
+ , bool SO > // Storage order
+inline DisableIf_< HasMutableDataAccess<MT> > invert( Submatrix<MT,AF,SO,true>& sm )
+{
+ typedef ResultType_< Submatrix<MT,AF,SO,true> > RT;
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( RT );
+ BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( RT );
+
+ RT tmp( sm );
+ invert<IF>( tmp );
+ sm = tmp;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a vector to a submatrix.
+// \ingroup submatrix
+//
+// \param lhs The target left-hand side submatrix.
+// \param rhs The right-hand side vector to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryAssign( const Submatrix<MT,AF,SO,DF>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= lhs.rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= lhs.columns() - column ), "Invalid number of columns" );
+
+ return tryAssign( lhs.matrix_, ~rhs, lhs.row_ + row, lhs.column_ + column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a matrix to a submatrix.
+// \ingroup submatrix
+//
+// \param lhs The target left-hand side submatrix.
+// \param rhs The right-hand side matrix to be assigned.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO1 // Storage order
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAssign( const Submatrix<MT1,AF,SO1,DF>& lhs, const Matrix<MT2,SO2>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ return tryAssign( lhs.matrix_, ~rhs, lhs.row_ + row, lhs.column_ + column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a submatrix.
+// \ingroup submatrix
+//
+// \param lhs The target left-hand side submatrix.
+// \param rhs The right-hand side vector to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryAddAssign( const Submatrix<MT,AF,SO,DF>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= lhs.rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= lhs.columns() - column ), "Invalid number of columns" );
+
+ return tryAddAssign( lhs.matrix_, ~rhs, lhs.row_ + row, lhs.column_ + column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a matrix to a submatrix.
+// \ingroup submatrix
+//
+// \param lhs The target left-hand side submatrix.
+// \param rhs The right-hand side matrix to be added.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO1 // Storage order
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool tryAddAssign( const Submatrix<MT1,AF,SO1,DF>& lhs, const Matrix<MT2,SO2>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ return tryAddAssign( lhs.matrix_, ~rhs, lhs.row_ + row, lhs.column_ + column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a submatrix.
+// \ingroup submatrix
+//
+// \param lhs The target left-hand side submatrix.
+// \param rhs The right-hand side vector to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool trySubAssign( const Submatrix<MT,AF,SO,DF>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= lhs.rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= lhs.columns() - column ), "Invalid number of columns" );
+
+ return trySubAssign( lhs.matrix_, ~rhs, lhs.row_ + row, lhs.column_ + column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a matrix to a submatrix.
+// \ingroup submatrix
+//
+// \param lhs The target left-hand side submatrix.
+// \param rhs The right-hand side matrix to be subtracted.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT1 // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO1 // Storage order
+ , bool DF // Density flag
+ , typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline bool trySubAssign( const Submatrix<MT1,AF,SO1,DF>& lhs, const Matrix<MT2,SO2>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).rows() <= lhs.rows() - row, "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).columns() <= lhs.columns() - column, "Invalid number of columns" );
+
+ return trySubAssign( lhs.matrix_, ~rhs, lhs.row_ + row, lhs.column_ + column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to a submatrix.
+// \ingroup submatrix
+//
+// \param lhs The target left-hand side submatrix.
+// \param rhs The right-hand side vector to be multiplied.
+// \param row The row index of the first element to be modified.
+// \param column The column index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF // Density flag
+ , typename VT // Type of the right-hand side vector
+ , bool TF > // Transpose flag of the right-hand side vector
+inline bool tryMultAssign( const Submatrix<MT,AF,SO,DF>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column )
+{
+ BLAZE_INTERNAL_ASSERT( row <= lhs.rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( column <= lhs.columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( TF || ( (~rhs).size() <= lhs.rows() - row ), "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( !TF || ( (~rhs).size() <= lhs.columns() - column ), "Invalid number of columns" );
+
+ return tryMultAssign( lhs.matrix_, ~rhs, lhs.row_ + row, lhs.column_ + column );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removal of all restrictions on the data access to the given submatrix.
+// \ingroup submatrix
+//
+// \param dm The submatrix to be derestricted.
+// \return Submatrix without access restrictions.
+//
+// This function removes all restrictions on the data access to the given submatrix. It returns a
+// submatrix that does provide the same interface but does not have any restrictions on the data
+// access.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the matrix
+ , bool AF // Alignment flag
+ , bool SO // Storage order
+ , bool DF > // Density flag
+inline DerestrictTrait_< Submatrix<MT,AF,SO,DF> > derestrict( Submatrix<MT,AF,SO,DF>& dm )
+{
+ typedef DerestrictTrait_< Submatrix<MT,AF,SO,DF> > ReturnType;
+ return ReturnType( derestrict( dm.matrix_ ), dm.row_, dm.column_, dm.m_, dm.n_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF >
+struct IsRestricted< Submatrix<MT,AF,SO,DF> >
+ : public BoolConstant< IsRestricted<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF >
+struct DerestrictTrait< Submatrix<MT,AF,SO,DF> >
+{
+ using Type = Submatrix< RemoveReference_< DerestrictTrait_<MT> >, AF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO >
+struct HasConstDataAccess< Submatrix<MT,AF,SO,true> >
+ : public BoolConstant< HasConstDataAccess<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO >
+struct HasMutableDataAccess< Submatrix<MT,AF,SO,true> >
+ : public BoolConstant< HasMutableDataAccess<MT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool SO >
+struct IsAligned< Submatrix<MT,aligned,SO,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF, typename T >
+struct AddTrait< Submatrix<MT,AF,SO,DF>, T >
+{
+ using Type = AddTrait_< SubmatrixTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool AF, bool SO, bool DF >
+struct AddTrait< T, Submatrix<MT,AF,SO,DF> >
+{
+ using Type = AddTrait_< T, SubmatrixTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF, typename T >
+struct SubTrait< Submatrix<MT,AF,SO,DF>, T >
+{
+ using Type = SubTrait_< SubmatrixTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool AF, bool SO, bool DF >
+struct SubTrait< T, Submatrix<MT,AF,SO,DF> >
+{
+ using Type = SubTrait_< T, SubmatrixTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF, typename T >
+struct MultTrait< Submatrix<MT,AF,SO,DF>, T >
+{
+ using Type = MultTrait_< SubmatrixTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool AF, bool SO, bool DF >
+struct MultTrait< T, Submatrix<MT,AF,SO,DF> >
+{
+ using Type = MultTrait_< T, SubmatrixTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF, typename T >
+struct DivTrait< Submatrix<MT,AF,SO,DF>, T >
+{
+ using Type = DivTrait_< SubmatrixTrait_<MT>, T >;
+};
+
+template< typename T, typename MT, bool AF, bool DF, bool SO >
+struct DivTrait< T, Submatrix<MT,AF,SO,DF> >
+{
+ using Type = DivTrait_< T, SubmatrixTrait_<MT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF >
+struct SubmatrixTrait< Submatrix<MT,AF,SO,DF> >
+{
+ using Type = SubmatrixTrait_< ResultType_< Submatrix<MT,AF,SO,DF> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBMATRIXEXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF1, bool SO, bool DF, bool AF2 >
+struct SubmatrixExprTrait< Submatrix<MT,AF1,SO,DF>, AF2 >
+{
+ using Type = Submatrix<MT,AF2,SO,DF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF1, bool SO, bool DF, bool AF2 >
+struct SubmatrixExprTrait< const Submatrix<MT,AF1,SO,DF>, AF2 >
+{
+ using Type = Submatrix<MT,AF2,SO,DF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF1, bool SO, bool DF, bool AF2 >
+struct SubmatrixExprTrait< volatile Submatrix<MT,AF1,SO,DF>, AF2 >
+{
+ using Type = Submatrix<MT,AF2,SO,DF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF1, bool SO, bool DF, bool AF2 >
+struct SubmatrixExprTrait< const volatile Submatrix<MT,AF1,SO,DF>, AF2 >
+{
+ using Type = Submatrix<MT,AF2,SO,DF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ROWTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF >
+struct RowTrait< Submatrix<MT,AF,SO,DF> >
+{
+ using Type = RowTrait_< ResultType_< Submatrix<MT,AF,SO,DF> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COLUMNTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename MT, bool AF, bool SO, bool DF >
+struct ColumnTrait< Submatrix<MT,AF,SO,DF> >
+{
+ using Type = ColumnTrait_< ResultType_< Submatrix<MT,AF,SO,DF> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/Subvector.h b/src/cpu/blaze/math/views/Subvector.h
new file mode 100644
index 00000000..84de08ba
--- /dev/null
+++ b/src/cpu/blaze/math/views/Subvector.h
@@ -0,0 +1,1500 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/Subvector.h
+// \brief Header file for the implementation of the Subvector view
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_SUBVECTOR_H_
+#define _BLAZE_MATH_VIEWS_SUBVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Vector.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/CrossTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorExprTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/HasConstDataAccess.h>
+#include <blaze/math/typetraits/HasMutableDataAccess.h>
+#include <blaze/math/typetraits/IsAligned.h>
+#include <blaze/math/typetraits/IsComputation.h>
+#include <blaze/math/typetraits/IsCrossExpr.h>
+#include <blaze/math/typetraits/IsTransExpr.h>
+#include <blaze/math/typetraits/IsVecEvalExpr.h>
+#include <blaze/math/typetraits/IsVecForEachExpr.h>
+#include <blaze/math/typetraits/IsVecScalarDivExpr.h>
+#include <blaze/math/typetraits/IsVecScalarMultExpr.h>
+#include <blaze/math/typetraits/IsVecSerialExpr.h>
+#include <blaze/math/typetraits/IsVecTransExpr.h>
+#include <blaze/math/typetraits/IsVecVecAddExpr.h>
+#include <blaze/math/typetraits/IsVecVecDivExpr.h>
+#include <blaze/math/typetraits/IsVecVecMultExpr.h>
+#include <blaze/math/typetraits/IsVecVecSubExpr.h>
+#include <blaze/math/views/subvector/BaseTemplate.h>
+#include <blaze/math/views/subvector/Dense.h>
+#include <blaze/math/views/subvector/Sparse.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// GLOBAL FUNCTION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific subvector of the given vector.
+// \ingroup views
+//
+// \param vector The vector containing the subvector.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specific subvector of the vector.
+// \exception std::invalid_argument Invalid subvector specification.
+//
+// This function returns an expression representing the specified subvector of the given vector.
+// The following example demonstrates the creation of a dense and sparse subvector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ typedef blaze::DynamicVector<double,columnVector> DenseVector;
+ typedef blaze::CompressedVector<int,rowVector> SparseVector;
+
+ DenseVector d;
+ SparseVector s;
+ // ... Resizing and initialization
+
+ // Creating a dense subvector of size 8, starting from index 4
+ blaze::Subvector<DenseVector> dsv = subvector( d, 4UL, 8UL );
+
+ // Creating a sparse subvector of size 7, starting from index 5
+ blaze::Subvector<SparseVector> ssv = subvector( s, 5UL, 7UL );
+ \endcode
+
+// In case the subvector is not properly specified (i.e. if the specified first index is larger
+// than the total size of the given vector or the subvector is specified beyond the size of the
+// vector) a \a std::invalid_argument exception is thrown.
+//
+// Please note that this function creates an unaligned dense or sparse subvector. For instance,
+// the creation of the dense subvector is equivalent to the following three function calls:
+
+ \code
+ blaze::Subvector<DenseVector> dsv = subvector<unaligned>( v, 4UL, 8UL );
+ blaze::Subvector<DenseVector,unaligned> dsv = subvector ( v, 4UL, 8UL );
+ blaze::Subvector<DenseVector,unaligned> dsv = subvector<unaligned>( v, 4UL, 8UL );
+ \endcode
+
+// In contrast to unaligned subvectors, which provide full flexibility, aligned subvectors pose
+// additional alignment restrictions. However, especially in case of dense subvectors this may
+// result in considerable performance improvements. In order to create an aligned subvector the
+// following function call has to be used:
+
+ \code
+ blaze::Subvector<DenseVector,aligned> = subvector<aligned>( v, 4UL, 8UL );
+ \endcode
+
+// Note however that in this case the given \a index and \a size are subject to additional checks
+// to guarantee proper alignment.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline SubvectorExprTrait_<VT,unaligned>
+ subvector( Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<unaligned>( ~vector, index, size );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific subvector of the given vector.
+// \ingroup views
+//
+// \param vector The vector containing the subvector.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specific subvector of the vector.
+// \exception std::invalid_argument Invalid subvector specification.
+//
+// This function returns an expression representing the specified subvector of the given vector.
+// The following example demonstrates the creation of a dense and sparse subvector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ typedef blaze::DynamicVector<double,columnVector> DenseVector;
+ typedef blaze::CompressedVector<int,rowVector> SparseVector;
+
+ DenseVector d;
+ SparseVector s;
+ // ... Resizing and initialization
+
+ // Creating a dense subvector of size 8, starting from index 4
+ blaze::Subvector<DenseVector> dsv = subvector( d, 4UL, 8UL );
+
+ // Creating a sparse subvector of size 7, starting from index 5
+ blaze::Subvector<SparseVector> ssv = subvector( s, 5UL, 7UL );
+ \endcode
+
+// In case the subvector is not properly specified (i.e. if the specified first index is larger
+// than the total size of the given vector or the subvector is specified beyond the size of the
+// vector) a \a std::invalid_argument exception is thrown.
+//
+// Please note that this function creates an unaligned dense or sparse subvector. For instance,
+// the creation of the dense subvector is equivalent to the following three function calls:
+
+ \code
+ blaze::Subvector<DenseVector> dsv = subvector<unaligned>( v, 4UL, 8UL );
+ blaze::Subvector<DenseVector,unaligned> dsv = subvector ( v, 4UL, 8UL );
+ blaze::Subvector<DenseVector,unaligned> dsv = subvector<unaligned>( v, 4UL, 8UL );
+ \endcode
+
+// In contrast to unaligned subvectors, which provide full flexibility, aligned subvectors pose
+// additional alignment restrictions. However, especially in case of dense subvectors this may
+// result in considerable performance improvements. In order to create an aligned subvector the
+// following function call has to be used:
+
+ \code
+ blaze::Subvector<DenseVector,aligned> = subvector<aligned>( v, 4UL, 8UL );
+ \endcode
+
+// Note however that in this case the given \a index and \a size are subject to additional checks
+// to guarantee proper alignment.
+*/
+template< typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline SubvectorExprTrait_<const VT,unaligned>
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<unaligned>( ~vector, index, size );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific subvector of the given vector.
+// \ingroup views
+//
+// \param vector The vector containing the subvector.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specific subvector of the vector.
+// \exception std::invalid_argument Invalid subvector specification.
+//
+// This function returns an expression representing an aligned or unaligned subvector of the
+// given dense or sparse vector, based on the specified alignment flag \a AF. The following
+// example demonstrates the creation of both an aligned and unaligned subvector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ typedef blaze::DynamicVector<double,columnVector> DenseVector;
+ typedef blaze::CompressedVector<int,rowVector> SparseVector;
+
+ DenseVector d;
+ SparseVector s;
+ // ... Resizing and initialization
+
+ // Creating an aligned dense subvector of size 8 starting from index 4
+ blaze::Subvector<DenseVector,aligned> dsv = subvector<aligned>( d, 4UL, 8UL );
+
+ // Creating an unaligned subvector of size 7 starting from index 3
+ blaze::Subvector<SparseVector,unaligned> ssv = subvector<unaligned>( s, 3UL, 7UL );
+ \endcode
+
+// In case the subvector is not properly specified (i.e. if the specified first index is larger
+// than the total size of the given vector or the subvector is specified beyond the size of the
+// vector) a \a std::invalid_argument exception is thrown.
+//
+// In contrast to unaligned subvectors, which provide full flexibility, aligned subvectors pose
+// additional alignment restrictions and the given \a index is subject to additional checks to
+// guarantee proper alignment. However, especially in case of dense subvectors this may result
+// in considerable performance improvements.
+//
+// The alignment restrictions refer to system dependent address restrictions for the used element
+// type and the available vectorization mode (SSE, AVX, ...). In order to be properly aligned the
+// first element of the subvector must be aligned. The following source code gives some examples
+// for a double precision dynamic vector, assuming that AVX is available, which packs 4 \c double
+// values into a SIMD vector:
+
+ \code
+ using blaze::columnVector;
+
+ typedef blaze::DynamicVector<double,columnVector> VectorType;
+ typedef blaze::Subvector<VectorType,aligned> SubvectorType;
+
+ VectorType d( 17UL );
+ // ... Resizing and initialization
+
+ // OK: Starts at the beginning, i.e. the first element is aligned
+ SubvectorType dsv1 = subvector<aligned>( d, 0UL, 13UL );
+
+ // OK: Start index is a multiple of 4, i.e. the first element is aligned
+ SubvectorType dsv2 = subvector<aligned>( d, 4UL, 7UL );
+
+ // OK: The start index is a multiple of 4 and the subvector includes the last element
+ SubvectorType dsv3 = subvector<aligned>( d, 8UL, 9UL );
+
+ // Error: Start index is not a multiple of 4, i.e. the first element is not aligned
+ SubvectorType dsv4 = subvector<aligned>( d, 5UL, 8UL );
+ \endcode
+
+// In case any alignment restrictions are violated, a \a std::invalid_argument exception is thrown.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline DisableIf_< Or< IsComputation<VT>, IsTransExpr<VT> >, SubvectorExprTrait_<VT,AF> >
+ subvector( Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SubvectorExprTrait_<VT,AF>( ~vector, index, size );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a view on a specific subvector of the given vector.
+// \ingroup views
+//
+// \param vector The vector containing the subvector.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specific subvector of the vector.
+// \exception std::invalid_argument Invalid subvector specification.
+//
+// This function returns an expression representing an aligned or unaligned subvector of the
+// given dense or sparse vector, based on the specified alignment flag \a AF. The following
+// example demonstrates the creation of both an aligned and unaligned subvector:
+
+ \code
+ using blaze::columnVector;
+ using blaze::rowVector;
+
+ typedef blaze::DynamicVector<double,columnVector> DenseVector;
+ typedef blaze::CompressedVector<int,rowVector> SparseVector;
+
+ DenseVector d;
+ SparseVector s;
+ // ... Resizing and initialization
+
+ // Creating an aligned dense subvector of size 8 starting from index 4
+ blaze::Subvector<DenseVector,aligned> dsv = subvector<aligned>( d, 4UL, 8UL );
+
+ // Creating an unaligned subvector of size 7 starting from index 3
+ blaze::Subvector<SparseVector,unaligned> ssv = subvector<unaligned>( s, 3UL, 7UL );
+ \endcode
+
+// In case the subvector is not properly specified (i.e. if the specified first index is larger
+// than the total size of the given vector or the subvector is specified beyond the size of the
+// vector) a \a std::invalid_argument exception is thrown.
+//
+// In contrast to unaligned subvectors, which provide full flexibility, aligned subvectors pose
+// additional alignment restrictions and the given \a index is subject to additional checks to
+// guarantee proper alignment. However, especially in case of dense subvectors this may result
+// in considerable performance improvements.
+//
+// The alignment restrictions refer to system dependent address restrictions for the used element
+// type and the available vectorization mode (SSE, AVX, ...). In order to be properly aligned the
+// first element of the subvector must be aligned. The following source code gives some examples
+// for a double precision dynamic vector, assuming that AVX is available, which packs 4 \c double
+// values into a SIMD vector:
+
+ \code
+ using blaze::columnVector;
+
+ typedef blaze::DynamicVector<double,columnVector> VectorType;
+ typedef blaze::Subvector<VectorType,aligned> SubvectorType;
+
+ VectorType d( 17UL );
+ // ... Resizing and initialization
+
+ // OK: Starts at the beginning, i.e. the first element is aligned
+ SubvectorType dsv1 = subvector<aligned>( d, 0UL, 13UL );
+
+ // OK: Start index is a multiple of 4, i.e. the first element is aligned
+ SubvectorType dsv2 = subvector<aligned>( d, 4UL, 7UL );
+
+ // OK: The start index is a multiple of 4 and the subvector includes the last element
+ SubvectorType dsv3 = subvector<aligned>( d, 8UL, 9UL );
+
+ // Error: Start index is not a multiple of 4, i.e. the first element is not aligned
+ SubvectorType dsv4 = subvector<aligned>( d, 5UL, 8UL );
+ \endcode
+
+// In case any alignment restrictions are violated, a \a std::invalid_argument exception is thrown.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline DisableIf_< Or< IsComputation<VT>, IsTransExpr<VT> >, SubvectorExprTrait_<const VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SubvectorExprTrait_<const VT,AF>( ~vector, index, size );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL RESTRUCTURING OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector/vector addition.
+// \ingroup views
+//
+// \param vector The constant vector/vector addition.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the addition.
+//
+// This function returns an expression representing the specified subvector of the given
+// vector/vector addition.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecVecAddExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<AF>( (~vector).leftOperand() , index, size ) +
+ subvector<AF>( (~vector).rightOperand(), index, size );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector/vector subtraction.
+// \ingroup views
+//
+// \param vector The constant vector/vector subtraction.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the subtraction.
+//
+// This function returns an expression representing the specified subvector of the given
+// vector/vector subtraction.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecVecSubExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<AF>( (~vector).leftOperand() , index, size ) -
+ subvector<AF>( (~vector).rightOperand(), index, size );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector/vector multiplication.
+// \ingroup views
+//
+// \param vector The constant vector/vector multiplication.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the multiplication.
+//
+// This function returns an expression representing the specified subvector of the given
+// vector/vector multiplication.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecVecMultExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<AF>( (~vector).leftOperand() , index, size ) *
+ subvector<AF>( (~vector).rightOperand(), index, size );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector/vector division.
+// \ingroup views
+//
+// \param vector The constant vector/vector division.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the division.
+//
+// This function returns an expression representing the specified subvector of the given
+// vector/vector division.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecVecDivExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<AF>( (~vector).leftOperand() , index, size ) /
+ subvector<AF>( (~vector).rightOperand(), index, size );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector/vector cross product.
+// \ingroup views
+//
+// \param vector The constant vector/vector cross product.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the cross product.
+//
+// This function returns an expression representing the specified subvector of the given
+// vector/vector cross product.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsCrossExpr<VT>, SubvectorExprTrait_<VT,unaligned> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return SubvectorExprTrait_<VT,unaligned>( ~vector, index, size );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector/scalar multiplication.
+// \ingroup views
+//
+// \param vector The constant vector/scalar multiplication.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the multiplication.
+//
+// This function returns an expression representing the specified subvector of the given
+// vector/scalar multiplication.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecScalarMultExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<AF>( (~vector).leftOperand(), index, size ) * (~vector).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector/scalar division.
+// \ingroup views
+//
+// \param vector The constant vector/scalar division.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the division.
+//
+// This function returns an expression representing the specified subvector of the given
+// vector/scalar division.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecScalarDivExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return subvector<AF>( (~vector).leftOperand(), index, size ) / (~vector).rightOperand();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector custom operation.
+// \ingroup views
+//
+// \param vector The constant vector custom operation.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the custom operation.
+//
+// This function returns an expression representing the specified subvector of the given vector
+// custom operation.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecForEachExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return forEach( subvector<AF>( (~vector).operand(), index, size ), (~vector).operation() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector evaluation operation.
+// \ingroup views
+//
+// \param vector The constant vector evaluation operation.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the evaluation operation.
+//
+// This function returns an expression representing the specified subvector of the given vector
+// evaluation operation.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecEvalExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return eval( subvector<AF>( (~vector).operand(), index, size ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector serialization operation.
+// \ingroup views
+//
+// \param vector The constant vector serialization operation.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the serialization operation.
+//
+// This function returns an expression representing the specified subvector of the given vector
+// serialization operation.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecSerialExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return serial( subvector<AF>( (~vector).operand(), index, size ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of the given vector transpose operation.
+// \ingroup views
+//
+// \param vector The constant vector transpose operation.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the transpose operation.
+//
+// This function returns an expression representing the specified subvector of the given vector
+// transpose operation.
+*/
+template< bool AF // Alignment flag
+ , typename VT // Type of the vector
+ , bool TF > // Transpose flag
+inline EnableIf_< IsVecTransExpr<VT>, SubvectorExprTrait_<VT,AF> >
+ subvector( const Vector<VT,TF>& vector, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ return trans( subvector<AF>( (~vector).operand(), index, size ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Creating a view on a specific subvector of another subvector.
+// \ingroup views
+//
+// \param sv The constant subvector.
+// \param index The index of the first element of the subvector.
+// \param size The size of the subvector.
+// \return View on the specified subvector of the other subvector.
+//
+// This function returns an expression representing the specified subvector of the given subvector.
+*/
+template< bool AF1 // Required alignment flag
+ , typename VT // Type of the dense vector
+ , bool AF2 // Present alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline const Subvector<VT,AF1,TF,DF>
+ subvector( const Subvector<VT,AF2,TF,DF>& sv, size_t index, size_t size )
+{
+ BLAZE_FUNCTION_TRACE;
+
+ if( index + size > sv.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid subvector specification" );
+ }
+
+ return Subvector<VT,AF1,TF,DF>( sv.vector_, sv.offset_ + index, size );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTOR OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Subvector operators */
+//@{
+template< typename VT, bool AF, bool TF, bool DF >
+inline void reset( Subvector<VT,AF,TF,DF>& sv );
+
+template< typename VT, bool AF, bool TF, bool DF >
+inline void clear( Subvector<VT,AF,TF,DF>& sv );
+
+template< typename VT, bool AF, bool TF, bool DF >
+inline bool isDefault( const Subvector<VT,AF,TF,DF>& sv );
+
+template< typename VT, bool AF, bool TF, bool DF >
+inline bool isIntact( const Subvector<VT,AF,TF,DF>& sv ) noexcept;
+
+template< typename VT, bool AF, bool TF, bool DF >
+inline bool isSame( const Subvector<VT,AF,TF,DF>& a, const Vector<VT,TF>& b ) noexcept;
+
+template< typename VT, bool AF, bool TF, bool DF >
+inline bool isSame( const Vector<VT,TF>& a, const Subvector<VT,AF,TF,DF>& b ) noexcept;
+
+template< typename VT, bool AF, bool TF, bool DF >
+inline bool isSame( const Subvector<VT,AF,TF,DF>& a, const Subvector<VT,AF,TF,DF>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the given subvector.
+// \ingroup subvector
+//
+// \param sv The subvector to be resetted.
+// \return void
+*/
+template< typename VT // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline void reset( Subvector<VT,AF,TF,DF>& sv )
+{
+ sv.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clearing the given subvector.
+// \ingroup subvector
+//
+// \param sv The subvector to be cleared.
+// \return void
+*/
+template< typename VT // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline void clear( Subvector<VT,AF,TF,DF>& sv )
+{
+ sv.reset();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given subvector is in default state.
+// \ingroup subvector
+//
+// \param sv The subvector to be tested for its default state.
+// \return \a true in case the given subvector is component-wise zero, \a false otherwise.
+//
+// This function checks whether the subvector is in default state. For instance, in case the
+// subvector is instantiated for a vector of built-in integral or floating point data type,
+// the function returns \a true in case all subvector elements are 0 and \a false in case any
+// subvector element is not 0. The following example demonstrates the use of the \a isDefault
+// function:
+
+ \code
+ blaze::DynamicVector<int,rowVector> v;
+ // ... Resizing and initialization
+ if( isDefault( subvector( v, 10UL, 20UL ) ) ) { ... }
+ \endcode
+*/
+template< typename VT // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline bool isDefault( const Subvector<VT,AF,TF,DF>& sv )
+{
+ for( size_t i=0UL; i<sv.size(); ++i )
+ if( !isDefault( sv[i] ) ) return false;
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the given sparse subvector is in default state.
+// \ingroup subvector
+//
+// \param sv The sparse subvector to be tested for its default state.
+// \return \a true in case the given subvector is component-wise zero, \a false otherwise.
+//
+// This function checks whether the sparse subvector is in default state. For instance, in case
+// the subvector is instantiated for a vector of built-in integral or floating point data type,
+// the function returns \a true in case all subvector elements are 0 and \a false in case any
+// element is not 0. The following example demonstrates the use of the \a isDefault function:
+
+ \code
+ blaze::CompressedVector<double,rowVector> v;
+ // ... Resizing and initialization
+ if( isDefault( subvector( v, 10UL, 20UL ) ) ) { ... }
+ \endcode
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline bool isDefault( const Subvector<VT,AF,TF,false>& sv )
+{
+ typedef ConstIterator_< Subvector<VT,AF,TF,false> > ConstIterator;
+
+ const ConstIterator end( sv.end() );
+ for( ConstIterator element=sv.begin(); element!=end; ++element )
+ if( !isDefault( element->value() ) ) return false;
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the invariants of the given subvector vector are intact.
+// \ingroup subvector
+//
+// \param sv The subvector to be tested.
+// \return \a true in case the given subvector's invariants are intact, \a false otherwise.
+//
+// This function checks whether the invariants of the subvector are intact, i.e. if its state
+// is valid. In case the invariants are intact, the function returns \a true, else it will
+// return \a false. The following example demonstrates the use of the \a isIntact() function:
+
+ \code
+ blaze::DynamicVector<int,rowVector> v;
+ // ... Resizing and initialization
+ if( isIntact( subvector( v, 10UL, 20UL ) ) ) { ... }
+ \endcode
+*/
+template< typename VT // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline bool isIntact( const Subvector<VT,AF,TF,DF>& sv ) noexcept
+{
+ return ( sv.offset_ + sv.size_ <= sv.vector_.size() &&
+ isIntact( sv.vector_ ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given vector and subvector represent the same observable state.
+// \ingroup subvector
+//
+// \param a The subvector to be tested for its state.
+// \param b The vector to be tested for its state.
+// \return \a true in case the subvector and vector share a state, \a false otherwise.
+//
+// This overload of the isSame function tests if the given subvector refers to the entire
+// range of the given vector and by that represents the same observable state. In this case,
+// the function returns \a true, otherwise it returns \a false.
+*/
+template< typename VT // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline bool isSame( const Subvector<VT,AF,TF,DF>& a, const Vector<VT,TF>& b ) noexcept
+{
+ return ( isSame( a.vector_, ~b ) && ( a.size() == (~b).size() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the given vector and subvector represent the same observable state.
+// \ingroup subvector
+//
+// \param a The vector to be tested for its state.
+// \param b The subvector to be tested for its state.
+// \return \a true in case the vector and subvector share a state, \a false otherwise.
+//
+// This overload of the isSame function tests if the given subvector refers to the entire
+// range of the given vector and by that represents the same observable state. In this case,
+// the function returns \a true, otherwise it returns \a false.
+*/
+template< typename VT // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline bool isSame( const Vector<VT,TF>& a, const Subvector<VT,AF,TF,DF>& b ) noexcept
+{
+ return ( isSame( ~a, b.vector_ ) && ( (~a).size() == b.size() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the two given subvectors represent the same observable state.
+// \ingroup subvector
+//
+// \param a The first subvector to be tested for its state.
+// \param b The second subvector to be tested for its state.
+// \return \a true in case the two subvectors share a state, \a false otherwise.
+//
+// This overload of the isSame function tests if the two given subvectors refer to exactly the
+// same range of the same vector. In case both subvectors represent the same observable state,
+// the function returns \a true, otherwise it returns \a false.
+*/
+template< typename VT // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline bool isSame( const Subvector<VT,AF,TF,DF>& a, const Subvector<VT,AF,TF,DF>& b ) noexcept
+{
+ return ( isSame( a.vector_, b.vector_ ) && ( a.offset_ == b.offset_ ) && ( a.size_ == b.size_ ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the assignment of a vector to a subvector.
+// \ingroup subvector
+//
+// \param lhs The target left-hand side subvector.
+// \param rhs The right-hand side vector to be assigned.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF // Density flag
+ , typename VT2 > // Type of the right-hand side vector
+inline bool tryAssign( const Subvector<VT1,AF,TF,DF>& lhs, const Vector<VT2,TF>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryAssign( lhs.vector_, ~rhs, lhs.offset_ + index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the addition assignment of a vector to a subvector.
+// \ingroup subvector
+//
+// \param lhs The target left-hand side subvector.
+// \param rhs The right-hand side vector to be added.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF // Density flag
+ , typename VT2 > // Type of the right-hand side vector
+inline bool tryAddAssign( const Subvector<VT1,AF,TF,DF>& lhs, const Vector<VT2,TF>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryAddAssign( lhs.vector_, ~rhs, lhs.offset_ + index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the subtraction assignment of a vector to a subvector.
+// \ingroup subvector
+//
+// \param lhs The target left-hand side subvector.
+// \param rhs The right-hand side vector to be subtracted.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF // Density flag
+ , typename VT2 > // Type of the right-hand side vector
+inline bool trySubAssign( const Subvector<VT1,AF,TF,DF>& lhs, const Vector<VT2,TF>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return trySubAssign( lhs.vector_, ~rhs, lhs.offset_ + index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the multiplication assignment of a vector to a subvector.
+// \ingroup subvector
+//
+// \param lhs The target left-hand side subvector.
+// \param rhs The right-hand side vector to be multiplied.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF // Density flag
+ , typename VT2 > // Type of the right-hand side vector
+inline bool tryMultAssign( const Subvector<VT1,AF,TF,DF>& lhs, const Vector<VT2,TF>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryMultAssign( lhs.vector_, ~rhs, lhs.offset_ + index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Predict invariant violations by the division assignment of a vector to a subvector.
+// \ingroup subvector
+//
+// \param lhs The target left-hand side subvector.
+// \param rhs The right-hand side vector divisor.
+// \param index The index of the first element to be modified.
+// \return \a true in case the assignment would be successful, \a false if not.
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT1 // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF // Density flag
+ , typename VT2 > // Type of the right-hand side vector
+inline bool tryDivAssign( const Subvector<VT1,AF,TF,DF>& lhs, const Vector<VT2,TF>& rhs, size_t index )
+{
+ BLAZE_INTERNAL_ASSERT( index <= lhs.size(), "Invalid vector access index" );
+ BLAZE_INTERNAL_ASSERT( (~rhs).size() <= lhs.size() - index, "Invalid vector size" );
+
+ return tryDivAssign( lhs.vector_, ~rhs, lhs.offset_ + index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removal of all restrictions on the data access to the given subvector.
+// \ingroup subvector
+//
+// \param sv The subvector to be derestricted.
+// \return Subvector without access restrictions.
+//
+// This function removes all restrictions on the data access to the given subvector. It returns a
+// subvector that does provide the same interface but does not have any restrictions on the data
+// access.\n
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in the violation of invariants, erroneous results and/or in compilation errors.
+*/
+template< typename VT // Type of the vector
+ , bool AF // Alignment flag
+ , bool TF // Transpose flag
+ , bool DF > // Density flag
+inline DerestrictTrait_< Subvector<VT,AF,TF,DF> > derestrict( Subvector<VT,AF,TF,DF>& sv )
+{
+ typedef DerestrictTrait_< Subvector<VT,AF,TF,DF> > ReturnType;
+ return ReturnType( derestrict( sv.vector_ ), sv.offset_, sv.size_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISRESTRICTED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF, bool DF >
+struct IsRestricted< Subvector<VT,AF,TF,DF> >
+ : public BoolConstant< IsRestricted<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DERESTRICTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF, bool DF >
+struct DerestrictTrait< Subvector<VT,AF,TF,DF> >
+{
+ using Type = Subvector< RemoveReference_< DerestrictTrait_<VT> >, AF, TF, DF >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASCONSTDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF >
+struct HasConstDataAccess< Subvector<VT,AF,TF,true> >
+ : public BoolConstant< HasConstDataAccess<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HASMUTABLEDATAACCESS SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF >
+struct HasMutableDataAccess< Subvector<VT,AF,TF,true> >
+ : public BoolConstant< HasMutableDataAccess<VT>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ISALIGNED SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool TF >
+struct IsAligned< Subvector<VT,aligned,TF,true> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ADDTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF, bool DF, typename T >
+struct AddTrait< Subvector<VT,AF,TF,DF>, T >
+{
+ using Type = AddTrait_< SubvectorTrait_<VT>, T >;
+};
+
+template< typename T, typename VT, bool AF, bool TF, bool DF >
+struct AddTrait< T, Subvector<VT,AF,TF,DF> >
+{
+ using Type = AddTrait_< T, SubvectorTrait_<VT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF, bool DF, typename T >
+struct SubTrait< Subvector<VT,AF,TF,DF>, T >
+{
+ using Type = SubTrait_< SubvectorTrait_<VT>, T >;
+};
+
+template< typename T, typename VT, bool AF, bool TF, bool DF >
+struct SubTrait< T, Subvector<VT,AF,TF,DF> >
+{
+ using Type = SubTrait_< T, SubvectorTrait_<VT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MULTTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF, bool DF, typename T >
+struct MultTrait< Subvector<VT,AF,TF,DF>, T >
+{
+ using Type = MultTrait_< SubvectorTrait_<VT>, T >;
+};
+
+template< typename T, typename VT, bool AF, bool TF, bool DF >
+struct MultTrait< T, Subvector<VT,AF,TF,DF> >
+{
+ using Type = MultTrait_< T, SubvectorTrait_<VT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CROSSTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF, bool DF, typename T >
+struct CrossTrait< Subvector<VT,AF,TF,DF>, T >
+{
+ using Type = CrossTrait_< SubvectorTrait_<VT>, T >;
+};
+
+template< typename T, typename VT, bool AF, bool TF, bool DF >
+struct CrossTrait< T, Subvector<VT,AF,TF,DF> >
+{
+ using Type = CrossTrait_< T, SubvectorTrait_<VT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DIVTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF, bool DF, typename T >
+struct DivTrait< Subvector<VT,AF,TF,DF>, T >
+{
+ using Type = DivTrait_< SubvectorTrait_<VT>, T >;
+};
+
+template< typename T, typename VT, bool AF, bool TF, bool DF >
+struct DivTrait< T, Subvector<VT,AF,TF,DF> >
+{
+ using Type = DivTrait_< T, SubvectorTrait_<VT> >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTORTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF, bool TF, bool DF >
+struct SubvectorTrait< Subvector<VT,AF,TF,DF> >
+{
+ using Type = SubvectorTrait_< ResultType_< Subvector<VT,AF,TF,DF> > >;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SUBVECTOREXPRTRAIT SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF1, bool TF, bool DF, bool AF2 >
+struct SubvectorExprTrait< Subvector<VT,AF1,TF,DF>, AF2 >
+{
+ using Type = Subvector<VT,AF2,TF,DF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF1, bool TF, bool DF, bool AF2 >
+struct SubvectorExprTrait< const Subvector<VT,AF1,TF,DF>, AF2 >
+{
+ using Type = Subvector<VT,AF2,TF,DF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF1, bool TF, bool DF, bool AF2 >
+struct SubvectorExprTrait< volatile Subvector<VT,AF1,TF,DF>, AF2 >
+{
+ using Type = Subvector<VT,AF2,TF,DF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT, bool AF1, bool TF, bool DF, bool AF2 >
+struct SubvectorExprTrait< const volatile Subvector<VT,AF1,TF,DF>, AF2 >
+{
+ using Type = Subvector<VT,AF2,TF,DF>;
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecDVecCrossExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = Subvector< DVecDVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< DVecSVecCrossExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = Subvector< DVecSVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< SVecDVecCrossExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = Subvector< SVecDVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+template< typename VT1, typename VT2, bool TF, bool AF >
+struct SubvectorExprTrait< SVecSVecCrossExpr<VT1,VT2,TF>, AF >
+{
+ public:
+ //**********************************************************************************************
+ using Type = Subvector< SVecSVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >;
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/Views.h b/src/cpu/blaze/math/views/Views.h
new file mode 100644
index 00000000..bc224f6c
--- /dev/null
+++ b/src/cpu/blaze/math/views/Views.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/Views.h
+// \brief Views module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_VIEWS_H_
+#define _BLAZE_MATH_VIEWS_VIEWS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup views Views
+// \ingroup math
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/math/views/column/BaseTemplate.h b/src/cpu/blaze/math/views/column/BaseTemplate.h
new file mode 100644
index 00000000..35570f7d
--- /dev/null
+++ b/src/cpu/blaze/math/views/column/BaseTemplate.h
@@ -0,0 +1,360 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/column/BaseTemplate.h
+// \brief Header file for the implementation of the Column base template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_COLUMN_BASETEMPLATE_H_
+#define _BLAZE_MATH_VIEWS_COLUMN_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup column Column
+// \ingroup views
+*/
+/*!\brief Reference to a specific column of a dense or sparse matrix.
+// \ingroup column
+//
+// The Column template represents a reference to a specific column of a dense or sparse matrix
+// primitive. The type of the matrix is specified via the first template parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF, bool SF >
+ class Column;
+ \endcode
+
+// - MT: specifies the type of the matrix primitive. Column can be used with every matrix
+// primitive, but does not work with any matrix expression type.
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+// - SF: specifies whether the given matrix is a symmetric matrix or not. Also this parameter
+// doesn't have to be explicitly defined, but is automatically derived from the first
+// template parameter.
+//
+//
+// \n \section column_setup Setup of Columns
+//
+// A reference to a dense or sparse column can be created very conveniently via the \c column()
+// function. This reference can be treated as any other column vector, i.e. it can be assigned to,
+// it can be copied from, and it can be used in arithmetic operations. The reference can also be
+// used on both sides of an assignment: The column can either be used as an alias to grant write
+// access to a specific column of a matrix primitive on the left-hand side of an assignment or to
+// grant read-access to a specific column of a matrix primitive or expression on the right-hand
+// side of an assignment. The following example demonstrates this in detail:
+
+ \code
+ using DenseVectorType = blaze::DynamicVector<double,columnVector>;
+ using SparseVectorType = blaze::CompressedVector<double,columnVector>;
+ using DenseMatrixType = blaze::DynamicMatrix<double,columnMajor>;
+ using SparseMatrixType = blaze::CompressedMatrix<double,columnMajor>;
+
+ DenseVectorType x;
+ SparseVectorType y;
+ DenseMatrixType A, B;
+ SparseMatrixType C, D;
+ // ... Resizing and initialization
+
+ // Setting the 1st column of matrix A to x
+ blaze::Column<DenseMatrixType> col1 = column( A, 1UL );
+ col1 = x;
+
+ // Setting the 4th column of matrix B to y
+ column( B, 4UL ) = y;
+
+ // Setting x to the 2nd column of the result of the matrix multiplication
+ x = column( A * B, 2UL );
+
+ // Setting y to the 2nd column of the result of the sparse matrix multiplication
+ y = column( C * D, 2UL );
+ \endcode
+
+// The \c column() function can be used on any dense or sparse matrix, including expressions, as
+// illustrated by the source code example. However, columns cannot be instantiated for expression
+// types, but only for matrix primitives, respectively, i.e. for matrix types that offer write
+// access.
+//
+//
+// \n \section column_element_access Element access
+//
+// A dense or sparse column can be used like any other column vector. For instance, the elements
+// of the dense column can be directly accessed with the subscript operator.
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<double,blaze::columnMajor>;
+ MatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a view on the 4th column of matrix A
+ blaze::Column<MatrixType> col4 = column( A, 4UL );
+
+ // Setting the 1st element of the dense column, which corresponds
+ // to the 1st element in the 4th column of matrix A
+ col4[1] = 2.0;
+ \endcode
+
+// The numbering of the column elements is
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right),\f]
+
+// where N is the number of rows of the referenced matrix. Alternatively, the elements of a
+// column can be traversed via iterators. Just as with vectors, in case of non-const rows,
+// \c begin() and \c end() return an Iterator, which allows a manipulation of the non-zero
+// values, in case of constant columns a ConstIterator is returned:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<int,blaze::columnMajor>;
+ using ColumnType = blaze::Column<MatrixType>;
+
+ MatrixType A( 128UL, 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st column of matrix A
+ ColumnType col31 = column( A, 31UL );
+
+ for( ColumnType::Iterator it=col31.begin(); it!=col31.end(); ++it ) {
+ *it = ...; // OK; Write access to the dense column value
+ ... = *it; // OK: Read access to the dense column value.
+ }
+
+ for( ColumnType::ConstIterator it=col31.begin(); it!=col31.end(); ++it ) {
+ *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = *it; // OK: Read access to the dense column value.
+ }
+ \endcode
+
+ \code
+ using MatrixType = blaze::CompressedMatrix<int,blaze::columnMajor>;
+ using ColumnType = blaze::Column<MatrixType>;
+
+ MatrixType A( 128UL, 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st column of matrix A
+ ColumnType col31 = column( A, 31UL );
+
+ for( ColumnType::Iterator it=col31.begin(); it!=col31.end(); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+
+ for( ColumnType::ConstIterator it=col31.begin(); it!=col31.end(); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+ \endcode
+
+// \n \section sparse_column_element_insertion Element Insertion
+//
+// Inserting/accessing elements in a sparse column can be done by several alternative functions.
+// The following example demonstrates all options:
+
+ \code
+ using MatrixType = blaze::CompressedMatrix<double,blaze::columnMajor>;
+ MatrixType A( 100UL, 10UL ); // Non-initialized 100x10 matrix
+
+ using ColumnType = blaze::Column<MatrixType>;
+ ColumnType col0( column( A, 0UL ) ); // Reference to the 0th column of A
+
+ // The subscript operator provides access to all possible elements of the sparse column,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse column, the element is inserted into the column.
+ col0[42] = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element
+ // is not contained in the column it is inserted into the column, if it is already contained
+ // in the column its value is modified.
+ col0.set( 45UL, -1.2 );
+
+ // An alternative for inserting elements into the column is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the column.
+ col0.insert( 50UL, 3.7 );
+
+ // A very efficient way to add new elements to a sparse column is the append() function.
+ // Note that append() requires that the appended element's index is strictly larger than
+ // the currently largest non-zero index of the column and that the column's capacity is
+ // large enough to hold the new element.
+ col0.reserve( 10UL );
+ col0.append( 51UL, -2.1 );
+ \endcode
+
+// \n \section column_common_operations Common Operations
+//
+// The current number of column elements can be obtained via the \c size() function, the current
+// capacity via the \c capacity() function, and the number of non-zero elements via the
+// \c nonZeros() function. However, since columns are references to specific columns of a matrix,
+// several operations are not possible on views, such as resizing and swapping:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<int,blaze::columnMajor>;
+ using ColumnType = blaze::Column<MatrixType>;
+
+ MatrixType A( 42UL, 42UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 2nd column of matrix A
+ ColumnType col2 = column( A, 2UL );
+
+ col2.size(); // Returns the number of elements in the column
+ col2.capacity(); // Returns the capacity of the column
+ col2.nonZeros(); // Returns the number of non-zero elements contained in the column
+
+ col2.resize( 84UL ); // Compilation error: Cannot resize a single column of a matrix
+
+ ColumnType col3 = column( A, 3UL );
+ swap( col2, col3 ); // Compilation error: Swap operation not allowed
+ \endcode
+
+// \n \section column_arithmetic_operations Arithmetic Operations
+//
+// Both dense and sparse columns can be used in all arithmetic operations that any other dense or
+// sparse column vector can be used in. The following example gives an impression of the use of
+// dense columns within arithmetic operations. All operations (addition, subtraction, multiplication,
+// scaling, ...) can be performed on all possible combinations of dense and sparse columns with
+// fitting element types:
+
+ \code
+ blaze::DynamicVector<double,blaze::columnVector> a( 2UL, 2.0 ), b;
+ blaze::CompressedVector<double,blaze::columnVector> c( 2UL );
+ c[1] = 3.0;
+
+ using MatrixType = blaze::DynamicMatrix<double,blaze::columnMajor>;
+ MatrixType A( 2UL, 4UL ); // Non-initialized 2x4 matrix
+
+ using ColumnType = blaze::Column<DenseMatrix>;
+ ColumnType col0( column( A, 0UL ) ); // Reference to the 0th column of A
+
+ col0[0] = 0.0; // Manual initialization of the 0th column of A
+ col0[1] = 0.0;
+ column( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st column of A
+ column( A, 2UL ) = a; // Dense vector initialization of the 2nd column of A
+ column( A, 3UL ) = c; // Sparse vector initialization of the 3rd column of A
+
+ b = col0 + a; // Dense vector/dense vector addition
+ b = c + column( A, 1UL ); // Sparse vector/dense vector addition
+ b = col0 * column( A, 2UL ); // Component-wise vector multiplication
+
+ column( A, 1UL ) *= 2.0; // In-place scaling of the 1st column
+ b = column( A, 1UL ) * 2.0; // Scaling of the 1st column
+ b = 2.0 * column( A, 1UL ); // Scaling of the 1st column
+
+ column( A, 2UL ) += a; // Addition assignment
+ column( A, 2UL ) -= c; // Subtraction assignment
+ column( A, 2UL ) *= column( A, 0UL ); // Multiplication assignment
+
+ double scalar = trans( c ) * column( A, 1UL ); // Scalar/dot/inner product between two vectors
+
+ A = column( A, 1UL ) * trans( c ); // Outer product between two vectors
+ \endcode
+
+// \n \section column_on_row_major_matrix Columns on a Row-Major Matrix
+//
+// It is especially noteworthy that column views can be created for both row-major and column-major
+// matrices. Whereas the interface of a row-major matrix only allows to traverse a row directly
+// and the interface of a column-major matrix only allows to traverse a column, via views it is
+// also possible to traverse a column of a row-major matrix. For instance:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<int,blaze::rowMajor>;
+ using ColumnType = blaze::Column<MatrixType>;
+
+ MatrixType A( 64UL, 32UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 1st column of a column-major matrix A
+ ColumnType col1 = column( A, 1UL );
+
+ for( ColumnType::Iterator it=col1.begin(); it!=col1.end(); ++it ) {
+ // ...
+ }
+ \endcode
+
+// However, please note that creating a column view on a matrix stored in a row-major fashion
+// can result in a considerable performance decrease in comparison to a column view on a matrix
+// with column-major storage format. This is due to the non-contiguous storage of the matrix
+// elements. Therefore care has to be taken in the choice of the most suitable storage order:
+
+ \code
+ // Setup of two row-major matrices
+ blaze::DynamicMatrix<double,blaze::rowMajor> A( 128UL, 128UL );
+ blaze::DynamicMatrix<double,blaze::rowMajor> B( 128UL, 128UL );
+ // ... Resizing and initialization
+
+ // The computation of the 15th column of the multiplication between A and B ...
+ blaze::DynamicVector<double,blaze::columnVector> x = column( A * B, 15UL );
+
+ // ... is essentially the same as the following computation, which multiplies
+ // A with the 15th column of the row-major matrix B.
+ blaze::DynamicVector<double,blaze::rowVector> x = A * column( B, 15UL );
+ \endcode
+
+// Although Blaze performs the resulting matrix/vector multiplication as efficiently as possible
+// using a column-major storage order for matrix A would result in a more efficient evaluation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order
+ , bool DF = IsDenseMatrix<MT>::value // Density flag
+ , bool SF = IsSymmetric<MT>::value > // Symmetry flag
+class Column
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/column/Dense.h b/src/cpu/blaze/math/views/column/Dense.h
new file mode 100644
index 00000000..798f1809
--- /dev/null
+++ b/src/cpu/blaze/math/views/column/Dense.h
@@ -0,0 +1,5817 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/column/Dense.h
+// \brief Column specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_COLUMN_DENSE_H_
+#define _BLAZE_MATH_VIEWS_COLUMN_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/View.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/views/column/BaseTemplate.h>
+#include <blaze/system/CacheSize.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Column for columns on column-major dense matrices.
+// \ingroup views
+//
+// This specialization of Column adapts the class template to the requirements of column-major
+// dense matrices.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+class Column<MT,true,true,SF>
+ : public DenseVector< Column<MT,true,true,SF>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Column<MT,true,true,SF> This; //!< Type of this Column instance.
+ typedef DenseVector<This,false> BaseType; //!< Base type of this Column instance.
+ typedef ColumnTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the column elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the column elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Column& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant column value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant column value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant column value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant column value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Column( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Column& operator=( const ElementType& rhs );
+ inline Column& operator=( initializer_list<ElementType> list );
+ inline Column& operator=( const Column& rhs );
+
+ template< typename VT > inline Column& operator= ( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator+=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator-=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator/=( const DenseVector<VT,false>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Column >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Column >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline Column& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDSub< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDMult< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDDiv< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool canAlias( const Column<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool isAliased( const Column<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the column.
+ const size_t col_; //!< The index of the column in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 > friend class Column;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Column<MT2,SO2,DF2,SF2>& column ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Column<MT2,SO2,DF2,SF2>& a, const Column<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryDivAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Column<MT2,SO2,DF2,SF2> > derestrict( Column<MT2,SO2,DF2,SF2>& column );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Column.
+//
+// \param matrix The matrix containing the column.
+// \param index The index of the column.
+// \exception std::invalid_argument Invalid column access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline Column<MT,true,true,SF>::Column( MT& matrix, size_t index )
+ : matrix_( matrix ) // The dense matrix containing the column
+ , col_ ( index ) // The index of the column in the matrix
+{
+ if( matrix_.columns() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid column access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::Reference Column<MT,true,true,SF>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return matrix_(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::ConstReference
+ Column<MT,true,true,SF>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return const_cast<const MT&>( matrix_ )(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::Reference Column<MT,true,true,SF>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::ConstReference
+ Column<MT,true,true,SF>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the column elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense column. Note that in case
+// of a row-major matrix you can NOT assume that the column elements lie adjacent to each other!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::Pointer Column<MT,true,true,SF>::data() noexcept
+{
+ return matrix_.data( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the column elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense column. Note that in case
+// of a row-major matrix you can NOT assume that the column elements lie adjacent to each other!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::ConstPointer Column<MT,true,true,SF>::data() const noexcept
+{
+ return matrix_.data( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::Iterator Column<MT,true,true,SF>::begin()
+{
+ return matrix_.begin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::ConstIterator Column<MT,true,true,SF>::begin() const
+{
+ return matrix_.cbegin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::ConstIterator Column<MT,true,true,SF>::cbegin() const
+{
+ return matrix_.cbegin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::Iterator Column<MT,true,true,SF>::end()
+{
+ return matrix_.end( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::ConstIterator Column<MT,true,true,SF>::end() const
+{
+ return matrix_.cend( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,true,SF>::ConstIterator Column<MT,true,true,SF>::cend() const
+{
+ return matrix_.cend( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all column elements.
+//
+// \param rhs Scalar value to be assigned to all column elements.
+// \return Reference to the assigned column.
+//
+// This function homogeneously assigns the given value to all elements of the column. Note that in
+// case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
+// of the underlying matrix are modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator=( const ElementType& rhs )
+{
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( col_+1UL )
+ :( col_ ) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( col_ )
+ :( col_+1UL ) )
+ :( size() ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ matrix_(i,col_) = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all column elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to column.
+//
+// This assignment operator offers the option to directly assign to all elements of the dense
+// column by means of an initializer list. The column elements are assigned the values from the
+// given initializer list. Missing values are reset to their default state. Note that in case
+// the size of the initializer list exceeds the size of the column, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator=( initializer_list<ElementType> list )
+{
+ if( list.size() > size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to column" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), begin() ), end(), ElementType() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Column.
+//
+// \param rhs Dense column to be copied.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Column sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two columns don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator=( const Column& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Column sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator+=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAddAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAddAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator-=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !trySubAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpSubAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator*=( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryMultAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpMultAssign( left, tmp );
+ }
+ else {
+ smpMultAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator*=( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const ResultType right( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, right );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::operator/=( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryDivAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpDivAssign( left, tmp );
+ }
+ else {
+ smpDivAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense column and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+//
+// This operator cannot be used for columns on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Column<MT,true,true,SF> >&
+ Column<MT,true,true,SF>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ return operator=( (*this) * rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense column by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// This operator cannot be used for columns on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Column<MT,true,true,SF> >&
+ Column<MT,true,true,SF>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ return operator=( (*this) / rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the column.
+//
+// \return The size of the column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline size_t Column<MT,true,true,SF>::size() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense column.
+//
+// \return The capacity of the dense column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline size_t Column<MT,true,true,SF>::capacity() const noexcept
+{
+ return matrix_.capacity( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the column.
+//
+// \return The number of non-zero elements in the column.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of rows of the matrix containing the column.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline size_t Column<MT,true,true,SF>::nonZeros() const
+{
+ return matrix_.nonZeros( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline void Column<MT,true,true,SF>::reset()
+{
+ matrix_.reset( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the column by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the column scaling.
+// \return Reference to the dense column.
+//
+// This function scales all elements of the column by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a column on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the scalar value
+inline Column<MT,true,true,SF>& Column<MT,true,true,SF>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( col_+1UL )
+ :( col_ ) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( col_ )
+ :( col_+1UL ) )
+ :( size() ) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ matrix_(i,col_) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address can alias with the dense column. In
+// contrast to the isAliased() function this function is allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,true,true,SF>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can alias with the given dense column \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address can alias with the dense column. In
+// contrast to the isAliased() function this function is allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename MT2 // Data type of the foreign dense column
+ , bool SO2 // Storage order of the foreign dense column
+ , bool SF2 > // Symmetry flag of the foreign dense column
+inline bool Column<MT,true,true,SF>::canAlias( const Column<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( alias->matrix_ ) && ( col_ == alias->col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense column. In
+// contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,true,true,SF>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is aliased with the given dense column \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense column. In
+// contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename MT2 // Data type of the foreign dense column
+ , bool SO2 // Storage order of the foreign dense column
+ , bool SF2 > // Symmetry flag of the foreign dense column
+inline bool Column<MT,true,true,SF>::isAliased( const Column<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( col_ == alias->col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is properly aligned in memory.
+//
+// \return \a true in case the dense column is aligned, \a false if not.
+//
+// This function returns whether the dense column is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of the dense column are guaranteed to conform to the
+// alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline bool Column<MT,true,true,SF>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can be used in SMP assignments.
+//
+// \return \a true in case the dense column can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the dense column can be used in SMP assignments. In contrast
+// to the \a smpAssignable member enumeration, which is based solely on compile time information,
+// this function additionally provides runtime information (as for instance the current size of
+// the dense column).
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline bool Column<MT,true,true,SF>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense column. The index must
+// be smaller than the number of matrix rows. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE typename Column<MT,true,true,SF>::SIMDType
+ Column<MT,true,true,SF>::load( size_t index ) const noexcept
+{
+ return matrix_.load( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense column. The
+// index must be smaller than the number of matrix rows. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE typename Column<MT,true,true,SF>::SIMDType
+ Column<MT,true,true,SF>::loada( size_t index ) const noexcept
+{
+ return matrix_.loada( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense column. The
+// index must be smaller than the number of matrix rows. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE typename Column<MT,true,true,SF>::SIMDType
+ Column<MT,true,true,SF>::loadu( size_t index ) const noexcept
+{
+ return matrix_.loadu( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store a specific SIMD element of the dense column. The index must
+// be smaller than the number of matrix rows. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE void
+ Column<MT,true,true,SF>::store( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.store( index, col_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store a specific SIMD element of the dense column. The
+// index must be smaller than the number of matrix rows. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE void
+ Column<MT,true,true,SF>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.storea( index, col_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store a specific SIMD element of the dense column. The
+// index must be smaller than the number of matrix rows. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE void
+ Column<MT,true,true,SF>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.storeu( index, col_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store a specific SIMD element of the dense
+// column. The index must be smaller than the number of matrix rows. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE void
+ Column<MT,true,true,SF>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.stream( index, col_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ Column<MT,true,true,SF>::assign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) = (~rhs)[i ];
+ matrix_(i+1UL,col_) = (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) = (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ Column<MT,true,true,SF>::assign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t rows( size() );
+
+ const size_t ipos( ( remainder )?( rows & size_t(-SIMDSIZE) ):( rows ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ if( useStreaming && rows > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( this ) )
+ {
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ else
+ {
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,true,true,SF>::assign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),col_) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ Column<MT,true,true,SF>::addAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) += (~rhs)[i ];
+ matrix_(i+1UL,col_) += (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) += (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ Column<MT,true,true,SF>::addAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t rows( size() );
+
+ const size_t ipos( ( remainder )?( rows & size_t(-SIMDSIZE) ):( rows ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left += *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,true,true,SF>::addAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),col_) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ Column<MT,true,true,SF>::subAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) -= (~rhs)[i ];
+ matrix_(i+1UL,col_) -= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) -= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ Column<MT,true,true,SF>::subAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t rows( size() );
+
+ const size_t ipos( ( remainder )?( rows & size_t(-SIMDSIZE) ):( rows ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left -= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,true,true,SF>::subAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),col_) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ Column<MT,true,true,SF>::multAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) *= (~rhs)[i ];
+ matrix_(i+1UL,col_) *= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) *= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ Column<MT,true,true,SF>::multAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t rows( size() );
+
+ const size_t ipos( ( remainder )?( rows & size_t(-SIMDSIZE) ):( rows ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left *= *right; ++left, ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,true,true,SF>::multAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),col_) = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ Column<MT,true,true,SF>::divAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) /= (~rhs)[i ];
+ matrix_(i+1UL,col_) /= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) /= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ Column<MT,true,true,SF>::divAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t rows( size() );
+
+ const size_t ipos( rows & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<rows; ++i ) {
+ *left /= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR GENERAL ROW-MAJOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Column for general row-major dense matrices.
+// \ingroup views
+//
+// This specialization of Column adapts the class template to the requirements of general
+// row-major dense matrices.
+*/
+template< typename MT > // Type of the dense matrix
+class Column<MT,false,true,false>
+ : public DenseVector< Column<MT,false,true,false>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Column<MT,false,true,false> This; //!< Type of this Column instance.
+ typedef DenseVector<This,false> BaseType; //!< Base type of this Column instance.
+ typedef ColumnTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the column elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Column& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant column value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant column value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant column value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant column value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+ //**********************************************************************************************
+
+ //**ColumnIterator class definition*************************************************************
+ /*!\brief Iterator over the elements of the dense column.
+ */
+ template< typename MatrixType > // Type of the dense matrix
+ class ColumnIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Return type for the access to the value of a dense element.
+ typedef If_< IsConst<MatrixType>, ConstReference_<MatrixType>, Reference_<MatrixType> > Reference;
+
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef RemoveReference_<Reference> ValueType; //!< Type of the underlying elements.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef Reference ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the ColumnIterator class.
+ */
+ inline ColumnIterator() noexcept
+ : matrix_( nullptr ) // The dense matrix containing the column.
+ , row_ ( 0UL ) // The current row index.
+ , column_( 0UL ) // The current column index.
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor of the ColumnIterator class.
+ //
+ // \param matrix The matrix containing the column.
+ // \param row The row index.
+ // \param column The column index.
+ */
+ inline ColumnIterator( MatrixType& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // The dense matrix containing the column.
+ , row_ ( row ) // The current row index.
+ , column_( column ) // The current column index.
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different ColumnIterator instances.
+ //
+ // \param it The column iterator to be copied.
+ */
+ template< typename MatrixType2 >
+ inline ColumnIterator( const ColumnIterator<MatrixType2>& it ) noexcept
+ : matrix_( it.matrix_ ) // The dense matrix containing the column.
+ , row_ ( it.row_ ) // The current row index.
+ , column_( it.column_ ) // The current column index.
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline ColumnIterator& operator+=( size_t inc ) noexcept {
+ row_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline ColumnIterator& operator-=( size_t dec ) noexcept {
+ row_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ColumnIterator& operator++() noexcept {
+ ++row_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ColumnIterator operator++( int ) noexcept {
+ const ColumnIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline ColumnIterator& operator--() noexcept {
+ --row_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ColumnIterator operator--( int ) noexcept {
+ const ColumnIterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Subscript operator***********************************************************************
+ /*!\brief Direct access to the dense column elements.
+ //
+ // \param index Access index.
+ // \return Reference to the accessed value.
+ */
+ inline ReferenceType operator[]( size_t index ) const {
+ return (*matrix_)(row_+index,column_);
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the dense vector element at the current iterator position.
+ //
+ // \return The current value of the dense element.
+ */
+ inline ReferenceType operator*() const {
+ return (*matrix_)(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the dense vector element at the current iterator position.
+ //
+ // \return Reference to the dense vector element at the current iterator position.
+ */
+ inline PointerType operator->() const {
+ return &(*matrix_)(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ColumnIterator objects.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator==( const ColumnIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ == rhs.row_ ) && ( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ColumnIterator objects.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ template< typename MatrixType2 >
+ inline bool operator!=( const ColumnIterator<MatrixType2>& rhs ) const noexcept {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two ColumnIterator objects.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator<( const ColumnIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ < rhs.row_ ) && ( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two ColumnIterator objects.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator>( const ColumnIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ > rhs.row_ ) && ( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two ColumnIterator objects.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator<=( const ColumnIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ <= rhs.row_ ) && ( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two ColumnIterator objects.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator>=( const ColumnIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ >= rhs.row_ ) && ( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two column iterators.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return The number of elements between the two column iterators.
+ */
+ inline DifferenceType operator-( const ColumnIterator& rhs ) const noexcept {
+ return row_ - rhs.row_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a ColumnIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ColumnIterator operator+( const ColumnIterator& it, size_t inc ) noexcept {
+ return ColumnIterator( *it.matrix_, it.row_+inc, it.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a ColumnIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const ColumnIterator operator+( size_t inc, const ColumnIterator& it ) noexcept {
+ return ColumnIterator( *it.matrix_, it.row_+inc, it.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a ColumnIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param inc The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const ColumnIterator operator-( const ColumnIterator& it, size_t dec ) noexcept {
+ return ColumnIterator( *it.matrix_, it.row_-dec, it.column_ );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MatrixType* matrix_; //!< The dense matrix containing the column.
+ size_t row_; //!< The current row index.
+ size_t column_; //!< The current column index.
+ //*******************************************************************************************
+
+ //**Friend declarations**********************************************************************
+ template< typename MatrixType2 > friend class ColumnIterator;
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef ColumnIterator<const MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, ColumnIterator<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Column( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Column& operator=( const ElementType& rhs );
+ inline Column& operator=( initializer_list<ElementType> list );
+ inline Column& operator=( const Column& rhs );
+
+ template< typename VT > inline Column& operator= ( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator+=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator-=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator/=( const DenseVector<VT,false>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Column >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Column >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline Column& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias ( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool canAlias ( const Column<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool isAliased( const Column<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void addAssign ( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void addAssign ( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void subAssign ( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void subAssign ( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void multAssign( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void multAssign( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void divAssign ( const DenseVector <VT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the column.
+ const size_t col_; //!< The index of the column in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 > friend class Column;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Column<MT2,SO2,DF2,SF2>& column ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Column<MT2,SO2,DF2,SF2>& a, const Column<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryDivAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Column<MT2,SO2,DF2,SF2> > derestrict( Column<MT2,SO2,DF2,SF2>& column );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Column.
+//
+// \param matrix The matrix containing the column.
+// \param index The index of the column.
+// \exception std::invalid_argument Invalid column access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline Column<MT,false,true,false>::Column( MT& matrix, size_t index )
+ : matrix_( matrix ) // The dense matrix containing the column
+ , col_ ( index ) // The index of the column in the matrix
+{
+ if( matrix_.columns() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid column access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::Reference
+ Column<MT,false,true,false>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return matrix_(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::ConstReference
+ Column<MT,false,true,false>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return const_cast<const MT&>( matrix_ )(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::Reference
+ Column<MT,false,true,false>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::ConstReference
+ Column<MT,false,true,false>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the column elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense column. Note that in case
+// of a row-major matrix you can NOT assume that the column elements lie adjacent to each other!
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::Pointer Column<MT,false,true,false>::data() noexcept
+{
+ return matrix_.data() + col_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the column elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense column. Note that in case
+// of a row-major matrix you can NOT assume that the column elements lie adjacent to each other!
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::ConstPointer Column<MT,false,true,false>::data() const noexcept
+{
+ return matrix_.data() + col_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::Iterator Column<MT,false,true,false>::begin()
+{
+ return Iterator( matrix_, 0UL, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::ConstIterator
+ Column<MT,false,true,false>::begin() const
+{
+ return ConstIterator( matrix_, 0UL, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::ConstIterator
+ Column<MT,false,true,false>::cbegin() const
+{
+ return ConstIterator( matrix_, 0UL, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::Iterator Column<MT,false,true,false>::end()
+{
+ return Iterator( matrix_, size(), col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::ConstIterator
+ Column<MT,false,true,false>::end() const
+{
+ return ConstIterator( matrix_, size(), col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,false>::ConstIterator
+ Column<MT,false,true,false>::cend() const
+{
+ return ConstIterator( matrix_, size(), col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all column elements.
+//
+// \param rhs Scalar value to be assigned to all column elements.
+// \return Reference to the assigned column.
+//
+// This function homogeneously assigns the given value to all elements of the column. Note that in
+// case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
+// of the underlying matrix are modified.
+*/
+template< typename MT > // Type of the dense matrix
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator=( const ElementType& rhs )
+{
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( col_+1UL )
+ :( col_ ) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( col_ )
+ :( col_+1UL ) )
+ :( size() ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ matrix_(i,col_) = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all column elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to column.
+//
+// This assignment operator offers the option to directly assign to all elements of the dense
+// column by means of an initializer list. The column elements are assigned the values from the
+// given initializer list. Missing values are reset to their default state. Note that in case
+// the size of the initializer list exceeds the size of the column, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator=( initializer_list<ElementType> list )
+{
+ if( list.size() > size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to column" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), begin() ), end(), ElementType() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Column.
+//
+// \param rhs Dense column to be copied.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Column sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two columns don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator=( const Column& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Column sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator+=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAddAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAddAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator-=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !trySubAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpSubAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator*=( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryMultAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpMultAssign( left, tmp );
+ }
+ else {
+ smpMultAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator*=( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const ResultType right( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, right );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,false,true,false>&
+ Column<MT,false,true,false>::operator/=( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryDivAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpDivAssign( left, tmp );
+ }
+ else {
+ smpDivAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense column and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+//
+// This operator cannot be used for columns on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Column<MT,false,true,false> >&
+ Column<MT,false,true,false>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ return operator=( (*this) * rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense column by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// This operator cannot be used for columns on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Column<MT,false,true,false> >&
+ Column<MT,false,true,false>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ return operator=( (*this) / rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the column.
+//
+// \return The size of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Column<MT,false,true,false>::size() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense column.
+//
+// \return The capacity of the dense column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Column<MT,false,true,false>::capacity() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the column.
+//
+// \return The number of non-zero elements in the column.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of columns of the matrix containing the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Column<MT,false,true,false>::nonZeros() const
+{
+ const size_t rows( size() );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<rows; ++i )
+ if( !isDefault( matrix_(i,col_) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Column<MT,false,true,false>::reset()
+{
+ using blaze::clear;
+
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( col_+1UL )
+ :( col_ ) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( col_ )
+ :( col_+1UL ) )
+ :( size() ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ clear( matrix_(i,col_) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the column by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the column scaling.
+// \return Reference to the dense column.
+//
+// This function scales all elements of the column by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a column on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline Column<MT,false,true,false>& Column<MT,false,true,false>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( col_+1UL )
+ :( col_ ) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( col_ )
+ :( col_+1UL ) )
+ :( size() ) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ matrix_(i,col_) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address can alias with the dense column. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,false,true,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can alias with the given dense column \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address can alias with the dense column. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense column
+ , bool SO2 // Storage order of the foreign dense column
+ , bool SF2 > // Symmetry flag of the foreign dense column
+inline bool Column<MT,false,true,false>::canAlias( const Column<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( col_ == alias->col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense column. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,false,true,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is aliased with the given dense column \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense column. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense column
+ , bool SO2 // Storage order of the foreign dense column
+ , bool SF2 > // Symmetry flag of the foreign dense column
+inline bool Column<MT,false,true,false>::isAliased( const Column<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( col_ == alias->col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is properly aligned in memory.
+//
+// \return \a true in case the dense column is aligned, \a false if not.
+//
+// This function returns whether the dense column is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of the dense column are guaranteed to conform to the
+// alignment restrictions of the element type \a Type.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Column<MT,false,true,false>::isAligned() const noexcept
+{
+ return false;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can be used in SMP assignments.
+//
+// \return \a true in case the dense column can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the dense column can be used in SMP assignments. In contrast
+// to the \a smpAssignable member enumeration, which is based solely on compile time information,
+// this function additionally provides runtime information (as for instance the current size of
+// the dense column).
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Column<MT,false,true,false>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,true,false>::assign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) = (~rhs)[i ];
+ matrix_(i+1UL,col_) = (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) = (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,true,false>::assign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),col_) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,true,false>::addAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) += (~rhs)[i ];
+ matrix_(i+1UL,col_) += (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) += (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,true,false>::addAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),col_) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,true,false>::subAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) -= (~rhs)[i ];
+ matrix_(i+1UL,col_) -= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) -= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,true,false>::subAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),col_) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,true,false>::multAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) *= (~rhs)[i ];
+ matrix_(i+1UL,col_) *= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) *= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,true,false>::multAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),col_) = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,true,false>::divAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,col_) /= (~rhs)[i ];
+ matrix_(i+1UL,col_) /= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,col_) /= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SYMMETRIC ROW-MAJOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Column for symmetric row-major dense matrices.
+// \ingroup views
+//
+// This specialization of Column adapts the class template to the requirements of symmetric
+// row-major dense matrices.
+*/
+template< typename MT > // Type of the dense matrix
+class Column<MT,false,true,true>
+ : public DenseVector< Column<MT,false,true,true>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Column<MT,false,true,true> This; //!< Type of this Column instance.
+ typedef DenseVector<This,false> BaseType; //!< Base type of this Column instance.
+ typedef ColumnTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the column elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the column elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Column& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant column value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant column value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant column value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant column value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Column( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Column& operator=( const ElementType& rhs );
+ inline Column& operator=( initializer_list<ElementType> list );
+ inline Column& operator=( const Column& rhs );
+
+ template< typename VT > inline Column& operator= ( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator+=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator-=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator/=( const DenseVector<VT,false>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Column >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Column >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline Column& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDSub< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDMult< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDDiv< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool canAlias( const Column<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool isAliased( const Column<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,false>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the column.
+ const size_t col_; //!< The index of the column in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 > friend class Column;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Column<MT2,SO2,DF2,SF2>& column ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Column<MT2,SO2,DF2,SF2>& a, const Column<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryDivAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Column<MT2,SO2,DF2,SF2> > derestrict( Column<MT2,SO2,DF2,SF2>& column );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Column.
+//
+// \param matrix The matrix containing the column.
+// \param index The index of the column.
+// \exception std::invalid_argument Invalid column access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline Column<MT,false,true,true>::Column( MT& matrix, size_t index )
+ : matrix_( matrix ) // The dense matrix containing the column
+ , col_ ( index ) // The index of the column in the matrix
+{
+ if( matrix_.columns() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid column access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::Reference
+ Column<MT,false,true,true>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return matrix_(col_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::ConstReference
+ Column<MT,false,true,true>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return const_cast<const MT&>( matrix_ )(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::Reference
+ Column<MT,false,true,true>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::ConstReference
+ Column<MT,false,true,true>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the column elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense column. Note that in case
+// of a row-major matrix you can NOT assume that the column elements lie adjacent to each other!
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::Pointer Column<MT,false,true,true>::data() noexcept
+{
+ return matrix_.data( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the column elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense column. Note that in case
+// of a row-major matrix you can NOT assume that the column elements lie adjacent to each other!
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::ConstPointer
+ Column<MT,false,true,true>::data() const noexcept
+{
+ return matrix_.data( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::Iterator Column<MT,false,true,true>::begin()
+{
+ return matrix_.begin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::ConstIterator Column<MT,false,true,true>::begin() const
+{
+ return matrix_.cbegin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::ConstIterator Column<MT,false,true,true>::cbegin() const
+{
+ return matrix_.cbegin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::Iterator Column<MT,false,true,true>::end()
+{
+ return matrix_.end( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::ConstIterator Column<MT,false,true,true>::end() const
+{
+ return matrix_.cend( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Column<MT,false,true,true>::ConstIterator Column<MT,false,true,true>::cend() const
+{
+ return matrix_.cend( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all column elements.
+//
+// \param rhs Scalar value to be assigned to all column elements.
+// \return Reference to the assigned column.
+*/
+template< typename MT > // Type of the dense matrix
+inline Column<MT,false,true,true>& Column<MT,false,true,true>::operator=( const ElementType& rhs )
+{
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( col_+1UL )
+ :( col_ ) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( col_ )
+ :( col_+1UL ) )
+ :( size() ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ matrix_(col_,j) = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all column elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to column.
+//
+// This assignment operator offers the option to directly assign to all elements of the dense
+// column by means of an initializer list. The column elements are assigned the values from the
+// given initializer list. Missing values are reset to their default state. Note that in case
+// the size of the initializer list exceeds the size of the column, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Column<MT,false,true,true>&
+ Column<MT,false,true,true>::operator=( initializer_list<ElementType> list )
+{
+ if( list.size() > size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to column" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), begin() ), end(), ElementType() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Column.
+//
+// \param rhs Dense column to be copied.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Column sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two columns don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Column<MT,false,true,true>& Column<MT,false,true,true>::operator=( const Column& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Column sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,true,true>&
+ Column<MT,false,true,true>::operator=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,true,true>&
+ Column<MT,false,true,true>::operator+=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAddAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAddAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,true,true>&
+ Column<MT,false,true,true>::operator-=( const Vector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !trySubAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpSubAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,false,true,true>&
+ Column<MT,false,true,true>::operator*=( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryMultAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpMultAssign( left, tmp );
+ }
+ else {
+ smpMultAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the dense column.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,false,true,true>&
+ Column<MT,false,true,true>::operator*=( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const ResultType right( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, right );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,false,true,true>&
+ Column<MT,false,true,true>::operator/=( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryDivAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpDivAssign( left, tmp );
+ }
+ else {
+ smpDivAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense column and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+//
+// This operator cannot be used for columns on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Column<MT,false,true,true> >&
+ Column<MT,false,true,true>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ return operator=( (*this) * rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense column by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// This operator cannot be used for columns on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Column<MT,false,true,true> >&
+ Column<MT,false,true,true>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ return operator=( (*this) / rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the column.
+//
+// \return The size of the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Column<MT,false,true,true>::size() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense column.
+//
+// \return The capacity of the dense column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Column<MT,false,true,true>::capacity() const noexcept
+{
+ return matrix_.capacity( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the column.
+//
+// \return The number of non-zero elements in the column.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of rows of the matrix containing the column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Column<MT,false,true,true>::nonZeros() const
+{
+ return matrix_.nonZeros( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Column<MT,false,true,true>::reset()
+{
+ matrix_.reset( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the column by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the column scaling.
+// \return Reference to the dense column.
+//
+// This function scales all elements of the column by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a column on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline Column<MT,false,true,true>& Column<MT,false,true,true>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( col_+1UL )
+ :( col_ ) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( col_ )
+ :( col_+1UL ) )
+ :( size() ) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ matrix_(col_,j) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address can alias with the dense column. In
+// contrast to the isAliased() function this function is allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,false,true,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can alias with the given dense column \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address can alias with the dense column. In
+// contrast to the isAliased() function this function is allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense column
+ , bool SO2 // Storage order of the foreign dense column
+ , bool SF2 > // Symmetry flag of the foreign dense column
+inline bool Column<MT,false,true,true>::canAlias( const Column<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( alias->matrix_ ) && ( col_ == alias->col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense column. In
+// contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,false,true,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is aliased with the given dense column \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense column, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense column. In
+// contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense column
+ , bool SO2 // Storage order of the foreign dense column
+ , bool SF2 > // Symmetry flag of the foreign dense column
+inline bool Column<MT,false,true,true>::isAliased( const Column<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( col_ == alias->col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column is properly aligned in memory.
+//
+// \return \a true in case the dense column is aligned, \a false if not.
+//
+// This function returns whether the dense column is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of the dense column are guaranteed to conform to the
+// alignment restrictions of the element type \a Type.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Column<MT,false,true,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense column can be used in SMP assignments.
+//
+// \return \a true in case the dense column can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the dense column can be used in SMP assignments. In contrast
+// to the \a smpAssignable member enumeration, which is based solely on compile time information,
+// this function additionally provides runtime information (as for instance the current size of
+// the dense column).
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Column<MT,false,true,true>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense column. The index must
+// be smaller than the number of matrix rows. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Column<MT,false,true,true>::SIMDType
+ Column<MT,false,true,true>::load( size_t index ) const noexcept
+{
+ return matrix_.load( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense column. The
+// index must be smaller than the number of matrix rows. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Column<MT,false,true,true>::SIMDType
+ Column<MT,false,true,true>::loada( size_t index ) const noexcept
+{
+ return matrix_.loada( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense column. The
+// index must be smaller than the number of matrix rows. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Column<MT,false,true,true>::SIMDType
+ Column<MT,false,true,true>::loadu( size_t index ) const noexcept
+{
+ return matrix_.loadu( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store a specific SIMD element of the dense column. The index must
+// be smaller than the number of matrix rows. This function must \b NOT be called explicitly! It
+// is used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Column<MT,false,true,true>::store( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.store( col_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store a specific SIMD element of the dense column. The
+// index must be smaller than the number of matrix rows. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Column<MT,false,true,true>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.storea( col_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store a specific SIMD element of the dense column. The
+// index must be smaller than the number of matrix rows. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Column<MT,false,true,true>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.storeu( col_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the dense column.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store a specific SIMD element of the dense
+// column. The index must be smaller than the number of matrix rows. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Column<MT,false,true,true>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.stream( col_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ Column<MT,false,true,true>::assign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(col_,j ) = (~rhs)[j ];
+ matrix_(col_,j+1UL) = (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(col_,jpos) = (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ Column<MT,false,true,true>::assign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t columns( size() );
+
+ const size_t jpos( ( remainder )?( columns & size_t(-SIMDSIZE) ):( columns ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ if( useStreaming && columns > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( this ) )
+ {
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ else
+ {
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,true,true>::assign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(col_,element->index()) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ Column<MT,false,true,true>::addAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(col_,j ) += (~rhs)[j ];
+ matrix_(col_,j+1UL) += (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(col_,jpos) += (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ Column<MT,false,true,true>::addAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t columns( size() );
+
+ const size_t jpos( ( remainder )?( columns & size_t(-SIMDSIZE) ):( columns ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left += *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,true,true>::addAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(col_,element->index()) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ Column<MT,false,true,true>::subAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(col_,j ) -= (~rhs)[j ];
+ matrix_(col_,j+1UL) -= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(col_,jpos) -= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ Column<MT,false,true,true>::subAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t columns( size() );
+
+ const size_t jpos( ( remainder )?( columns & size_t(-SIMDSIZE) ):( columns ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left -= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,true,true>::subAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(col_,element->index()) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ Column<MT,false,true,true>::multAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(col_,j ) *= (~rhs)[j ];
+ matrix_(col_,j+1UL) *= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(col_,jpos) *= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ Column<MT,false,true,true>::multAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t columns( size() );
+
+ const size_t jpos( ( remainder )?( columns & size_t(-SIMDSIZE) ):( columns ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left *= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,true,true>::multAssign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(col_,element->index()) = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ Column<MT,false,true,true>::divAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(col_,j ) /= (~rhs)[j ];
+ matrix_(col_,j+1UL) /= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(col_,jpos) /= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Column<MT,false,true,true>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ Column<MT,false,true,true>::divAssign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t columns( size() );
+
+ const size_t jpos( columns & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<columns; ++j ) {
+ *left /= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/column/Sparse.h b/src/cpu/blaze/math/views/column/Sparse.h
new file mode 100644
index 00000000..401624ba
--- /dev/null
+++ b/src/cpu/blaze/math/views/column/Sparse.h
@@ -0,0 +1,5360 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/column/Sparse.h
+// \brief Column specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_COLUMN_SPARSE_H_
+#define _BLAZE_MATH_VIEWS_COLUMN_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/ColumnVector.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/View.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/ColumnTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/views/column/BaseTemplate.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Column for columns on column-major sparse matrices.
+// \ingroup views
+//
+// This specialization of Column adapts the class template to the requirements of column-major
+// sparse matrices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+class Column<MT,true,false,SF>
+ : public SparseVector< Column<MT,true,false,SF>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Column<MT,true,false,SF> This; //!< Type of this Column instance.
+ typedef SparseVector<This,false> BaseType; //!< Base type of this Column instance.
+ typedef ColumnTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the column elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Column& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant column value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant column value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Column( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Column& operator=( const Column& rhs );
+
+ template< typename VT > inline Column& operator= ( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator= ( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator+=( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator+=( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator-=( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator-=( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator/=( const DenseVector<VT,false>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Column >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Column >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline Iterator set ( size_t index, const ElementType& value );
+ inline Iterator insert ( size_t index, const ElementType& value );
+ inline void erase ( size_t index );
+ inline Iterator erase ( Iterator pos );
+ inline Iterator erase ( Iterator first, Iterator last );
+ inline void reserve( size_t n );
+ template< typename Other > inline Column& scale ( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index );
+ inline ConstIterator find ( size_t index ) const;
+ inline Iterator lowerBound( size_t index );
+ inline ConstIterator lowerBound( size_t index ) const;
+ inline Iterator upperBound( size_t index );
+ inline ConstIterator upperBound( size_t index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append( size_t index, const ElementType& value, bool check=false );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void addAssign( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void addAssign( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void subAssign( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void subAssign( const SparseVector<VT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t extendCapacity() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The sparse matrix containing the column.
+ const size_t col_; //!< The index of the column in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Column<MT2,SO2,DF2,SF2>& column ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Column<MT2,SO2,DF2,SF2>& a, const Column<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Column<MT2,SO2,DF2,SF2> > derestrict( Column<MT2,SO2,DF2,SF2>& column );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Column.
+//
+// \param matrix The matrix containing the column.
+// \param index The index of the column.
+// \exception std::invalid_argument Invalid column access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline Column<MT,true,false,SF>::Column( MT& matrix, size_t index )
+ : matrix_( matrix ) // The sparse matrix containing the column
+ , col_ ( index ) // The index of the column in the matrix
+{
+ if( matrix_.columns() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid column access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Reference
+ Column<MT,true,false,SF>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return matrix_(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstReference
+ Column<MT,true,false,SF>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return const_cast<const MT&>( matrix_ )(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Reference
+ Column<MT,true,false,SF>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstReference
+ Column<MT,true,false,SF>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator Column<MT,true,false,SF>::begin()
+{
+ return matrix_.begin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstIterator Column<MT,true,false,SF>::begin() const
+{
+ return matrix_.cbegin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstIterator Column<MT,true,false,SF>::cbegin() const
+{
+ return matrix_.cbegin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator Column<MT,true,false,SF>::end()
+{
+ return matrix_.end( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstIterator Column<MT,true,false,SF>::end() const
+{
+ return matrix_.cend( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstIterator Column<MT,true,false,SF>::cend() const
+{
+ return matrix_.cend( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Column.
+//
+// \param rhs Sparse column to be copied.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Column sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two columns don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator=( const Column& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && col_ == rhs.col_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Column sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ left.reserve( rhs.nonZeros() );
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for dense vectors.
+//
+// \param rhs Dense vector to be assigned.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ left.reset();
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for sparse vectors.
+//
+// \param rhs Sparse vector to be assigned.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator=( const SparseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ left.reserve( right.nonZeros() );
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a dense vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be added to the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator+=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a sparse vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be added to the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator+=( const SparseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a dense vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be subtracted from the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator-=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a sparse vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be subtracted from the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator-=( const SparseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator*=( const Vector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::operator/=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const DivType tmp( *this / (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse column
+// and a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse column.
+//
+// Via this operator it is possible to scale the sparse column. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for columns on lower
+// or upper unitriangular matrices. The attempt to scale such a column results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse column must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Column<MT,true,false,SF> >&
+ Column<MT,true,false,SF>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse column by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the sparse column.
+//
+// Via this operator it is possible to scale the sparse column. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for columns on lower
+// or upper unitriangular matrices. The attempt to scale such a column results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse column must either support the multiplication assignment operator for the given
+// floating point data type or the division assignment operator for the given integral data
+// type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Column<MT,true,false,SF> >&
+ Column<MT,true,false,SF>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= tmp;
+ }
+ else {
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the sparse column.
+//
+// \return The size of the sparse column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline size_t Column<MT,true,false,SF>::size() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse column.
+//
+// \return The capacity of the sparse column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline size_t Column<MT,true,false,SF>::capacity() const noexcept
+{
+ return matrix_.capacity( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the column.
+//
+// \return The number of non-zero elements in the column.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of rows of the matrix containing the column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline size_t Column<MT,true,false,SF>::nonZeros() const
+{
+ return matrix_.nonZeros( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline void Column<MT,true,false,SF>::reset()
+{
+ matrix_.reset( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse column.
+//
+// \param index The index of the element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+//
+// This function sets the value of an element of the sparse column. In case the sparse column
+// already contains an element with index \a index its value is modified, else a new element
+// with the given \a value is inserted.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator
+ Column<MT,true,false,SF>::set( size_t index, const ElementType& value )
+{
+ return matrix_.set( index, col_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse column.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid sparse column access index.
+//
+// This function inserts a new element into the sparse column. However, duplicate elements
+// are not allowed. In case the sparse column already contains an element at index \a index,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator
+ Column<MT,true,false,SF>::insert( size_t index, const ElementType& value )
+{
+ return matrix_.insert( index, col_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse column.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline void Column<MT,true,false,SF>::erase( size_t index )
+{
+ matrix_.erase( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse column.
+//
+// \param pos Iterator to the element to be erased.
+// \return void
+//
+// This function erases an element from the sparse column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator Column<MT,true,false,SF>::erase( Iterator pos )
+{
+ return matrix_.erase( col_, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse column.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the sparse column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator
+ Column<MT,true,false,SF>::erase( Iterator first, Iterator last )
+{
+ return matrix_.erase( col_, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse column.
+//
+// \param n The new minimum capacity of the sparse column.
+// \return void
+//
+// This function increases the capacity of the sparse column to at least \a n elements. The
+// current values of the column elements are preserved.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+void Column<MT,true,false,SF>::reserve( size_t n )
+{
+ matrix_.reserve( col_, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse column by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the column scaling.
+// \return Reference to the sparse column.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the scalar value
+inline Column<MT,true,false,SF>& Column<MT,true,false,SF>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating a new sparse column capacity.
+//
+// \return The new sparse column capacity.
+//
+// This function calculates a new column capacity based on the current capacity of the sparse
+// column. Note that the new capacity is restricted to the interval \f$[7..size]\f$.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline size_t Column<MT,true,false,SF>::extendCapacity() const noexcept
+{
+ using blaze::max;
+ using blaze::min;
+
+ size_t nonzeros( 2UL*capacity()+1UL );
+ nonzeros = max( nonzeros, 7UL );
+ nonzeros = min( nonzeros, size() );
+
+ BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific column element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// column. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse column (the end() iterator) is returned. Note that
+// the returned sparse column iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator Column<MT,true,false,SF>::find( size_t index )
+{
+ return matrix_.find( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific column element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// column. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse column (the end() iterator) is returned. Note that
+// the returned sparse column iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstIterator
+ Column<MT,true,false,SF>::find( size_t index ) const
+{
+ return matrix_.find( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator Column<MT,true,false,SF>::lowerBound( size_t index )
+{
+ return matrix_.lowerBound( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstIterator
+ Column<MT,true,false,SF>::lowerBound( size_t index ) const
+{
+ return matrix_.lowerBound( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::Iterator Column<MT,true,false,SF>::upperBound( size_t index )
+{
+ return matrix_.upperBound( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Column<MT,true,false,SF>::ConstIterator
+ Column<MT,true,false,SF>::upperBound( size_t index ) const
+{
+ return matrix_.upperBound( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the sparse column.
+//
+// \param index The index of the new element. The index must be smaller than the number of matrix rows.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse column with elements. It appends
+// a new element to the end of the sparse column without any memory allocation. Therefore it is
+// strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the sparse column
+// - the current number of non-zero elements must be smaller than the capacity of the column
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline void Column<MT,true,false,SF>::append( size_t index, const ElementType& value, bool check )
+{
+ matrix_.append( index, col_, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse column can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse column, \a false if not.
+//
+// This function returns whether the given address can alias with the sparse column. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,true,false,SF>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse column is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse column, \a false if not.
+//
+// This function returns whether the given address is aliased with the sparse column. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,true,false,SF>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,true,false,SF>::assign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ for( size_t i=0UL; i<size(); ++i )
+ {
+ if( matrix_.nonZeros( col_ ) == matrix_.capacity( col_ ) )
+ matrix_.reserve( col_, extendCapacity() );
+
+ matrix_.append( i, col_, (~rhs)[i], true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,true,false,SF>::assign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ matrix_.append( element->index(), col_, element->value(), true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,true,false,SF>::addAssign( const DenseVector<VT,false>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ matrix_.reset( col_ );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,true,false,SF>::addAssign( const SparseVector<VT,false>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ matrix_.reset( col_ );
+ matrix_.reserve( col_, tmp.nonZeros() );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,true,false,SF>::subAssign( const DenseVector<VT,false>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ matrix_.reset( col_ );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,true,false,SF>::subAssign( const SparseVector<VT,false>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ matrix_.reset( col_ );
+ matrix_.reserve( col_, tmp.nonZeros() );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR GENERAL ROW-MAJOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Column for general row-major sparse matrices.
+// \ingroup views
+//
+// This specialization of Column adapts the class template to the requirements of general
+// row-major sparse matrices.
+*/
+template< typename MT > // Type of the sparse matrix
+class Column<MT,false,false,false>
+ : public SparseVector< Column<MT,false,false,false>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Column<MT,false,false,false> This; //!< Type of this Column instance.
+ typedef SparseVector<This,false> BaseType; //!< Base type of this Column instance.
+ typedef ColumnTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the column elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Column& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant column value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant column value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+ //**********************************************************************************************
+
+ //**ColumnElement class definition**************************************************************
+ /*!\brief Access proxy for a specific element of the sparse column.
+ */
+ template< typename MatrixType // Type of the sparse matrix
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class ColumnElement : private SparseElement
+ {
+ private:
+ //*******************************************************************************************
+ //! Compilation switch for the return type of the value member function.
+ /*! The \a returnConst compile time constant expression represents a compilation switch for
+ the return type of the value member function. In case the given matrix type \a MatrixType
+ is const qualified, \a returnConst will be set to 1 and the value member function will
+ return a reference to const. Otherwise \a returnConst will be set to 0 and the value
+ member function will offer write access to the sparse matrix elements. */
+ enum : bool { returnConst = IsConst<MatrixType>::value };
+ //*******************************************************************************************
+
+ //**Type definitions*************************************************************************
+ //! Type of the underlying sparse elements.
+ typedef typename std::iterator_traits<IteratorType>::value_type SET;
+
+ typedef Reference_<SET> RT; //!< Reference type of the underlying sparse element.
+ typedef ConstReference_<SET> CRT; //!< Reference-to-const type of the underlying sparse element.
+ //*******************************************************************************************
+
+ public:
+ //**Type definitions*************************************************************************
+ typedef ValueType_<SET> ValueType; //!< The value type of the row element.
+ typedef size_t IndexType; //!< The index type of the row element.
+ typedef IfTrue_<returnConst,CRT,RT> Reference; //!< Reference return type
+ typedef CRT ConstReference; //!< Reference-to-const return type.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ColumnElement class.
+ //
+ // \param pos Iterator to the current position within the sparse column.
+ // \param row The row index.
+ */
+ inline ColumnElement( IteratorType pos, size_t row )
+ : pos_( pos ) // Iterator to the current position within the sparse column
+ , row_( row ) // Index of the according row
+ {}
+ //*******************************************************************************************
+
+ //**Assignment operator**********************************************************************
+ /*!\brief Assignment to the accessed sparse column element.
+ //
+ // \param value The new value of the sparse column element.
+ // \return Reference to the sparse column element.
+ */
+ template< typename T > inline ColumnElement& operator=( const T& v ) {
+ *pos_ = v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment to the accessed sparse column element.
+ //
+ // \param value The right-hand side value for the addition.
+ // \return Reference to the sparse column element.
+ */
+ template< typename T > inline ColumnElement& operator+=( const T& v ) {
+ *pos_ += v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment to the accessed sparse column element.
+ //
+ // \param value The right-hand side value for the subtraction.
+ // \return Reference to the sparse column element.
+ */
+ template< typename T > inline ColumnElement& operator-=( const T& v ) {
+ *pos_ -= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Multiplication assignment operator*******************************************************
+ /*!\brief Multiplication assignment to the accessed sparse column element.
+ //
+ // \param value The right-hand side value for the multiplication.
+ // \return Reference to the sparse column element.
+ */
+ template< typename T > inline ColumnElement& operator*=( const T& v ) {
+ *pos_ *= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Division assignment operator*************************************************************
+ /*!\brief Division assignment to the accessed sparse column element.
+ //
+ // \param value The right-hand side value for the division.
+ // \return Reference to the sparse column element.
+ */
+ template< typename T > inline ColumnElement& operator/=( const T& v ) {
+ *pos_ /= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const ColumnElement* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse column element.
+ //
+ // \return The current value of the sparse column element.
+ */
+ inline Reference value() const {
+ return pos_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline IndexType index() const {
+ return row_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current position within the sparse column.
+ size_t row_; //!< Index of the according row.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**ColumnIterator class definition*************************************************************
+ /*!\brief Iterator over the elements of the sparse column.
+ */
+ template< typename MatrixType // Type of the sparse matrix
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class ColumnIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef ColumnElement<MatrixType,IteratorType> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the ColumnIterator class.
+ */
+ inline ColumnIterator()
+ : matrix_( nullptr ) // The sparse matrix containing the column.
+ , row_ ( 0UL ) // The current row index.
+ , column_( 0UL ) // The current column index.
+ , pos_ () // Iterator to the current sparse element.
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor of the ColumnIterator class.
+ //
+ // \param matrix The matrix containing the column.
+ // \param row The row index.
+ // \param column The column index.
+ */
+ inline ColumnIterator( MatrixType& matrix, size_t row, size_t column )
+ : matrix_( &matrix ) // The sparse matrix containing the column.
+ , row_ ( row ) // The current row index.
+ , column_( column ) // The current column index.
+ , pos_ () // Iterator to the current sparse element.
+ {
+ for( ; row_<matrix_->rows(); ++row_ ) {
+ pos_ = matrix_->find( row_, column_ );
+ if( pos_ != matrix_->end( row_ ) ) break;
+ }
+ }
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the ColumnIterator class.
+ //
+ // \param matrix The matrix containing the column.
+ // \param row The row index.
+ // \param column The column index.
+ // \param pos Initial position of the iterator
+ */
+ inline ColumnIterator( MatrixType& matrix, size_t row, size_t column, IteratorType pos )
+ : matrix_( &matrix ) // The sparse matrix containing the column.
+ , row_ ( row ) // The current row index.
+ , column_( column ) // The current column index.
+ , pos_ ( pos ) // Iterator to the current sparse element.
+ {
+ BLAZE_INTERNAL_ASSERT( matrix.find( row, column ) == pos, "Invalid initial iterator position" );
+ }
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different ColumnIterator instances.
+ //
+ // \param it The column iterator to be copied.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline ColumnIterator( const ColumnIterator<MatrixType2,IteratorType2>& it )
+ : matrix_( it.matrix_ ) // The sparse matrix containing the column.
+ , row_ ( it.row_ ) // The current row index.
+ , column_( it.column_ ) // The current column index.
+ , pos_ ( it.pos_ ) // Iterator to the current sparse element.
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline ColumnIterator& operator++() {
+ ++row_;
+ for( ; row_<matrix_->rows(); ++row_ ) {
+ pos_ = matrix_->find( row_, column_ );
+ if( pos_ != matrix_->end( row_ ) ) break;
+ }
+
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const ColumnIterator operator++( int ) {
+ const ColumnIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, row_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, row_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two ColumnIterator objects.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline bool operator==( const ColumnIterator<MatrixType2,IteratorType2>& rhs ) const {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ == rhs.row_ ) && ( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two ColumnIterator objects.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline bool operator!=( const ColumnIterator<MatrixType2,IteratorType2>& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two column iterators.
+ //
+ // \param rhs The right-hand side column iterator.
+ // \return The number of elements between the two column iterators.
+ */
+ inline DifferenceType operator-( const ColumnIterator& rhs ) const {
+ size_t counter( 0UL );
+ for( size_t i=rhs.row_; i<row_; ++i ) {
+ if( matrix_->find( i, column_ ) != matrix_->end( i ) )
+ ++counter;
+ }
+ return counter;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MatrixType* matrix_; //!< The sparse matrix containing the column.
+ size_t row_; //!< The current row index.
+ size_t column_; //!< The current column index.
+ IteratorType pos_; //!< Iterator to the current sparse element.
+ //*******************************************************************************************
+
+ //**Friend declarations**********************************************************************
+ template< typename MatrixType2, typename IteratorType2 > friend class ColumnIterator;
+ template< typename MT2, bool SO2, bool DF2, bool SF2 > friend class Column;
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef ColumnIterator< const MT, ConstIterator_<MT> > ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, ColumnIterator< MT, Iterator_<MT> > > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Column( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Column& operator= ( const Column& rhs );
+ template< typename VT > inline Column& operator= ( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator+=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator-=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator/=( const DenseVector<VT,false>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Column >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Column >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const;
+ inline size_t capacity() const;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline Iterator set ( size_t index, const ElementType& value );
+ inline Iterator insert ( size_t index, const ElementType& value );
+ inline void erase ( size_t index );
+ inline Iterator erase ( Iterator pos );
+ inline Iterator erase ( Iterator first, Iterator last );
+ inline void reserve( size_t n );
+ template< typename Other > inline Column& scale ( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index );
+ inline ConstIterator find ( size_t index ) const;
+ inline Iterator lowerBound( size_t index );
+ inline ConstIterator lowerBound( size_t index ) const;
+ inline Iterator upperBound( size_t index );
+ inline ConstIterator upperBound( size_t index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append( size_t index, const ElementType& value, bool check=false );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const;
+ template< typename Other > inline bool isAliased( const Other* alias ) const;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void addAssign( const Vector<VT,false>& rhs );
+ template< typename VT > inline void subAssign( const Vector<VT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The sparse matrix containing the column.
+ const size_t col_; //!< The index of the column in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Column<MT2,SO2,DF2,SF2>& column ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Column<MT2,SO2,DF2,SF2>& a, const Column<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Column<MT2,SO2,DF2,SF2> > derestrict( Column<MT2,SO2,DF2,SF2>& column );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Column.
+//
+// \param matrix The matrix containing the column.
+// \param index The index of the column.
+// \exception std::invalid_argument Invalid column access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline Column<MT,false,false,false>::Column( MT& matrix, size_t index )
+ : matrix_( matrix ) // The sparse matrix containing the column
+ , col_ ( index ) // The index of the column in the matrix
+{
+ if( matrix_.columns() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid column access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Reference
+ Column<MT,false,false,false>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return matrix_(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstReference
+ Column<MT,false,false,false>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return const_cast<const MT&>( matrix_ )(index,col_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Reference
+ Column<MT,false,false,false>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstReference
+ Column<MT,false,false,false>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator Column<MT,false,false,false>::begin()
+{
+ return Iterator( matrix_, 0UL, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstIterator
+ Column<MT,false,false,false>::begin() const
+{
+ return ConstIterator( matrix_, 0UL, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstIterator
+ Column<MT,false,false,false>::cbegin() const
+{
+ return ConstIterator( matrix_, 0UL, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator Column<MT,false,false,false>::end()
+{
+ return Iterator( matrix_, size(), col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstIterator
+ Column<MT,false,false,false>::end() const
+{
+ return ConstIterator( matrix_, size(), col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstIterator
+ Column<MT,false,false,false>::cend() const
+{
+ return ConstIterator( matrix_, size(), col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Column.
+//
+// \param rhs Sparse column to be copied.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Column sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two columns don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+inline Column<MT,false,false,false>&
+ Column<MT,false,false,false>::operator=( const Column& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && col_ == rhs.col_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Column sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ assign( left, tmp );
+ }
+ else {
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,false,false>&
+ Column<MT,false,false,false>::operator=( const Vector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const CompositeType_<VT> tmp( ~rhs );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,false,false>&
+ Column<MT,false,false,false>::operator+=( const Vector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,false,false>&
+ Column<MT,false,false,false>::operator-=( const Vector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,false,false>&
+ Column<MT,false,false,false>::operator*=( const Vector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,false,false>&
+ Column<MT,false,false,false>::operator/=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const DivType tmp( *this / (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse column
+// and a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse column.
+//
+// Via this operator it is possible to scale the sparse column. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for columns on lower
+// or upper unitriangular matrices. The attempt to scale such a column results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse column must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Column<MT,false,false,false> >&
+ Column<MT,false,false,false>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse column by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the sparse column.
+//
+// Via this operator it is possible to scale the sparse column. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for columns on lower
+// or upper unitriangular matrices. The attempt to scale such a column results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse column must either support the multiplication assignment operator for the given
+// floating point data type or the division assignment operator for the given integral data
+// type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Column<MT,false,false,false> >&
+ Column<MT,false,false,false>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= tmp;
+ }
+ else {
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the column.
+//
+// \return The size of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Column<MT,false,false,false>::size() const
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse column.
+//
+// \return The capacity of the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Column<MT,false,false,false>::capacity() const
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the column.
+//
+// \return The number of non-zero elements in the column.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of rows of the matrix containing the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Column<MT,false,false,false>::nonZeros() const
+{
+ size_t counter( 0UL );
+ for( ConstIterator element=begin(); element!=end(); ++element ) {
+ ++counter;
+ }
+ return counter;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Column<MT,false,false,false>::reset()
+{
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( col_+1UL )
+ :( col_ ) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( col_ )
+ :( col_+1UL ) )
+ :( size() ) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ matrix_.erase( i, col_ );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse column.
+//
+// \param index The index of the element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+//
+// This function sets the value of an element of the sparse column. In case the sparse column
+// already contains an element with index \a index its value is modified, else a new element
+// with the given \a value is inserted.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator
+ Column<MT,false,false,false>::set( size_t index, const ElementType& value )
+{
+ return Iterator( matrix_, index, col_, matrix_.set( index, col_, value ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse column.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid sparse column access index.
+//
+// This function inserts a new element into the sparse column. However, duplicate elements
+// are not allowed. In case the sparse column already contains an element at index \a index,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator
+ Column<MT,false,false,false>::insert( size_t index, const ElementType& value )
+{
+ return Iterator( matrix_, index, col_, matrix_.insert( index, col_, value ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse column.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Column<MT,false,false,false>::erase( size_t index )
+{
+ matrix_.erase( index, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse column.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator
+ Column<MT,false,false,false>::erase( Iterator pos )
+{
+ const size_t row( pos.row_ );
+
+ if( row == size() )
+ return pos;
+
+ matrix_.erase( row, pos.pos_ );
+ return Iterator( matrix_, row+1UL, col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse column.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator
+ Column<MT,false,false,false>::erase( Iterator first, Iterator last )
+{
+ for( ; first!=last; ++first ) {
+ matrix_.erase( first.row_, first.pos_ );
+ }
+ return last;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse column.
+//
+// \param n The new minimum capacity of the sparse column.
+// \return void
+//
+// This function increases the capacity of the sparse column to at least \a n elements. The
+// current values of the column elements are preserved.
+*/
+template< typename MT > // Type of the sparse matrix
+void Column<MT,false,false,false>::reserve( size_t n )
+{
+ UNUSED_PARAMETER( n );
+
+ return;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse column by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the column scaling.
+// \return Reference to the sparse column.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the scalar value
+inline Column<MT,false,false,false>& Column<MT,false,false,false>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific column element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// column. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse column (the end() iterator) is returned. Note that
+// the returned sparse column iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator
+ Column<MT,false,false,false>::find( size_t index )
+{
+ const Iterator_<MT> pos( matrix_.find( index, col_ ) );
+
+ if( pos != matrix_.end( index ) )
+ return Iterator( matrix_, index, col_, pos );
+ else
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific column element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// column. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse column (the end() iterator) is returned. Note that
+// the returned sparse column iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstIterator
+ Column<MT,false,false,false>::find( size_t index ) const
+{
+ const ConstIterator_<MT> pos( matrix_.find( index, col_ ) );
+
+ if( pos != matrix_.end( index ) )
+ return ConstIterator( matrix_, index, col_, pos );
+ else
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator
+ Column<MT,false,false,false>::lowerBound( size_t index )
+{
+ for( size_t i=index; i<size(); ++i )
+ {
+ const Iterator_<MT> pos( matrix_.find( i, col_ ) );
+
+ if( pos != matrix_.end( i ) )
+ return Iterator( matrix_, i, col_, pos );
+ }
+
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstIterator
+ Column<MT,false,false,false>::lowerBound( size_t index ) const
+{
+ for( size_t i=index; i<size(); ++i )
+ {
+ const ConstIterator_<MT> pos( matrix_.find( i, col_ ) );
+
+ if( pos != matrix_.end( i ) )
+ return ConstIterator( matrix_, i, col_, pos );
+ }
+
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::Iterator
+ Column<MT,false,false,false>::upperBound( size_t index )
+{
+ for( size_t i=index+1UL; i<size(); ++i )
+ {
+ const Iterator_<MT> pos( matrix_.find( i, col_ ) );
+
+ if( pos != matrix_.end( i ) )
+ return Iterator( matrix_, i, col_, pos );
+ }
+
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,false>::ConstIterator
+ Column<MT,false,false,false>::upperBound( size_t index ) const
+{
+ for( size_t i=index+1UL; i<size(); ++i )
+ {
+ const ConstIterator_<MT> pos( matrix_.find( i, col_ ) );
+
+ if( pos != matrix_.end( i ) )
+ return ConstIterator( matrix_, i, col_, pos );
+ }
+
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the sparse column.
+//
+// \param index The index of the new element. The index must be smaller than the number of matrix rows.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse column with elements. It appends
+// a new element to the end of the sparse column without any memory allocation. Therefore it is
+// strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the sparse column
+// - the current number of non-zero elements must be smaller than the capacity of the column
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Column<MT,false,false,false>::append( size_t index, const ElementType& value, bool check )
+{
+ if( !check || !isDefault( value ) )
+ matrix_.insert( index, col_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse column can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse column, \a false if not.
+//
+// This function returns whether the given address can alias with the sparse column. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,false,false,false>::canAlias( const Other* alias ) const
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse column is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this column, \a false if not.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,false,false,false>::isAliased( const Other* alias ) const
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,false,false>::assign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( size_t i=0UL; i<(~rhs).size(); ++i ) {
+ matrix_(i,col_) = (~rhs)[i];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,false,false>::assign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ size_t i( 0UL );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ for( ; i<element->index(); ++i )
+ matrix_.erase( i, col_ );
+ matrix_(i++,col_) = element->value();
+ }
+ for( ; i<size(); ++i ) {
+ matrix_.erase( i, col_ );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a vector.
+//
+// \param rhs The right-hand side vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline void Column<MT,false,false,false>::addAssign( const Vector<VT,false>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a vector.
+//
+// \param rhs The right-hand side vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline void Column<MT,false,false,false>::subAssign( const Vector<VT,false>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SYMMETRIC ROW-MAJOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Column for symmetric row-major sparse matrices.
+// \ingroup views
+//
+// This specialization of Column adapts the class template to the requirements of symmetric
+// row-major matrices.
+*/
+template< typename MT > // Type of the sparse matrix
+class Column<MT,false,false,true>
+ : public SparseVector< Column<MT,false,false,true>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Column<MT,false,false,true> This; //!< Type of this Column instance.
+ typedef SparseVector<This,false> BaseType; //!< Base type of this Column instance.
+ typedef ColumnTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the column elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Column& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant column value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant column value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Column( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Column& operator=( const Column& rhs );
+
+ template< typename VT > inline Column& operator= ( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator= ( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator+=( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator+=( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator-=( const DenseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator-=( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline Column& operator*=( const Vector<VT,false>& rhs );
+ template< typename VT > inline Column& operator/=( const DenseVector<VT,false>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Column >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Column >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline Iterator set ( size_t index, const ElementType& value );
+ inline Iterator insert ( size_t index, const ElementType& value );
+ inline void erase ( size_t index );
+ inline Iterator erase ( Iterator pos );
+ inline Iterator erase ( Iterator first, Iterator last );
+ inline void reserve( size_t n );
+ template< typename Other > inline Column& scale ( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index );
+ inline ConstIterator find ( size_t index ) const;
+ inline Iterator lowerBound( size_t index );
+ inline ConstIterator lowerBound( size_t index ) const;
+ inline Iterator upperBound( size_t index );
+ inline ConstIterator upperBound( size_t index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append( size_t index, const ElementType& value, bool check=false );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void addAssign( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void addAssign( const SparseVector<VT,false>& rhs );
+ template< typename VT > inline void subAssign( const DenseVector <VT,false>& rhs );
+ template< typename VT > inline void subAssign( const SparseVector<VT,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t extendCapacity() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The sparse matrix containing the column.
+ const size_t col_; //!< The index of the column in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Column<MT2,SO2,DF2,SF2>& column ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Column<MT2,SO2,DF2,SF2>& a, const Column<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Column<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,false>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Column<MT2,SO2,DF2,SF2> > derestrict( Column<MT2,SO2,DF2,SF2>& column );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Column.
+//
+// \param matrix The matrix containing the column.
+// \param index The index of the column.
+// \exception std::invalid_argument Invalid column access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline Column<MT,false,false,true>::Column( MT& matrix, size_t index )
+ : matrix_( matrix ) // The sparse matrix containing the column
+ , col_ ( index ) // The index of the column in the matrix
+{
+ if( matrix_.columns() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid column access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Reference
+ Column<MT,false,false,true>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return matrix_(col_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstReference
+ Column<MT,false,false,true>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid column access index" );
+ return const_cast<const MT&>( matrix_ )(col_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Reference
+ Column<MT,false,false,true>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the column elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix rows.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid column access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstReference
+ Column<MT,false,false,true>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator Column<MT,false,false,true>::begin()
+{
+ return matrix_.begin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstIterator
+ Column<MT,false,false,true>::begin() const
+{
+ return matrix_.cbegin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the column.
+//
+// \return Iterator to the first element of the column.
+//
+// This function returns an iterator to the first element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstIterator
+ Column<MT,false,false,true>::cbegin() const
+{
+ return matrix_.cbegin( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator Column<MT,false,false,true>::end()
+{
+ return matrix_.end( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstIterator
+ Column<MT,false,false,true>::end() const
+{
+ return matrix_.cend( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the column.
+//
+// \return Iterator just past the last element of the column.
+//
+// This function returns an iterator just past the last element of the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstIterator
+ Column<MT,false,false,true>::cend() const
+{
+ return matrix_.cend( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Column.
+//
+// \param rhs Sparse column to be copied.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Column sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two columns don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+inline Column<MT,false,false,true>& Column<MT,false,false,true>::operator=( const Column& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && col_ == rhs.col_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Column sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ left.reserve( rhs.nonZeros() );
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for dense vectors.
+//
+// \param rhs Dense vector to be assigned.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,false,false,true>&
+ Column<MT,false,false,true>::operator=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ left.reset();
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for sparse vectors.
+//
+// \param rhs Sparse vector to be assigned.
+// \return Reference to the assigned column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,false,false,true>&
+ Column<MT,false,false,true>::operator=( const SparseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right);
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ left.reserve( right.nonZeros() );
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a dense vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be added to the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,false,false,true>&
+ Column<MT,false,false,true>::operator+=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a sparse vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be added to the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,false,false,true>&
+ Column<MT,false,false,true>::operator+=( const SparseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a dense vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be subtracted from the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Column<MT,false,false,true>&
+ Column<MT,false,false,true>::operator-=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a sparse vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be subtracted from the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Column<MT,false,false,true>&
+ Column<MT,false,false,true>::operator-=( const SparseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the sparse column.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,false,true>&
+ Column<MT,false,false,true>::operator*=( const Vector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the sparse column.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Column<MT,false,false,true>&
+ Column<MT,false,false,true>::operator/=( const DenseVector<VT,false>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const DivType tmp( *this / (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse column
+// and a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse column.
+//
+// Via this operator it is possible to scale the sparse column. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for columns on lower
+// or upper unitriangular matrices. The attempt to scale such a column results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse column must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Column<MT,false,false,true> >&
+ Column<MT,false,false,true>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse column by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the sparse column.
+//
+// Via this operator it is possible to scale the sparse column. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for columns on lower
+// or upper unitriangular matrices. The attempt to scale such a column results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse column must either support the multiplication assignment operator for the given
+// floating point data type or the division assignment operator for the given integral data
+// type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Column<MT,false,false,true> >&
+ Column<MT,false,false,true>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= tmp;
+ }
+ else {
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the sparse column.
+//
+// \return The size of the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Column<MT,false,false,true>::size() const noexcept
+{
+ return matrix_.rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse column.
+//
+// \return The capacity of the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Column<MT,false,false,true>::capacity() const noexcept
+{
+ return matrix_.capacity( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the column.
+//
+// \return The number of non-zero elements in the column.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of rows of the matrix containing the column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Column<MT,false,false,true>::nonZeros() const
+{
+ return matrix_.nonZeros( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Column<MT,false,false,true>::reset()
+{
+ matrix_.reset( col_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse column.
+//
+// \param index The index of the element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+//
+// This function sets the value of an element of the sparse column. In case the sparse column
+// already contains an element with index \a index its value is modified, else a new element
+// with the given \a value is inserted.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator
+ Column<MT,false,false,true>::set( size_t index, const ElementType& value )
+{
+ return matrix_.set( col_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse column.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid sparse column access index.
+//
+// This function inserts a new element into the sparse column. However, duplicate elements
+// are not allowed. In case the sparse column already contains an element at index \a index,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator
+ Column<MT,false,false,true>::insert( size_t index, const ElementType& value )
+{
+ return matrix_.insert( col_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse column.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Column<MT,false,false,true>::erase( size_t index )
+{
+ matrix_.erase( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse column.
+//
+// \param pos Iterator to the element to be erased.
+// \return void
+//
+// This function erases an element from the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator
+ Column<MT,false,false,true>::erase( Iterator pos )
+{
+ return matrix_.erase( col_, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse column.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the sparse column.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator
+ Column<MT,false,false,true>::erase( Iterator first, Iterator last )
+{
+ return matrix_.erase( col_, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse column.
+//
+// \param n The new minimum capacity of the sparse column.
+// \return void
+//
+// This function increases the capacity of the sparse column to at least \a n elements. The
+// current values of the column elements are preserved.
+*/
+template< typename MT > // Type of the sparse matrix
+void Column<MT,false,false,true>::reserve( size_t n )
+{
+ matrix_.reserve( col_, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse column by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the column scaling.
+// \return Reference to the sparse column.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the scalar value
+inline Column<MT,false,false,true>& Column<MT,false,false,true>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating a new sparse column capacity.
+//
+// \return The new sparse column capacity.
+//
+// This function calculates a new column capacity based on the current capacity of the sparse
+// column. Note that the new capacity is restricted to the interval \f$[7..size]\f$.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Column<MT,false,false,true>::extendCapacity() const noexcept
+{
+ using blaze::max;
+ using blaze::min;
+
+ size_t nonzeros( 2UL*capacity()+1UL );
+ nonzeros = max( nonzeros, 7UL );
+ nonzeros = min( nonzeros, size() );
+
+ BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific column element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// column. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse column (the end() iterator) is returned. Note that
+// the returned sparse column iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator
+ Column<MT,false,false,true>::find( size_t index )
+{
+ return matrix_.find( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific column element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// column. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse column (the end() iterator) is returned. Note that
+// the returned sparse column iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstIterator
+ Column<MT,false,false,true>::find( size_t index ) const
+{
+ return matrix_.find( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator
+ Column<MT,false,false,true>::lowerBound( size_t index )
+{
+ return matrix_.lowerBound( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstIterator
+ Column<MT,false,false,true>::lowerBound( size_t index ) const
+{
+ return matrix_.lowerBound( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::Iterator
+ Column<MT,false,false,true>::upperBound( size_t index )
+{
+ return matrix_.upperBound( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse column iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Column<MT,false,false,true>::ConstIterator
+ Column<MT,false,false,true>::upperBound( size_t index ) const
+{
+ return matrix_.upperBound( col_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the sparse column.
+//
+// \param index The index of the new element. The index must be smaller than the number of matrix rows.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse column with elements. It appends
+// a new element to the end of the sparse column without any memory allocation. Therefore it is
+// strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the sparse column
+// - the current number of non-zero elements must be smaller than the capacity of the column
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Column<MT,false,false,true>::append( size_t index, const ElementType& value, bool check )
+{
+ matrix_.append( col_, index, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse column can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse column, \a false if not.
+//
+// This function returns whether the given address can alias with the sparse column. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,false,false,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse column is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse column, \a false if not.
+//
+// This function returns whether the given address is aliased with the sparse column. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Column<MT,false,false,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,false,true>::assign( const DenseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ for( size_t i=0UL; i<size(); ++i )
+ {
+ if( matrix_.nonZeros( col_ ) == matrix_.capacity( col_ ) )
+ matrix_.reserve( col_, extendCapacity() );
+
+ matrix_.append( col_, i, (~rhs)[i], true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,false,true>::assign( const SparseVector<VT,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ matrix_.append( col_, element->index(), element->value(), true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,false,true>::addAssign( const DenseVector<VT,false>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ matrix_.reset( col_ );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,false,true>::addAssign( const SparseVector<VT,false>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ matrix_.reset( col_ );
+ matrix_.reserve( col_, tmp.nonZeros() );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Column<MT,false,false,true>::subAssign( const DenseVector<VT,false>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ matrix_.reset( col_ );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Column<MT,false,false,true>::subAssign( const SparseVector<VT,false>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ matrix_.reset( col_ );
+ matrix_.reserve( col_, tmp.nonZeros() );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/row/BaseTemplate.h b/src/cpu/blaze/math/views/row/BaseTemplate.h
new file mode 100644
index 00000000..c5b0912f
--- /dev/null
+++ b/src/cpu/blaze/math/views/row/BaseTemplate.h
@@ -0,0 +1,361 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/row/BaseTemplate.h
+// \brief Header file for the implementation of the Row base template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_ROW_BASETEMPLATE_H_
+#define _BLAZE_MATH_VIEWS_ROW_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+#include <blaze/math/typetraits/IsRowMajorMatrix.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup row Row
+// \ingroup views
+*/
+/*!\brief Reference to a specific row of a dense or sparse matrix.
+// \ingroup row
+//
+// The Row template represents a reference to a specific row of a dense or sparse matrix primitive.
+// The type of the matrix is specified via the first template parameter:
+
+ \code
+ template< typename MT, bool SO, bool DF, bool SF >
+ class Row;
+ \endcode
+
+// - MT: specifies the type of the matrix primitive. Row can be used with every matrix primitive,
+// but does not work with any matrix expression type.
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+// - SF: specifies whether the given matrix is a symmetric matrix or not. Also this parameter
+// doesn't have to be explicitly defined, but is automatically derived from the first
+// template parameter.
+//
+//
+// \n \section row_setup Setup of Rows
+//
+// A reference to a dense or sparse row can be created very conveniently via the \c row() function.
+// This reference can be treated as any other row vector, i.e. it can be assigned to, it can be
+// copied from, and it can be used in arithmetic operations. The reference can also be used on
+// both sides of an assignment: The row can either be used as an alias to grant write access to a
+// specific row of a matrix primitive on the left-hand side of an assignment or to grant read-access
+// to a specific row of a matrix primitive or expression on the right-hand side of an assignment.
+// The following example demonstrates this in detail:
+
+ \code
+ using DenseVectorType = blaze::DynamicVector<double,rowVector>;
+ using SparseVectorType = blaze::CompressedVector<double,rowVector>;
+ using DenseMatrixType = blaze::DynamicMatrix<double,rowMajor>;
+ using SparseMatrixType = blaze::CompressedMatrix<double,rowMajor>;
+
+ DenseVectorType x;
+ SparseVectorType y;
+ DenseMatrixType A, B;
+ SparseMatrixType C, D;
+ // ... Resizing and initialization
+
+ // Setting the 2nd row of matrix A to x
+ blaze::Row<DenseMatrixType> row2 = row( A, 2UL );
+ row2 = x;
+
+ // Setting the 3rd row of matrix B to y
+ row( B, 3UL ) = y;
+
+ // Setting x to the 4th row of the result of the matrix multiplication
+ x = row( A * B, 4UL );
+
+ // Setting y to the 2nd row of the result of the sparse matrix multiplication
+ y = row( C * D, 2UL );
+ \endcode
+
+// The \c row() function can be used on any dense or sparse matrix, including expressions, as
+// illustrated by the source code example. However, rows cannot be instantiated for expression
+// types, but only for matrix primitives, respectively, i.e. for matrix types that offer write
+// access.
+//
+//
+// \n \section row_element_access Element access
+//
+// A dense or sparse row can be used like any other row vector. For instance, the elements of a
+// row can be directly accessed with the subscript operator:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<double,blaze::rowMajor>;
+ MatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a view on the 4th row of matrix A
+ blaze::Row<MatrixType> row4 = row( A, 4UL );
+
+ // Setting the 1st element of the dense row, which corresponds
+ // to the 1st element in the 4th row of matrix A
+ row4[1] = 2.0;
+ \endcode
+
+// The numbering of the row elements is
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right),\f]
+
+// where N is the number of columns of the referenced matrix. Alternatively, the elements of
+// a row can be traversed via iterators. Just as with vectors, in case of non-const rows,
+// \c begin() and \c end() return an Iterator, which allows a manipulation of the non-zero
+// values, in case of constant rows a ConstIterator is returned:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<int,blaze::rowMajor>;
+ using RowType = blaze::Row<MatrixType>;
+
+ MatrixType A( 128UL, 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st row of matrix A
+ RowType row31 = row( A, 31UL );
+
+ for( RowType::Iterator it=row31.begin(); it!=row31.end(); ++it ) {
+ *it = ...; // OK; Write access to the dense row value
+ ... = *it; // OK: Read access to the dense row value.
+ }
+
+ for( RowType::ConstIterator it=row31.begin(); it!=row31.end(); ++it ) {
+ *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = *it; // OK: Read access to the dense row value.
+ }
+ \endcode
+
+ \code
+ using MatrixType = blaze::CompressedMatrix<int,blaze::rowMajor>;
+ using RowType = blaze::Row<MatrixType>;
+
+ MatrixType A( 128UL, 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 31st row of matrix A
+ RowType row31 = row( A, 31UL );
+
+ for( RowType::Iterator it=row31.begin(); it!=row31.end(); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+
+ for( RowType::ConstIterator it=row31.begin(); it!=row31.end(); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+ \endcode
+
+// \n \section sparse_row_element_insertion Element Insertion
+//
+// Inserting/accessing elements in a sparse row can be done by several alternative functions.
+// The following example demonstrates all options:
+
+ \code
+ using MatrixType = blaze::CompressedMatrix<double,blaze::rowMajor>;
+ MatrixType A( 10UL, 100UL ); // Non-initialized 10x100 matrix
+
+ using RowType = blaze::Row<MatrixType>;
+ RowType row0( row( A, 0UL ) ); // Reference to the 0th row of A
+
+ // The subscript operator provides access to all possible elements of the sparse row,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse row, the element is inserted into the row.
+ row0[42] = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element
+ // is not contained in the row it is inserted into the row, if it is already contained in
+ // the row its value is modified.
+ row0.set( 45UL, -1.2 );
+
+ // An alternative for inserting elements into the row is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the row.
+ row0.insert( 50UL, 3.7 );
+
+ // A very efficient way to add new elements to a sparse row is the append() function.
+ // Note that append() requires that the appended element's index is strictly larger than
+ // the currently largest non-zero index of the row and that the row's capacity is large
+ // enough to hold the new element.
+ row0.reserve( 10UL );
+ row0.append( 51UL, -2.1 );
+ \endcode
+
+// \n \section row_common_operations Common Operations
+//
+// The current number of row elements can be obtained via the \c size() function, the current
+// capacity via the \c capacity() function, and the number of non-zero elements via the
+// \c nonZeros() function. However, since rows are references to specific rows of a matrix,
+// several operations are not possible on views, such as resizing and swapping. The following
+// example shows this by means of a dense row view:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<int,blaze::rowMajor>;
+ using RowType = blaze::Row<MatrixType>;
+
+ MatrixType A( 42UL, 42UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 2nd row of matrix A
+ RowType row2 = row( A, 2UL );
+
+ row2.size(); // Returns the number of elements in the row
+ row2.capacity(); // Returns the capacity of the row
+ row2.nonZeros(); // Returns the number of non-zero elements contained in the row
+
+ row2.resize( 84UL ); // Compilation error: Cannot resize a single row of a matrix
+
+ RowType row3 = row( A, 3UL );
+ swap( row2, row3 ); // Compilation error: Swap operation not allowed
+ \endcode
+
+// \n \section row_arithmetic_operations Arithmetic Operations
+//
+// Both dense and sparse rows can be used in all arithmetic operations that any other dense or
+// sparse row vector can be used in. The following example gives an impression of the use of
+// dense rows within arithmetic operations. All operations (addition, subtraction, multiplication,
+// scaling, ...) can be performed on all possible combinations of dense and sparse rows with
+// fitting element types:
+
+ \code
+ blaze::DynamicVector<double,blaze::rowVector> a( 2UL, 2.0 ), b;
+ blaze::CompressedVector<double,blaze::rowVector> c( 2UL );
+ c[1] = 3.0;
+
+ using DenseMatrix = blaze::DynamicMatrix<double,blaze::rowMajor>;
+ DenseMatrix A( 4UL, 2UL ); // Non-initialized 4x2 matrix
+
+ using RowType = blaze::Row<DenseMatrix>;
+ RowType row0( row( A, 0UL ) ); // Reference to the 0th row of A
+
+ row0[0] = 0.0; // Manual initialization of the 0th row of A
+ row0[1] = 0.0;
+ row( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st row of A
+ row( A, 2UL ) = a; // Dense vector initialization of the 2nd row of A
+ row( A, 3UL ) = c; // Sparse vector initialization of the 3rd row of A
+
+ b = row0 + a; // Dense vector/dense vector addition
+ b = c + row( A, 1UL ); // Sparse vector/dense vector addition
+ b = row0 * row( A, 2UL ); // Component-wise vector multiplication
+
+ row( A, 1UL ) *= 2.0; // In-place scaling of the 1st row
+ b = row( A, 1UL ) * 2.0; // Scaling of the 1st row
+ b = 2.0 * row( A, 1UL ); // Scaling of the 1st row
+
+ row( A, 2UL ) += a; // Addition assignment
+ row( A, 2UL ) -= c; // Subtraction assignment
+ row( A, 2UL ) *= row( A, 0UL ); // Multiplication assignment
+
+ double scalar = row( A, 1UL ) * trans( c ); // Scalar/dot/inner product between two vectors
+
+ A = trans( c ) * row( A, 1UL ); // Outer product between two vectors
+ \endcode
+
+// \n \section row_on_column_major_matrix Rows on Column-Major Matrices
+//
+// It is especially noteworthy that row views can be created for both row-major and column-major
+// matrices. Whereas the interface of a row-major matrix only allows to traverse a row directly
+// and the interface of a column-major matrix only allows to traverse a column, via views it is
+// also possible to traverse a row of a column-major matrix. For instance:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<int,blaze::columnMajor>;
+ using RowType = blaze::Row<MatrixType>;
+
+ MatrixType A( 64UL, 32UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to the 1st row of a column-major matrix A
+ RowType row1 = row( A, 1UL );
+
+ for( RowType::Iterator it=row1.begin(); it!=row1.end(); ++it ) {
+ // ...
+ }
+ \endcode
+
+// However, please note that creating a row view on a matrix stored in a column-major fashion
+// can result in a considerable performance decrease in comparison to a row view on a matrix
+// with row-major storage format. This is due to the non-contiguous storage of the matrix elements.
+// Therefore care has to be taken in the choice of the most suitable storage order:
+
+ \code
+ // Setup of two column-major matrices
+ blaze::DynamicMatrix<double,blaze::columnMajor> A( 128UL, 128UL );
+ blaze::DynamicMatrix<double,blaze::columnMajor> B( 128UL, 128UL );
+ // ... Resizing and initialization
+
+ // The computation of the 15th row of the multiplication between A and B ...
+ blaze::DynamicVector<double,blaze::rowVector> x = row( A * B, 15UL );
+
+ // ... is essentially the same as the following computation, which multiplies
+ // the 15th row of the column-major matrix A with B.
+ blaze::DynamicVector<double,blaze::rowVector> x = row( A, 15UL ) * B;
+ \endcode
+
+// Although Blaze performs the resulting vector/matrix multiplication as efficiently as possible
+// using a row-major storage order for matrix A would result in a more efficient evaluation.
+*/
+template< typename MT // Type of the matrix
+ , bool SO = IsRowMajorMatrix<MT>::value // Storage order
+ , bool DF = IsDenseMatrix<MT>::value // Density flag
+ , bool SF = IsSymmetric<MT>::value > // Symmetry flag
+class Row
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/row/Dense.h b/src/cpu/blaze/math/views/row/Dense.h
new file mode 100644
index 00000000..b995e99b
--- /dev/null
+++ b/src/cpu/blaze/math/views/row/Dense.h
@@ -0,0 +1,5800 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/row/Dense.h
+// \brief Row specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_ROW_DENSE_H_
+#define _BLAZE_MATH_VIEWS_ROW_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/View.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsPadded.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/views/row/BaseTemplate.h>
+#include <blaze/system/CacheSize.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR ROW-MAJOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Row for rows on row-major dense matrices.
+// \ingroup views
+//
+// This specialization of Row adapts the class template to the requirements of row-major dense
+// matrices.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+class Row<MT,true,true,SF>
+ : public DenseVector< Row<MT,true,true,SF>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Row<MT,true,true,SF> This; //!< Type of this Row instance.
+ typedef DenseVector<This,true> BaseType; //!< Base type of this Row instance.
+ typedef RowTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the row elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the row elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Row& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant row value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant row value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant row value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant row value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Row( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Row& operator=( const ElementType& rhs );
+ inline Row& operator=( initializer_list<ElementType> list );
+ inline Row& operator=( const Row& rhs );
+
+ template< typename VT > inline Row& operator= ( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator+=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator-=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator/=( const DenseVector<VT,true>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Row >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Row >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline Row& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDSub< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDMult< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDDiv< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool canAlias( const Row<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool isAliased( const Row<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,true>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the row.
+ const size_t row_; //!< The index of the row in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 > friend class Row;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Row<MT2,SO2,DF2,SF2>& row ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Row<MT2,SO2,DF2,SF2>& a, const Row<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2,bool SF2, typename VT >
+ friend bool tryDivAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Row<MT2,SO2,DF2,SF2> > derestrict( Row<MT2,SO2,DF2,SF2>& row );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Row.
+//
+// \param matrix The matrix containing the row.
+// \param index The index of the row.
+// \exception std::invalid_argument Invalid row access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline Row<MT,true,true,SF>::Row( MT& matrix, size_t index )
+ : matrix_( matrix ) // The dense matrix containing the row
+ , row_ ( index ) // The index of the row in the matrix
+{
+ if( matrix_.rows() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid row access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::Reference Row<MT,true,true,SF>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return matrix_(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::ConstReference
+ Row<MT,true,true,SF>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return const_cast<const MT&>( matrix_ )(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::Reference Row<MT,true,true,SF>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::ConstReference Row<MT,true,true,SF>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the row elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense row. Note that in case
+// of a column-major matrix you can NOT assume that the row elements lie adjacent to each other!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::Pointer Row<MT,true,true,SF>::data() noexcept
+{
+ return matrix_.data( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the row elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense row. Note that in case
+// of a column-major matrix you can NOT assume that the row elements lie adjacent to each other!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::ConstPointer Row<MT,true,true,SF>::data() const noexcept
+{
+ return matrix_.data( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::Iterator Row<MT,true,true,SF>::begin()
+{
+ return matrix_.begin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::ConstIterator Row<MT,true,true,SF>::begin() const
+{
+ return matrix_.cbegin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::ConstIterator Row<MT,true,true,SF>::cbegin() const
+{
+ return matrix_.cbegin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::Iterator Row<MT,true,true,SF>::end()
+{
+ return matrix_.end( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::ConstIterator Row<MT,true,true,SF>::end() const
+{
+ return matrix_.cend( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,true,SF>::ConstIterator Row<MT,true,true,SF>::cend() const
+{
+ return matrix_.cend( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all row elements.
+//
+// \param rhs Scalar value to be assigned to all row elements.
+// \return Reference to the assigned row.
+//
+// This function homogeneously assigns the given value to all elements of the row. Note that in
+// case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
+// of the underlying matrix are modified.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator=( const ElementType& rhs )
+{
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( row_+1UL )
+ :( row_ ) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( row_ )
+ :( row_+1UL ) )
+ :( size() ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ matrix_(row_,j) = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all row elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to row.
+//
+// This assignment operator offers the option to directly assign to all elements of the dense
+// row by means of an initializer list. The row elements are assigned the values from the given
+// initializer list. Missing values are reset to their default state. Note that in case the size
+// of the initializer list exceeds the size of the row, a \a std::invalid_argument exception is
+// thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator=( initializer_list<ElementType> list )
+{
+ if( list.size() > size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to row" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), begin() ), end(), ElementType() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Row.
+//
+// \param rhs Dense row to be copied.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Row sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two rows don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator=( const Row& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Row sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator+=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAddAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAddAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator-=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !trySubAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpSubAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator*=( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryMultAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpMultAssign( left, tmp );
+ }
+ else {
+ smpMultAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator*=( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const ResultType right( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, right );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::operator/=( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryDivAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpDivAssign( left, tmp );
+ }
+ else {
+ smpDivAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense row and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+//
+// This operator cannot be used for rows on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Row<MT,true,true,SF> >&
+ Row<MT,true,true,SF>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ return operator=( (*this) * rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense row by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// This operator cannot be used for rows on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Row<MT,true,true,SF> >&
+ Row<MT,true,true,SF>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ return operator=( (*this) / rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the row.
+//
+// \return The size of the row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline size_t Row<MT,true,true,SF>::size() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense row.
+//
+// \return The capacity of the dense row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline size_t Row<MT,true,true,SF>::capacity() const noexcept
+{
+ return matrix_.capacity( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the row.
+//
+// \return The number of non-zero elements in the row.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of columns of the matrix containing the row.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline size_t Row<MT,true,true,SF>::nonZeros() const
+{
+ return matrix_.nonZeros( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline void Row<MT,true,true,SF>::reset()
+{
+ matrix_.reset( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the row by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the row scaling.
+// \return Reference to the dense row.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the scalar value
+inline Row<MT,true,true,SF>& Row<MT,true,true,SF>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( row_+1UL )
+ :( row_ ) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( row_ )
+ :( row_+1UL ) )
+ :( size() ) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ matrix_(row_,j) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address can alias with the dense row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,true,true,SF>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can alias with the given dense row \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address can alias with the dense row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename MT2 // Data type of the foreign dense row
+ , bool SO2 // Storage order of the foreign dense row
+ , bool SF2 > // Symmetry flag of the foreign dense row
+inline bool Row<MT,true,true,SF>::canAlias( const Row<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( row_ == alias->row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense row. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,true,true,SF>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is aliased with the given dense row \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense row. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename MT2 // Data type of the foreign dense row
+ , bool SO2 // Storage order of the foreign dense row
+ , bool SF2 > // Symmetry flag of the foreign dense row
+inline bool Row<MT,true,true,SF>::isAliased( const Row<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( row_ == alias->row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is properly aligned in memory.
+//
+// \return \a true in case the dense row is aligned, \a false if not.
+//
+// This function returns whether the dense row is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of the dense row are guaranteed to conform to the
+// alignment restrictions of the element type \a Type.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline bool Row<MT,true,true,SF>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can be used in SMP assignments.
+//
+// \return \a true in case the dense row can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the dense row can be used in SMP assignments. In contrast to
+// the \a smpAssignable member enumeration, which is based solely on compile time information,
+// this function additionally provides runtime information (as for instance the current size
+// of the dense row).
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+inline bool Row<MT,true,true,SF>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense row. The index
+// must be smaller than the number of matrix columns. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE typename Row<MT,true,true,SF>::SIMDType
+ Row<MT,true,true,SF>::load( size_t index ) const noexcept
+{
+ return matrix_.load( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense row.
+// The index must be smaller than the number of matrix columns. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE typename Row<MT,true,true,SF>::SIMDType
+ Row<MT,true,true,SF>::loada( size_t index ) const noexcept
+{
+ return matrix_.loada( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense row.
+// The index must be smaller than the number of matrix columns. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE typename Row<MT,true,true,SF>::SIMDType
+ Row<MT,true,true,SF>::loadu( size_t index ) const noexcept
+{
+ return matrix_.loadu( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store a specific SIMD element of the dense row. The index
+// must be smaller than the number of matrix columns. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE void
+ Row<MT,true,true,SF>::store( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.store( row_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store a specific SIMD element of the dense row. The
+// index must be smaller than the number of matrix columns. This function must \b NOT be
+// called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE void
+ Row<MT,true,true,SF>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.storea( row_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unligned store of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store a specific SIMD element of the dense row.
+// The index must be smaller than the number of matrix columns. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE void
+ Row<MT,true,true,SF>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.storeu( row_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store a specific SIMD element of the dense
+// row. The index must be smaller than the number of matrix columns. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+BLAZE_ALWAYS_INLINE void
+ Row<MT,true,true,SF>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.stream( row_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ Row<MT,true,true,SF>::assign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) = (~rhs)[j ];
+ matrix_(row_,j+1UL) = (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) = (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ Row<MT,true,true,SF>::assign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t columns( size() );
+
+ const size_t jpos( ( remainder )?( columns & size_t(-SIMDSIZE) ):( columns ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ if( useStreaming && columns > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( &matrix_ ) )
+ {
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ else
+ {
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,true,true,SF>::assign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(row_,element->index()) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ Row<MT,true,true,SF>::addAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) += (~rhs)[j ];
+ matrix_(row_,j+1UL) += (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) += (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ Row<MT,true,true,SF>::addAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t columns( size() );
+
+ const size_t jpos( ( remainder )?( columns & size_t(-SIMDSIZE) ):( columns ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left += *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,true,true,SF>::addAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(row_,element->index()) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ Row<MT,true,true,SF>::subAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) -= (~rhs)[j ];
+ matrix_(row_,j+1UL) -= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) -= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ Row<MT,true,true,SF>::subAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t columns( size() );
+
+ const size_t jpos( ( remainder )?( columns & size_t(-SIMDSIZE) ):( columns ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left -= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,true,true,SF>::subAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(row_,element->index()) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ Row<MT,true,true,SF>::multAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) *= (~rhs)[j ];
+ matrix_(row_,j+1UL) *= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) *= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ Row<MT,true,true,SF>::multAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t columns( size() );
+
+ const size_t jpos( ( remainder )?( columns & size_t(-SIMDSIZE) ):( columns ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && j<columns; ++j ) {
+ *left *= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,true,true,SF>::multAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(row_,element->index()) = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ Row<MT,true,true,SF>::divAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) /= (~rhs)[j ];
+ matrix_(row_,j+1UL) /= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) /= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the dense matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,true,true,SF>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ Row<MT,true,true,SF>::divAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t columns( size() );
+
+ const size_t jpos( columns & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( columns - ( columns % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<columns; ++j ) {
+ *left /= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR GENERAL COLUMN-MAJOR MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Row for general column-major dense matrices.
+// \ingroup dense_row
+//
+// This specialization of Row adapts the class template to the requirements of general
+// column-major dense matrices.
+*/
+template< typename MT > // Type of the dense matrix
+class Row<MT,false,true,false>
+ : public DenseVector< Row<MT,false,true,false>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Row<MT,false,true,false> This; //!< Type of this Row instance.
+ typedef DenseVector<This,true> BaseType; //!< Base type of this Row instance.
+ typedef RowTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the row elements.
+ typedef ElementType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Row& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant row value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant row value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant row value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant row value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+ //**********************************************************************************************
+
+ //**RowIterator class definition****************************************************************
+ /*!\brief Iterator over the elements of the dense row.
+ */
+ template< typename MatrixType > // Type of the dense matrix
+ class RowIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! Return type for the access to the value of a dense element.
+ typedef If_< IsConst<MatrixType>, ConstReference_<MatrixType>, Reference_<MatrixType> > Reference;
+
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef RemoveReference_<Reference> ValueType; //!< Type of the underlying elements.
+ typedef ValueType* PointerType; //!< Pointer return type.
+ typedef Reference ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the RowIterator class.
+ */
+ inline RowIterator() noexcept
+ : matrix_( nullptr ) // The dense matrix containing the row.
+ , row_ ( 0UL ) // The current row index.
+ , column_( 0UL ) // The current column index.
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor of the RowIterator class.
+ //
+ // \param matrix The matrix containing the row.
+ // \param row The row index.
+ // \param column The column index.
+ */
+ inline RowIterator( MatrixType& matrix, size_t row, size_t column ) noexcept
+ : matrix_( &matrix ) // The dense matrix containing the row.
+ , row_ ( row ) // The current row index.
+ , column_( column ) // The current column index.
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different RowIterator instances.
+ //
+ // \param it The row iterator to be copied.
+ */
+ template< typename MatrixType2 >
+ inline RowIterator( const RowIterator<MatrixType2>& it ) noexcept
+ : matrix_( it.matrix_ ) // The dense matrix containing the row.
+ , row_ ( it.row_ ) // The current row index.
+ , column_( it.column_ ) // The current column index.
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline RowIterator& operator+=( size_t inc ) noexcept {
+ column_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline RowIterator& operator-=( size_t dec ) noexcept {
+ column_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline RowIterator& operator++() noexcept {
+ ++column_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const RowIterator operator++( int ) noexcept {
+ const RowIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline RowIterator& operator--() noexcept {
+ --column_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const RowIterator operator--( int ) noexcept {
+ const RowIterator tmp( *this );
+ --(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Subscript operator***********************************************************************
+ /*!\brief Direct access to the dense row elements.
+ //
+ // \param index Access index.
+ // \return Reference to the accessed value.
+ */
+ inline ReferenceType operator[]( size_t index ) const {
+ return (*matrix_)(row_,column_+index);
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the dense row element at the current iterator position.
+ //
+ // \return Reference to the current value.
+ */
+ inline ReferenceType operator*() const {
+ return (*matrix_)(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the dense row element at the current iterator position.
+ //
+ // \return Pointer to the dense row element at the current iterator position.
+ */
+ inline PointerType operator->() const {
+ return &(*matrix_)(row_,column_);
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two RowIterator objects.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator==( const RowIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ == rhs.row_ ) && ( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two RowIterator objects.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ template< typename MatrixType2 >
+ inline bool operator!=( const RowIterator<MatrixType2>& rhs ) const noexcept {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two RowIterator objects.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator<( const RowIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ == rhs.row_ ) && ( column_ < rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two RowIterator objects.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator>( const RowIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ == rhs.row_ ) && ( column_ > rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two RowIterator objects.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator<=( const RowIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ == rhs.row_ ) && ( column_ <= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two RowIterator objects.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ template< typename MatrixType2 >
+ inline bool operator>=( const RowIterator<MatrixType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ == rhs.row_ ) && ( column_ >= rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two row iterators.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return The number of elements between the two row iterators.
+ */
+ inline DifferenceType operator-( const RowIterator& rhs ) const noexcept {
+ return column_ - rhs.column_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a RowIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const RowIterator operator+( const RowIterator& it, size_t inc ) noexcept {
+ return RowIterator( *it.matrix_, it.row_, it.column_+inc );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a RowIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const RowIterator operator+( size_t inc, const RowIterator& it ) noexcept {
+ return RowIterator( *it.matrix_, it.row_, it.column_+inc );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a RowIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param inc The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const RowIterator operator-( const RowIterator& it, size_t dec ) noexcept {
+ return RowIterator( *it.matrix_, it.row_, it.column_-dec );
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MatrixType* matrix_; //!< The dense matrix containing the row.
+ size_t row_; //!< The current row index.
+ size_t column_; //!< The current column index.
+ //*******************************************************************************************
+
+ //**Friend declarations**********************************************************************
+ template< typename MatrixType2 > friend class RowIterator;
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef RowIterator<const MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, RowIterator<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Row( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Row& operator=( const ElementType& rhs );
+ inline Row& operator=( initializer_list<ElementType> list );
+ inline Row& operator=( const Row& rhs );
+
+ template< typename VT > inline Row& operator= ( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator+=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator-=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator/=( const DenseVector<VT,true>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Row >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Row >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline Row& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool canAlias( const Row<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool isAliased( const Row<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void addAssign ( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void addAssign ( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void subAssign ( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void subAssign ( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void multAssign( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void multAssign( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void divAssign ( const DenseVector <VT,true>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the row.
+ const size_t row_; //!< The index of the row in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 > friend class Row;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Row<MT2,SO2,DF2,SF2>& row ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Row<MT2,SO2,DF2,SF2>& a, const Row<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryDivAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Row<MT2,SO2,DF2,SF2> > derestrict( Row<MT2,SO2,DF2,SF2>& row );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Row.
+//
+// \param matrix The matrix containing the row.
+// \param index The index of the row.
+// \exception std::invalid_argument Invalid row access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline Row<MT,false,true,false>::Row( MT& matrix, size_t index )
+ : matrix_( matrix ) // The dense matrix containing the row
+ , row_ ( index ) // The index of the row in the matrix
+{
+ if( matrix_.rows() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid row access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::Reference
+ Row<MT,false,true,false>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return matrix_(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::ConstReference
+ Row<MT,false,true,false>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return const_cast<const MT&>( matrix_ )(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::Reference
+ Row<MT,false,true,false>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::ConstReference
+ Row<MT,false,true,false>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the row elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense row. Note that in case
+// of a column-major matrix you can NOT assume that the row elements lie adjacent to each other!
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::Pointer Row<MT,false,true,false>::data() noexcept
+{
+ return matrix_.data() + row_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the row elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense row. Note that in case
+// of a column-major matrix you can NOT assume that the row elements lie adjacent to each other!
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::ConstPointer Row<MT,false,true,false>::data() const noexcept
+{
+ return matrix_.data() + row_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::Iterator Row<MT,false,true,false>::begin()
+{
+ return Iterator( matrix_, row_, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::ConstIterator Row<MT,false,true,false>::begin() const
+{
+ return ConstIterator( matrix_, row_, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::ConstIterator Row<MT,false,true,false>::cbegin() const
+{
+ return ConstIterator( matrix_, row_, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::Iterator Row<MT,false,true,false>::end()
+{
+ return Iterator( matrix_, row_, size() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::ConstIterator Row<MT,false,true,false>::end() const
+{
+ return ConstIterator( matrix_, row_, size() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,false>::ConstIterator Row<MT,false,true,false>::cend() const
+{
+ return ConstIterator( matrix_, row_, size() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all row elements.
+//
+// \param rhs Scalar value to be assigned to all row elements.
+// \return Reference to the assigned row.
+//
+// This function homogeneously assigns the given value to all elements of the row. Note that in
+// case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
+// of the underlying matrix are modified.
+*/
+template< typename MT > // Type of the dense matrix
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::operator=( const ElementType& rhs )
+{
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( row_+1UL )
+ :( row_ ) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( row_ )
+ :( row_+1UL ) )
+ :( size() ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ matrix_(row_,j) = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all row elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to row.
+//
+// This assignment operator offers the option to directly assign to all elements of the dense
+// row by means of an initializer list. The row elements are assigned the values from the given
+// initializer list. Missing values are reset to their default state. Note that in case the size
+// of the initializer list exceeds the size of the row, a \a std::invalid_argument exception is
+// thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Row<MT,false,true,false>&
+ Row<MT,false,true,false>::operator=( initializer_list<ElementType> list )
+{
+ if( list.size() > size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to row" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), begin() ), end(), ElementType() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Row.
+//
+// \param rhs Dense row to be copied.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Row sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two rows don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::operator=( const Row& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Row sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::operator=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::operator+=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAddAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAddAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::operator-=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !trySubAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpSubAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::operator*=( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryMultAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpMultAssign( left, tmp );
+ }
+ else {
+ smpMultAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::operator*=( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const ResultType right( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, right );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::operator/=( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryDivAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpDivAssign( left, tmp );
+ }
+ else {
+ smpDivAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense row and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+//
+// This operator cannot be used for rows on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Row<MT,false,true,false> >&
+ Row<MT,false,true,false>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ return operator=( (*this) * rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense row by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// This operator cannot be used for rows on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Row<MT,false,true,false> >&
+ Row<MT,false,true,false>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ return operator=( (*this) / rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the row.
+//
+// \return The size of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Row<MT,false,true,false>::size() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense row.
+//
+// \return The capacity of the dense row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Row<MT,false,true,false>::capacity() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the row.
+//
+// \return The number of non-zero elements in the row.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of columns of the matrix containing the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Row<MT,false,true,false>::nonZeros() const
+{
+ const size_t columns( size() );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=0UL; j<columns; ++j )
+ if( !isDefault( matrix_(row_,j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Row<MT,false,true,false>::reset()
+{
+ using blaze::clear;
+
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( row_+1UL )
+ :( row_ ) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( row_ )
+ :( row_+1UL ) )
+ :( size() ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ clear( matrix_(row_,j) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the row by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the row scaling.
+// \return Reference to the dense row.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline Row<MT,false,true,false>& Row<MT,false,true,false>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( row_+1UL )
+ :( row_ ) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( row_ )
+ :( row_+1UL ) )
+ :( size() ) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ matrix_(row_,j) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address can alias with the dense row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,false,true,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can alias with the given dense row \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address can alias with the dense row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense row
+ , bool SO2 // Storage order of the foreign dense row
+ , bool SF2 > // Symmetry flag of the foreign dense row
+inline bool Row<MT,false,true,false>::canAlias( const Row<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( row_ == alias->row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense row. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,false,true,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is aliased with the given dense row \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense row. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense row
+ , bool SO2 // Storage order of the foreign dense row
+ , bool SF2 > // Symmetry flag of the foreign dense row
+inline bool Row<MT,false,true,false>::isAliased( const Row<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( row_ == alias->row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is properly aligned in memory.
+//
+// \return \a true in case the dense row is aligned, \a false if not.
+//
+// This function returns whether the dense row is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of the dense row are guaranteed to conform to the
+// alignment restrictions of the element type \a Type.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Row<MT,false,true,false>::isAligned() const noexcept
+{
+ return false;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can be used in SMP assignments.
+//
+// \return \a true in case the dense row can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the dense row can be used in SMP assignments. In contrast to
+// the \a smpAssignable member enumeration, which is based solely on compile time information,
+// this function additionally provides runtime information (as for instance the current size
+// of the dense row).
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Row<MT,false,true,false>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,true,false>::assign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) = (~rhs)[j ];
+ matrix_(row_,j+1UL) = (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) = (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,true,false>::assign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(row_,element->index()) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,true,false>::addAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) += (~rhs)[j ];
+ matrix_(row_,j+1UL) += (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) += (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,true,false>::addAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(row_,element->index()) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,true,false>::subAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) -= (~rhs)[j ];
+ matrix_(row_,j+1UL) -= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) -= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,true,false>::subAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(row_,element->index()) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,true,false>::multAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) *= (~rhs)[j ];
+ matrix_(row_,j+1UL) *= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) *= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,true,false>::multAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(row_,element->index()) = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,true,false>::divAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t jpos( (~rhs).size() & size_t(-2) );
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_,j ) /= (~rhs)[j ];
+ matrix_(row_,j+1UL) /= (~rhs)[j+1UL];
+ }
+ if( jpos < (~rhs).size() )
+ matrix_(row_,jpos) /= (~rhs)[jpos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SYMMETRIC COLUMN-MAJOR DENSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Row for symmetric column-major dense matrices.
+// \ingroup dense_row
+//
+// This specialization of Row adapts the class template to the requirements of symmetric
+// column-major dense matrices.
+*/
+template< typename MT > // Type of the dense matrix
+class Row<MT,false,true,true>
+ : public DenseVector< Row<MT,false,true,true>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Row<MT,false,true,true> This; //!< Type of this Row instance.
+ typedef DenseVector<This,true> BaseType; //!< Base type of this Row instance.
+ typedef RowTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the row elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the row elements.
+ typedef ElementType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Row& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant row value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant row value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant row value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant row value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Row( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Row& operator=( const ElementType& rhs );
+ inline Row& operator=( initializer_list<ElementType> list );
+ inline Row& operator=( const Row& rhs );
+
+ template< typename VT > inline Row& operator= ( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator+=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator-=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator/=( const DenseVector<VT,true>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Row >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Row >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline Row& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDSub< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDMult< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT> >::value &&
+ HasSIMDDiv< ElementType, ElementType_<VT> >::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool canAlias( const Row<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool SO2, bool SF2 >
+ inline bool isAliased( const Row<MT2,SO2,true,SF2>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedAssign<VT> > assign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT > inline void assign( const SparseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedAddAssign<VT> > addAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT > inline void addAssign( const SparseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedSubAssign<VT> > subAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT > inline void subAssign( const SparseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedMultAssign<VT> > multAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT > inline void multAssign( const SparseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline DisableIf_< VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,true>& rhs );
+
+ template< typename VT >
+ inline EnableIf_< VectorizedDivAssign<VT> > divAssign( const DenseVector<VT,true>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the row.
+ const size_t row_; //!< The index of the row in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 > friend class Row;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Row<MT2,SO2,DF2,SF2>& row ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Row<MT2,SO2,DF2,SF2>& a, const Row<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryDivAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Row<MT2,SO2,DF2,SF2> > derestrict( Row<MT2,SO2,DF2,SF2>& row );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SYMMETRIC_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Row.
+//
+// \param matrix The matrix containing the row.
+// \param index The index of the row.
+// \exception std::invalid_argument Invalid row access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline Row<MT,false,true,true>::Row( MT& matrix, size_t index )
+ : matrix_( matrix ) // The dense matrix containing the row
+ , row_ ( index ) // The index of the row in the matrix
+{
+ if( matrix_.rows() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid row access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::Reference
+ Row<MT,false,true,true>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return matrix_(index,row_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::ConstReference
+ Row<MT,false,true,true>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return const_cast<const MT&>( matrix_ )(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::Reference
+ Row<MT,false,true,true>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::ConstReference
+ Row<MT,false,true,true>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the row elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense row. Note that in case
+// of a column-major matrix you can NOT assume that the row elements lie adjacent to each other!
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::Pointer Row<MT,false,true,true>::data() noexcept
+{
+ return matrix_.data( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the row elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense row. Note that in case
+// of a column-major matrix you can NOT assume that the row elements lie adjacent to each other!
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::ConstPointer Row<MT,false,true,true>::data() const noexcept
+{
+ return matrix_.data( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::Iterator Row<MT,false,true,true>::begin()
+{
+ return matrix_.begin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::ConstIterator Row<MT,false,true,true>::begin() const
+{
+ return matrix_.cbegin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::ConstIterator Row<MT,false,true,true>::cbegin() const
+{
+ return matrix_.cbegin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::Iterator Row<MT,false,true,true>::end()
+{
+ return matrix_.end( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::ConstIterator Row<MT,false,true,true>::end() const
+{
+ return matrix_.cend( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Row<MT,false,true,true>::ConstIterator Row<MT,false,true,true>::cend() const
+{
+ return matrix_.cend( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all row elements.
+//
+// \param rhs Scalar value to be assigned to all row elements.
+// \return Reference to the assigned row.
+*/
+template< typename MT > // Type of the dense matrix
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::operator=( const ElementType& rhs )
+{
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( row_+1UL )
+ :( row_ ) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( row_ )
+ :( row_+1UL ) )
+ :( size() ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ matrix_(i,row_) = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all row elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to row.
+//
+// This assignment operator offers the option to directly assign to all elements of the dense
+// row by means of an initializer list. The row elements are assigned the values from the given
+// initializer list. Missing values are reset to their default state. Note that in case the size
+// of the initializer list exceeds the size of the row, a \a std::invalid_argument exception is
+// thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Row<MT,false,true,true>&
+ Row<MT,false,true,true>::operator=( initializer_list<ElementType> list )
+{
+ if( list.size() > size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to row" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), begin() ), end(), ElementType() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Row.
+//
+// \param rhs Dense row to be copied.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Row sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two rows don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::operator=( const Row& rhs )
+{
+ if( &rhs == this ) return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Row sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, rhs );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::operator=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ if( IsSparseVector<VT>::value )
+ reset();
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::operator+=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAddAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpAddAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::operator-=( const Vector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !trySubAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpSubAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::operator*=( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryMultAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpMultAssign( left, tmp );
+ }
+ else {
+ smpMultAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the dense row.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::operator*=( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const ResultType right( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, right );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::operator/=( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryDivAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ smpDivAssign( left, tmp );
+ }
+ else {
+ smpDivAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense row and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the vector.
+//
+// This operator cannot be used for rows on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Row<MT,false,true,true> >&
+ Row<MT,false,true,true>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ return operator=( (*this) * rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense row by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the vector.
+//
+// This operator cannot be used for rows on lower or upper unitriangular matrices. The attempt
+// to scale such a row results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Row<MT,false,true,true> >&
+ Row<MT,false,true,true>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ return operator=( (*this) / rhs );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the row.
+//
+// \return The size of the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Row<MT,false,true,true>::size() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense row.
+//
+// \return The capacity of the dense row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Row<MT,false,true,true>::capacity() const noexcept
+{
+ return matrix_.capacity( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the row.
+//
+// \return The number of non-zero elements in the row.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of columns of the matrix containing the row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Row<MT,false,true,true>::nonZeros() const
+{
+ return matrix_.nonZeros( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Row<MT,false,true,true>::reset()
+{
+ matrix_.reset( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the row by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the row scaling.
+// \return Reference to the dense row.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline Row<MT,false,true,true>& Row<MT,false,true,true>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( row_+1UL )
+ :( row_ ) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( row_ )
+ :( row_+1UL ) )
+ :( size() ) );
+
+ for( size_t i=ibegin; i<iend; ++i ) {
+ matrix_(i,row_) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address can alias with the dense row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,false,true,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can alias with the given dense row \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address can alias with the dense row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense row
+ , bool SO2 // Storage order of the foreign dense row
+ , bool SF2 > // Symmetry flag of the foreign dense row
+inline bool Row<MT,false,true,true>::canAlias( const Row<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( row_ == alias->row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense row. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,false,true,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is aliased with the given dense row \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense row, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense row. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense row
+ , bool SO2 // Storage order of the foreign dense row
+ , bool SF2 > // Symmetry flag of the foreign dense row
+inline bool Row<MT,false,true,true>::isAliased( const Row<MT2,SO2,true,SF2>* alias ) const noexcept
+{
+ return matrix_.isAliased( &alias->matrix_ ) && ( row_ == alias->row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row is properly aligned in memory.
+//
+// \return \a true in case the dense row is aligned, \a false if not.
+//
+// This function returns whether the dense row is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of the dense row are guaranteed to conform to the
+// alignment restrictions of the element type \a Type.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Row<MT,false,true,true>::isAligned() const noexcept
+{
+ return matrix_.isAligned();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense row can be used in SMP assignments.
+//
+// \return \a true in case the dense row can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the dense row can be used in SMP assignments. In contrast to
+// the \a smpAssignable member enumeration, which is based solely on compile time information,
+// this function additionally provides runtime information (as for instance the current size
+// of the dense row).
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Row<MT,false,true,true>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense row. The index
+// must be smaller than the number of matrix columns. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Row<MT,false,true,true>::SIMDType
+ Row<MT,false,true,true>::load( size_t index ) const noexcept
+{
+ return matrix_.load( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense row.
+// The index must be smaller than the number of matrix columns. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Row<MT,false,true,true>::SIMDType
+ Row<MT,false,true,true>::loada( size_t index ) const noexcept
+{
+ return matrix_.loada( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense row.
+// The index must be smaller than the number of matrix columns. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Row<MT,false,true,true>::SIMDType
+ Row<MT,false,true,true>::loadu( size_t index ) const noexcept
+{
+ return matrix_.loadu( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store a specific SIMD element of the dense row. The index
+// must be smaller than the number of matrix columns. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Row<MT,false,true,true>::store( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.store( index, row_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store a specific SIMD element of the dense row. The
+// index must be smaller than the number of matrix columns. This function must \b NOT be
+// called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Row<MT,false,true,true>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.storea( index, row_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unligned store of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store a specific SIMD element of the dense row.
+// The index must be smaller than the number of matrix columns. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Row<MT,false,true,true>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.storeu( index, row_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the dense row.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store a specific SIMD element of the dense
+// row. The index must be smaller than the number of matrix columns. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Row<MT,false,true,true>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ matrix_.stream( index, row_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ Row<MT,false,true,true>::assign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,row_) = (~rhs)[i ];
+ matrix_(i+1UL,row_) = (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,row_) = (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedAssign<VT> >
+ Row<MT,false,true,true>::assign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t rows( size() );
+
+ const size_t ipos( ( remainder )?( rows & size_t(-SIMDSIZE) ):( rows ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ if( useStreaming && rows > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( &matrix_ ) )
+ {
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ else
+ {
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,true,true>::assign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),row_) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ Row<MT,false,true,true>::addAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,row_) += (~rhs)[i ];
+ matrix_(i+1UL,row_) += (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,row_) += (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<VT> >
+ Row<MT,false,true,true>::addAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t rows( size() );
+
+ const size_t ipos( ( remainder )?( rows & size_t(-SIMDSIZE) ):( rows ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left += *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,true,true>::addAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),row_) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ Row<MT,false,true,true>::subAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,row_) -= (~rhs)[i ];
+ matrix_(i+1UL,row_) -= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,row_) -= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<VT> >
+ Row<MT,false,true,true>::subAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t rows( size() );
+
+ const size_t ipos( ( remainder )?( rows & size_t(-SIMDSIZE) ):( rows ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left -= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,true,true>::subAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),row_) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ Row<MT,false,true,true>::multAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,row_) *= (~rhs)[i ];
+ matrix_(i+1UL,row_) *= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,row_) *= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedMultAssign<VT> >
+ Row<MT,false,true,true>::multAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const bool remainder( !IsPadded<MT>::value || !IsPadded<VT>::value );
+ const size_t rows( size() );
+
+ const size_t ipos( ( remainder )?( rows & size_t(-SIMDSIZE) ):( rows ) );
+ BLAZE_INTERNAL_ASSERT( !remainder || ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; remainder && i<rows; ++i ) {
+ *left *= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,true,true>::multAssign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ matrix_(element->index(),row_) = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline DisableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ Row<MT,false,true,true>::divAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( (~rhs).size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(i ,row_) /= (~rhs)[i ];
+ matrix_(i+1UL,row_) /= (~rhs)[i+1UL];
+ }
+ if( ipos < (~rhs).size() )
+ matrix_(ipos,row_) /= (~rhs)[ipos];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline EnableIf_< typename Row<MT,false,true,true>::BLAZE_TEMPLATE VectorizedDivAssign<VT> >
+ Row<MT,false,true,true>::divAssign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t rows( size() );
+
+ const size_t ipos( rows & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( rows - ( rows % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<rows; ++i ) {
+ *left /= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/row/Sparse.h b/src/cpu/blaze/math/views/row/Sparse.h
new file mode 100644
index 00000000..19acd276
--- /dev/null
+++ b/src/cpu/blaze/math/views/row/Sparse.h
@@ -0,0 +1,5340 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/row/Sparse.h
+// \brief Row specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_ROW_SPARSE_H_
+#define _BLAZE_MATH_VIEWS_ROW_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/RowVector.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/View.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Reset.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/RowTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/views/row/BaseTemplate.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR ROW-MAJOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Row for rows on row-major sparse matrices.
+// \ingroup views
+//
+// This specialization of Row adapts the class template to the requirements of row-major sparse
+// matrices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+class Row<MT,true,false,SF>
+ : public SparseVector< Row<MT,true,false,SF>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Row<MT,true,false,SF> This; //!< Type of this Row instance.
+ typedef SparseVector<This,true> BaseType; //!< Base type of this Row instance.
+ typedef RowTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the row elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Row& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant row value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant row value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Row( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Row& operator=( const Row& rhs );
+
+ template< typename VT > inline Row& operator= ( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator= ( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator+=( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator+=( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator-=( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator-=( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator/=( const DenseVector<VT,true>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Row >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Row >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline Iterator set ( size_t index, const ElementType& value );
+ inline Iterator insert ( size_t index, const ElementType& value );
+ inline void erase ( size_t index );
+ inline Iterator erase ( Iterator pos );
+ inline Iterator erase ( Iterator first, Iterator last );
+ inline void reserve( size_t n );
+ template< typename Other > inline Row& scale ( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index );
+ inline ConstIterator find ( size_t index ) const;
+ inline Iterator lowerBound( size_t index );
+ inline ConstIterator lowerBound( size_t index ) const;
+ inline Iterator upperBound( size_t index );
+ inline ConstIterator upperBound( size_t index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append( size_t index, const ElementType& value, bool check=false );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void addAssign( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void addAssign( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void subAssign( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void subAssign( const SparseVector<VT,true>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t extendCapacity() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The sparse matrix containing the row.
+ const size_t row_; //!< The index of the row in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Row<MT2,SO2,DF2,SF2>& row ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Row<MT2,SO2,DF2,SF2>& a, const Row<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Row<MT2,SO2,DF2,SF2> > derestrict( Row<MT2,SO2,DF2,SF2>& row );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Row.
+//
+// \param matrix The matrix containing the row.
+// \param index The index of the row.
+// \exception std::invalid_argument Invalid row access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline Row<MT,true,false,SF>::Row( MT& matrix, size_t index )
+ : matrix_( matrix ) // The sparse matrix containing the row
+ , row_ ( index ) // The index of the row in the matrix
+{
+ if( matrix_.rows() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid row access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Reference Row<MT,true,false,SF>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return matrix_(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstReference
+ Row<MT,true,false,SF>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return const_cast<const MT&>( matrix_ )(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Reference Row<MT,true,false,SF>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstReference Row<MT,true,false,SF>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator Row<MT,true,false,SF>::begin()
+{
+ return matrix_.begin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstIterator Row<MT,true,false,SF>::begin() const
+{
+ return matrix_.cbegin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstIterator Row<MT,true,false,SF>::cbegin() const
+{
+ return matrix_.cbegin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator Row<MT,true,false,SF>::end()
+{
+ return matrix_.end( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstIterator Row<MT,true,false,SF>::end() const
+{
+ return matrix_.cend( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstIterator Row<MT,true,false,SF>::cend() const
+{
+ return matrix_.cend( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Row.
+//
+// \param rhs Sparse row to be copied.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Row sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two rows don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator=( const Row& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Row sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ left.reserve( rhs.nonZeros() );
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for dense vectors.
+//
+// \param rhs Dense vector to be assigned.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ left.reset();
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for sparse vectors.
+//
+// \param rhs Sparse vector to be assigned.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator=( const SparseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ left.reserve( right.nonZeros() );
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a dense vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be added to the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator+=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a sparse vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be added to the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator+=( const SparseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a dense vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be subtracted from the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator-=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a sparse vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be subtracted from the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator-=( const SparseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator*=( const Vector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::operator/=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const DivType tmp( *this / (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse row
+// and a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse row.
+//
+// Via this operator it is possible to scale the sparse row. Note however that the function is
+// subject to three restrictions. First, this operator cannot be used for rows on lower or upper
+// unitriangular matrices. The attempt to scale such a row results in a compilation error!
+// Second, this operator can only be used for numeric data types. And third, the elements of
+// the sparse row must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Row<MT,true,false,SF> >&
+ Row<MT,true,false,SF>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse row by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the sparse row.
+//
+// Via this operator it is possible to scale the sparse row. Note however that the function is
+// subject to three restrictions. First, this operator cannot be used for rows on lower or upper
+// unitriangular matrices. The attempt to scale such a row results in a compilation error!
+// Second, this operator can only be used for numeric data types. And third, the elements of
+// the sparse row must either support the multiplication assignment operator for the given
+// floating point data type or the division assignment operator for the given integral data
+// type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Row<MT,true,false,SF> >&
+ Row<MT,true,false,SF>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= tmp;
+ }
+ else {
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the sparse row.
+//
+// \return The size of the sparse row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline size_t Row<MT,true,false,SF>::size() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse row.
+//
+// \return The capacity of the sparse row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline size_t Row<MT,true,false,SF>::capacity() const noexcept
+{
+ return matrix_.capacity( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the row.
+//
+// \return The number of non-zero elements in the row.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of columns of the matrix containing the row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline size_t Row<MT,true,false,SF>::nonZeros() const
+{
+ return matrix_.nonZeros( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline void Row<MT,true,false,SF>::reset()
+{
+ matrix_.reset( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse row.
+//
+// \param index The index of the element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+//
+// This function sets the value of an element of the sparse row. In case the sparse row already
+// contains an element with index \a index its value is modified, else a new element with the
+// given \a value is inserted.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator
+ Row<MT,true,false,SF>::set( size_t index, const ElementType& value )
+{
+ return matrix_.set( row_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse row.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid sparse row access index.
+//
+// This function inserts a new element into the sparse row. However, duplicate elements
+// are not allowed. In case the sparse row already contains an element at index \a index,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator
+ Row<MT,true,false,SF>::insert( size_t index, const ElementType& value )
+{
+ return matrix_.insert( row_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse row.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline void Row<MT,true,false,SF>::erase( size_t index )
+{
+ matrix_.erase( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse row.
+//
+// \param pos Iterator to the element to be erased.
+// \return void
+//
+// This function erases an element from the sparse row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator Row<MT,true,false,SF>::erase( Iterator pos )
+{
+ return matrix_.erase( row_, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse row.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the sparse row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator
+ Row<MT,true,false,SF>::erase( Iterator first, Iterator last )
+{
+ return matrix_.erase( row_, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse row.
+//
+// \param n The new minimum capacity of the sparse row.
+// \return void
+//
+// This function increases the capacity of the sparse row to at least \a n elements. The
+// current values of the row elements are preserved.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+void Row<MT,true,false,SF>::reserve( size_t n )
+{
+ matrix_.reserve( row_, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse row by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the row scaling.
+// \return Reference to the sparse row.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the scalar value
+inline Row<MT,true,false,SF>& Row<MT,true,false,SF>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating a new sparse row capacity.
+//
+// \return The new sparse row capacity.
+//
+// This function calculates a new row capacity based on the current capacity of the sparse
+// row. Note that the new capacity is restricted to the interval \f$[7..size]\f$.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline size_t Row<MT,true,false,SF>::extendCapacity() const noexcept
+{
+ using blaze::max;
+ using blaze::min;
+
+ size_t nonzeros( 2UL*capacity()+1UL );
+ nonzeros = max( nonzeros, 7UL );
+ nonzeros = min( nonzeros, size() );
+
+ BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific row element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// row. It specifically searches for the element with index \a index. In case the element is
+// found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse row (the end() iterator) is returned. Note that
+// the returned sparse row iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator Row<MT,true,false,SF>::find( size_t index )
+{
+ return matrix_.find( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific row element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// row. It specifically searches for the element with index \a index. In case the element is
+// found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse row (the end() iterator) is returned. Note that
+// the returned sparse row iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstIterator Row<MT,true,false,SF>::find( size_t index ) const
+{
+ return matrix_.find( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator Row<MT,true,false,SF>::lowerBound( size_t index )
+{
+ return matrix_.lowerBound( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstIterator Row<MT,true,false,SF>::lowerBound( size_t index ) const
+{
+ return matrix_.lowerBound( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::Iterator Row<MT,true,false,SF>::upperBound( size_t index )
+{
+ return matrix_.upperBound( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline typename Row<MT,true,false,SF>::ConstIterator Row<MT,true,false,SF>::upperBound( size_t index ) const
+{
+ return matrix_.upperBound( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the sparse row.
+//
+// \param index The index of the new element. The index must be smaller than the number of matrix columns.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse row with elements. It appends
+// a new element to the end of the sparse row without any memory allocation. Therefore it is
+// strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the sparse row
+// - the current number of non-zero elements must be smaller than the capacity of the row
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+inline void Row<MT,true,false,SF>::append( size_t index, const ElementType& value, bool check )
+{
+ matrix_.append( row_, index, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse row can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse row, \a false if not.
+//
+// This function returns whether the given address can alias with the sparse row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,true,false,SF>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse row is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse row, \a false if not.
+//
+// This function returns whether the given address is aliased with the sparse row. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,true,false,SF>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,true,false,SF>::assign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ for( size_t j=0UL; j<size(); ++j )
+ {
+ if( matrix_.nonZeros( row_ ) == matrix_.capacity( row_ ) )
+ matrix_.reserve( row_, extendCapacity() );
+
+ matrix_.append( row_, j, (~rhs)[j], true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,true,false,SF>::assign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ matrix_.append( row_, element->index(), element->value(), true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,true,false,SF>::addAssign( const DenseVector<VT,true>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ matrix_.reset( row_ );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,true,false,SF>::addAssign( const SparseVector<VT,true>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ matrix_.reset( row_ );
+ matrix_.reserve( row_, tmp.nonZeros() );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,true,false,SF>::subAssign( const DenseVector<VT,true>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ matrix_.reset( row_ );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool SF > // Symmetry flag
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,true,false,SF>::subAssign( const SparseVector<VT,true>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ matrix_.reset( row_ );
+ matrix_.reserve( row_, tmp.nonZeros() );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR GENERAL COLUMN-MAJOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Row for general column-major sparse matrices.
+// \ingroup sparse_row
+//
+// This specialization of Row adapts the class template to the requirements of general
+// column-major sparse matrices.
+*/
+template< typename MT > // Type of the sparse matrix
+class Row<MT,false,false,false>
+ : public SparseVector< Row<MT,false,false,false>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Row<MT,false,false,false> This; //!< Type of this Row instance.
+ typedef SparseVector<This,true> BaseType; //!< Base type of this Row instance.
+ typedef RowTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the row elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Row& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant row value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant row value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+ //**********************************************************************************************
+
+ //**RowElement class definition*****************************************************************
+ /*!\brief Access proxy for a specific element of the sparse row.
+ */
+ template< typename MatrixType // Type of the sparse matrix
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class RowElement : private SparseElement
+ {
+ private:
+ //*******************************************************************************************
+ //! Compilation switch for the return type of the value member function.
+ /*! The \a returnConst compile time constant expression represents a compilation switch for
+ the return type of the value member function. In case the given matrix type \a MatrixType
+ is const qualified, \a returnConst will be set to 1 and the value member function will
+ return a reference to const. Otherwise \a returnConst will be set to 0 and the value
+ member function will offer write access to the sparse matrix elements. */
+ enum : bool { returnConst = IsConst<MatrixType>::value };
+ //*******************************************************************************************
+
+ //**Type definitions*************************************************************************
+ //! Type of the underlying sparse elements.
+ typedef typename std::iterator_traits<IteratorType>::value_type SET;
+
+ typedef Reference_<SET> RT; //!< Reference type of the underlying sparse element.
+ typedef ConstReference_<SET> CRT; //!< Reference-to-const type of the underlying sparse element.
+ //*******************************************************************************************
+
+ public:
+ //**Type definitions*************************************************************************
+ typedef ValueType_<SET> ValueType; //!< The value type of the row element.
+ typedef size_t IndexType; //!< The index type of the row element.
+ typedef IfTrue_<returnConst,CRT,RT> Reference; //!< Reference return type
+ typedef CRT ConstReference; //!< Reference-to-const return type.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the RowElement class.
+ //
+ // \param pos Iterator to the current position within the sparse row.
+ // \param column The column index.
+ */
+ inline RowElement( IteratorType pos, size_t column )
+ : pos_ ( pos ) // Iterator to the current position within the sparse row
+ , column_( column ) // Index of the according column
+ {}
+ //*******************************************************************************************
+
+ //**Assignment operator**********************************************************************
+ /*!\brief Assignment to the accessed sparse row element.
+ //
+ // \param value The new value of the sparse row element.
+ // \return Reference to the sparse row element.
+ */
+ template< typename T > inline RowElement& operator=( const T& v ) {
+ *pos_ = v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment to the accessed sparse row element.
+ //
+ // \param value The right-hand side value for the addition.
+ // \return Reference to the sparse row element.
+ */
+ template< typename T > inline RowElement& operator+=( const T& v ) {
+ *pos_ += v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment to the accessed sparse row element.
+ //
+ // \param value The right-hand side value for the subtraction.
+ // \return Reference to the sparse row element.
+ */
+ template< typename T > inline RowElement& operator-=( const T& v ) {
+ *pos_ -= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Multiplication assignment operator*******************************************************
+ /*!\brief Multiplication assignment to the accessed sparse row element.
+ //
+ // \param value The right-hand side value for the multiplication.
+ // \return Reference to the sparse row element.
+ */
+ template< typename T > inline RowElement& operator*=( const T& v ) {
+ *pos_ *= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Division assignment operator*************************************************************
+ /*!\brief Division assignment to the accessed sparse row element.
+ //
+ // \param value The right-hand side value for the division.
+ // \return Reference to the sparse row element.
+ */
+ template< typename T > inline RowElement& operator/=( const T& v ) {
+ *pos_ /= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline const RowElement* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse row element.
+ //
+ // \return The current value of the sparse row element.
+ */
+ inline Reference value() const {
+ return pos_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline IndexType index() const {
+ return column_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current position within the sparse row.
+ size_t column_; //!< Index of the according column.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**RowIterator class definition****************************************************************
+ /*!\brief Iterator over the elements of the sparse row.
+ */
+ template< typename MatrixType // Type of the sparse matrix
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class RowIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef RowElement<MatrixType,IteratorType> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the RowIterator class.
+ */
+ inline RowIterator()
+ : matrix_( nullptr ) // The sparse matrix containing the row.
+ , row_ ( 0UL ) // The current row index.
+ , column_( 0UL ) // The current column index.
+ , pos_ () // Iterator to the current sparse element.
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor of the RowIterator class.
+ //
+ // \param matrix The matrix containing the row.
+ // \param row The row index.
+ // \param column The column index.
+ */
+ inline RowIterator( MatrixType& matrix, size_t row, size_t column )
+ : matrix_( &matrix ) // The sparse matrix containing the row.
+ , row_ ( row ) // The current row index.
+ , column_( column ) // The current column index.
+ , pos_ () // Iterator to the current sparse element.
+ {
+ for( ; column_<matrix_->columns(); ++column_ ) {
+ pos_ = matrix_->find( row_, column_ );
+ if( pos_ != matrix_->end( column_ ) ) break;
+ }
+ }
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the RowIterator class.
+ //
+ // \param matrix The matrix containing the row.
+ // \param row The row index.
+ // \param column The column index.
+ // \param pos Initial position of the iterator
+ */
+ inline RowIterator( MatrixType& matrix, size_t row, size_t column, IteratorType pos )
+ : matrix_( &matrix ) // The sparse matrix containing the row.
+ , row_ ( row ) // The current row index.
+ , column_( column ) // The current column index.
+ , pos_ ( pos ) // Iterator to the current sparse element.
+ {
+ BLAZE_INTERNAL_ASSERT( matrix.find( row, column ) == pos, "Invalid initial iterator position" );
+ }
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different RowIterator instances.
+ //
+ // \param it The row iterator to be copied.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline RowIterator( const RowIterator<MatrixType2,IteratorType2>& it )
+ : matrix_( it.matrix_ ) // The sparse matrix containing the row.
+ , row_ ( it.row_ ) // The current row index.
+ , column_( it.column_ ) // The current column index.
+ , pos_ ( it.pos_ ) // Iterator to the current sparse element.
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline RowIterator& operator++() {
+ ++column_;
+ for( ; column_<matrix_->columns(); ++column_ ) {
+ pos_ = matrix_->find( row_, column_ );
+ if( pos_ != matrix_->end( column_ ) ) break;
+ }
+
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const RowIterator operator++( int ) {
+ const RowIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return The current value of the sparse element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse vector element at the current iterator position.
+ //
+ // \return Reference to the sparse vector element at the current iterator position.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, column_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two RowIterator objects.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline bool operator==( const RowIterator<MatrixType2,IteratorType2>& rhs ) const noexcept {
+ return ( matrix_ == rhs.matrix_ ) && ( row_ == rhs.row_ ) && ( column_ == rhs.column_ );
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two RowIterator objects.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline bool operator!=( const RowIterator<MatrixType2,IteratorType2>& rhs ) const noexcept {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two row iterators.
+ //
+ // \param rhs The right-hand side row iterator.
+ // \return The number of elements between the two row iterators.
+ */
+ inline DifferenceType operator-( const RowIterator& rhs ) const {
+ size_t counter( 0UL );
+ for( size_t j=rhs.column_; j<column_; ++j ) {
+ if( matrix_->find( row_, j ) != matrix_->end( j ) )
+ ++counter;
+ }
+ return counter;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ MatrixType* matrix_; //!< The sparse matrix containing the row.
+ size_t row_; //!< The current row index.
+ size_t column_; //!< The current column index.
+ IteratorType pos_; //!< Iterator to the current sparse element.
+ //*******************************************************************************************
+
+ //**Friend declarations**********************************************************************
+ template< typename MatrixType2, typename IteratorType2 > friend class RowIterator;
+ template< typename MT2, bool SO2, bool DF2, bool SF2 > friend class Row;
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef RowIterator< const MT, ConstIterator_<MT> > ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, RowIterator< MT, Iterator_<MT> > > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Row( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Row& operator= ( const Row& rhs );
+ template< typename VT > inline Row& operator= ( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator+=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator-=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator/=( const DenseVector<VT,true>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Row >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Row >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline Iterator set ( size_t index, const ElementType& value );
+ inline Iterator insert ( size_t index, const ElementType& value );
+ inline void erase ( size_t index );
+ inline Iterator erase ( Iterator pos );
+ inline Iterator erase ( Iterator first, Iterator last );
+ inline void reserve( size_t n );
+ template< typename Other > inline Row& scale ( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index );
+ inline ConstIterator find ( size_t index ) const;
+ inline Iterator lowerBound( size_t index );
+ inline ConstIterator lowerBound( size_t index ) const;
+ inline Iterator upperBound( size_t index );
+ inline ConstIterator upperBound( size_t index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append( size_t index, const ElementType& value, bool check=false );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void addAssign( const Vector<VT,true>& rhs );
+ template< typename VT > inline void subAssign( const Vector<VT,true>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The sparse matrix containing the row.
+ const size_t row_; //!< The index of the row in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Row<MT2,SO2,DF2,SF2>& row ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Row<MT2,SO2,DF2,SF2>& a, const Row<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Row<MT2,SO2,DF2,SF2> > derestrict( Row<MT2,SO2,DF2,SF2>& row );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Row.
+//
+// \param matrix The matrix containing the row.
+// \param index The index of the row.
+// \exception std::invalid_argument Invalid row access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline Row<MT,false,false,false>::Row( MT& matrix, size_t index )
+ : matrix_( matrix ) // The sparse matrix containing the row
+ , row_ ( index ) // The index of the row in the matrix
+{
+ if( matrix_.rows() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid row access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Reference
+ Row<MT,false,false,false>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return matrix_(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstReference
+ Row<MT,false,false,false>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return const_cast<const MT&>( matrix_ )(row_,index);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Reference
+ Row<MT,false,false,false>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstReference
+ Row<MT,false,false,false>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator Row<MT,false,false,false>::begin()
+{
+ return Iterator( matrix_, row_, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstIterator Row<MT,false,false,false>::begin() const
+{
+ return ConstIterator( matrix_, row_, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstIterator Row<MT,false,false,false>::cbegin() const
+{
+ return ConstIterator( matrix_, row_, 0UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator Row<MT,false,false,false>::end()
+{
+ return Iterator( matrix_, row_, size() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstIterator Row<MT,false,false,false>::end() const
+{
+ return ConstIterator( matrix_, row_, size() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstIterator Row<MT,false,false,false>::cend() const
+{
+ return ConstIterator( matrix_, row_, size() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Row.
+//
+// \param rhs Sparse row to be copied.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Row sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two rows don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+inline Row<MT,false,false,false>& Row<MT,false,false,false>::operator=( const Row& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Row sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ assign( left, tmp );
+ }
+ else {
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,false,false>& Row<MT,false,false,false>::operator=( const Vector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const CompositeType_<VT> tmp( ~rhs );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,false,false>& Row<MT,false,false,false>::operator+=( const Vector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,false,false>& Row<MT,false,false,false>::operator-=( const Vector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,false,false>& Row<MT,false,false,false>::operator*=( const Vector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,false,false>&
+ Row<MT,false,false,false>::operator/=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const DivType tmp( *this / (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse row
+// and a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse row.
+//
+// Via this operator it is possible to scale the sparse row. Note however that the function is
+// subject to three restrictions. First, this operator cannot be used for rows on lower or upper
+// unitriangular matrices. The attempt to scale such a row results in a compilation error!
+// Second, this operator can only be used for numeric data types. And third, the elements of
+// the sparse row must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Row<MT,false,false,false> >&
+ Row<MT,false,false,false>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse row by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the sparse row.
+//
+// Via this operator it is possible to scale the sparse row. Note however that the function is
+// subject to three restrictions. First, this operator cannot be used for rows on lower or upper
+// unitriangular matrices. The attempt to scale such a row results in a compilation error!
+// Second, this operator can only be used for numeric data types. And third, the elements of
+// the sparse row must either support the multiplication assignment operator for the given
+// floating point data type or the division assignment operator for the given integral data
+// type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Row<MT,false,false,false> >&
+ Row<MT,false,false,false>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= tmp;
+ }
+ else {
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the row.
+//
+// \return The size of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Row<MT,false,false,false>::size() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse row.
+//
+// \return The capacity of the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Row<MT,false,false,false>::capacity() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the row.
+//
+// \return The number of non-zero elements in the row.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of columns of the matrix containing the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Row<MT,false,false,false>::nonZeros() const
+{
+ size_t counter( 0UL );
+ for( ConstIterator element=begin(); element!=end(); ++element ) {
+ ++counter;
+ }
+ return counter;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Row<MT,false,false,false>::reset()
+{
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( row_+1UL )
+ :( row_ ) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( row_ )
+ :( row_+1UL ) )
+ :( size() ) );
+
+ for( size_t j=jbegin; j<jend; ++j ) {
+ matrix_.erase( row_, j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse row.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid sparse row access index.
+//
+// This function inserts a new element into the sparse row. However, duplicate elements
+// are not allowed. In case the sparse row already contains an element at index \a index,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator
+ Row<MT,false,false,false>::insert( size_t index, const ElementType& value )
+{
+ return Iterator( matrix_, row_, index, matrix_.insert( row_, index, value ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse row.
+//
+// \param index The index of the element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+//
+// This function sets the value of an element of the sparse row. In case the sparse row already
+// contains an element with index \a index its value is modified, else a new element with the
+// given \a value is inserted.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator
+ Row<MT,false,false,false>::set( size_t index, const ElementType& value )
+{
+ return Iterator( matrix_, row_, index, matrix_.set( row_, index, value ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse row.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Row<MT,false,false,false>::erase( size_t index )
+{
+ matrix_.erase( row_, index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse row.
+//
+// \param pos Iterator to the element to be erased.
+// \return void
+//
+// This function erases an element from the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator Row<MT,false,false,false>::erase( Iterator pos )
+{
+ const size_t column( pos.column_ );
+
+ if( column == size() )
+ return pos;
+
+ matrix_.erase( column, pos.pos_ );
+ return Iterator( matrix_, row_, column+1UL );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse row.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator
+ Row<MT,false,false,false>::erase( Iterator first, Iterator last )
+{
+ for( ; first!=last; ++first ) {
+ matrix_.erase( first.column_, first.pos_ );
+ }
+ return last;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse row.
+//
+// \param n The new minimum capacity of the sparse row.
+// \return void
+//
+// This function increases the capacity of the sparse row to at least \a n elements. The
+// current values of the row elements are preserved.
+*/
+template< typename MT > // Type of the sparse matrix
+void Row<MT,false,false,false>::reserve( size_t n )
+{
+ UNUSED_PARAMETER( n );
+
+ return;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse row by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the row scaling.
+// \return Reference to the sparse row.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the scalar value
+inline Row<MT,false,false,false>& Row<MT,false,false,false>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific row element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// row. It specifically searches for the element with index \a index. In case the element is
+// found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse row (the end() iterator) is returned. Note that
+// the returned sparse row iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator Row<MT,false,false,false>::find( size_t index )
+{
+ const Iterator_<MT> pos( matrix_.find( row_, index ) );
+
+ if( pos != matrix_.end( index ) )
+ return Iterator( matrix_, row_, index, pos );
+ else
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific row element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// row. It specifically searches for the element with index \a index. In case the element is
+// found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse row (the end() iterator) is returned. Note that
+// the returned sparse row iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstIterator
+ Row<MT,false,false,false>::find( size_t index ) const
+{
+ const ConstIterator_<MT> pos( matrix_.find( row_, index ) );
+
+ if( pos != matrix_.end( index ) )
+ return ConstIterator( matrix_, row_, index, pos );
+ else
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator
+ Row<MT,false,false,false>::lowerBound( size_t index )
+{
+ for( size_t i=index; i<size(); ++i )
+ {
+ const Iterator_<MT> pos( matrix_.find( row_, i ) );
+
+ if( pos != matrix_.end( i ) )
+ return Iterator( matrix_, row_, i, pos );
+ }
+
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstIterator
+ Row<MT,false,false,false>::lowerBound( size_t index ) const
+{
+ for( size_t i=index; i<size(); ++i )
+ {
+ const ConstIterator_<MT> pos( matrix_.find( row_, i ) );
+
+ if( pos != matrix_.end( i ) )
+ return ConstIterator( matrix_, row_, i, pos );
+ }
+
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::Iterator
+ Row<MT,false,false,false>::upperBound( size_t index )
+{
+ for( size_t i=index+1UL; i<size(); ++i )
+ {
+ const Iterator_<MT> pos( matrix_.find( row_, i ) );
+
+ if( pos != matrix_.end( i ) )
+ return Iterator( matrix_, row_, i, pos );
+ }
+
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,false>::ConstIterator
+ Row<MT,false,false,false>::upperBound( size_t index ) const
+{
+ for( size_t i=index+1UL; i<size(); ++i )
+ {
+ const ConstIterator_<MT> pos( matrix_.find( row_, i ) );
+
+ if( pos != matrix_.end( i ) )
+ return ConstIterator( matrix_, row_, i, pos );
+ }
+
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the sparse row.
+//
+// \param index The index of the new element. The index must be smaller than the number of matrix columns.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse row with elements. It appends
+// a new element to the end of the sparse row without any memory allocation. Therefore it is
+// strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the sparse row
+// - the current number of non-zero elements must be smaller than the capacity of the row
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Row<MT,false,false,false>::append( size_t index, const ElementType& value, bool check )
+{
+ if( !check || !isDefault( value ) )
+ matrix_.insert( row_, index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse row can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse row, \a false if not.
+//
+// This function returns whether the given address can alias with the sparse row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,false,false,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse row is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this row, \a false if not.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,false,false,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,false,false>::assign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( size_t j=0UL; j<(~rhs).size(); ++j ) {
+ matrix_(row_,j) = (~rhs)[j];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,false,false>::assign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ size_t j( 0UL );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ for( ; j<element->index(); ++j )
+ matrix_.erase( row_, j );
+ matrix_(row_,j++) = element->value();
+ }
+ for( ; j<size(); ++j ) {
+ matrix_.erase( row_, j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a vector.
+//
+// \param rhs The right-hand side vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline void Row<MT,false,false,false>::addAssign( const Vector<VT,true>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a vector.
+//
+// \param rhs The right-hand side vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline void Row<MT,false,false,false>::subAssign( const Vector<VT,true>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SYMMETRIC COLUMN-MAJOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Row for symmetric column-major sparse matrices.
+// \ingroup sparse_row
+//
+// This specialization of Row adapts the class template to the requirements of symmetric
+// column-major sparse matrices.
+*/
+template< typename MT > // Type of the sparse matrix
+class Row<MT,false,false,true>
+ : public SparseVector< Row<MT,false,false,true>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Row<MT,false,false,true> This; //!< Type of this Row instance.
+ typedef SparseVector<This,true> BaseType; //!< Base type of this Row instance.
+ typedef RowTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the row elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Row& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant row value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant row value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Row( MT& matrix, size_t index );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Row& operator=( const Row& rhs );
+
+ template< typename VT > inline Row& operator= ( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator= ( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator+=( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator+=( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator-=( const DenseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator-=( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline Row& operator*=( const Vector<VT,true>& rhs );
+ template< typename VT > inline Row& operator/=( const DenseVector<VT,true>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Row >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Row >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline Iterator set ( size_t index, const ElementType& value );
+ inline Iterator insert ( size_t index, const ElementType& value );
+ inline void erase ( size_t index );
+ inline Iterator erase ( Iterator pos );
+ inline Iterator erase ( Iterator first, Iterator last );
+ inline void reserve( size_t n );
+ template< typename Other > inline Row& scale ( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index );
+ inline ConstIterator find ( size_t index ) const;
+ inline Iterator lowerBound( size_t index );
+ inline ConstIterator lowerBound( size_t index ) const;
+ inline Iterator upperBound( size_t index );
+ inline ConstIterator upperBound( size_t index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append( size_t index, const ElementType& value, bool check=false );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename VT > inline void assign ( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void assign ( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void addAssign( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void addAssign( const SparseVector<VT,true>& rhs );
+ template< typename VT > inline void subAssign( const DenseVector <VT,true>& rhs );
+ template< typename VT > inline void subAssign( const SparseVector<VT,true>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t extendCapacity() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The sparse matrix containing the row.
+ const size_t row_; //!< The index of the row in the matrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isIntact( const Row<MT2,SO2,DF2,SF2>& row ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend bool isSame( const Row<MT2,SO2,DF2,SF2>& a, const Row<MT2,SO2,DF2,SF2>& b ) noexcept;
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryAddAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool trySubAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT >
+ friend bool tryMultAssign( const Row<MT2,SO2,DF2,SF2>& lhs, const Vector<VT,true>& rhs, size_t index );
+
+ template< typename MT2, bool SO2, bool DF2, bool SF2 >
+ friend DerestrictTrait_< Row<MT2,SO2,DF2,SF2> > derestrict( Row<MT2,SO2,DF2,SF2>& row );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_BE_SYMMETRIC_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Row.
+//
+// \param matrix The matrix containing the row.
+// \param index The index of the row.
+// \exception std::invalid_argument Invalid row access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline Row<MT,false,false,true>::Row( MT& matrix, size_t index )
+ : matrix_( matrix ) // The sparse matrix containing the row
+ , row_ ( index ) // The index of the row in the matrix
+{
+ if( matrix_.rows() <= index ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid row access index" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Reference
+ Row<MT,false,false,true>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return matrix_(index,row_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstReference
+ Row<MT,false,false,true>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid row access index" );
+ return const_cast<const MT&>( matrix_ )(index,row_);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Reference
+ Row<MT,false,false,true>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the row elements.
+//
+// \param index Access index. The index must be smaller than the number of matrix columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid row access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstReference
+ Row<MT,false,false,true>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator Row<MT,false,false,true>::begin()
+{
+ return matrix_.begin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstIterator Row<MT,false,false,true>::begin() const
+{
+ return matrix_.cbegin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the row.
+//
+// \return Iterator to the first element of the row.
+//
+// This function returns an iterator to the first element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstIterator Row<MT,false,false,true>::cbegin() const
+{
+ return matrix_.cbegin( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator Row<MT,false,false,true>::end()
+{
+ return matrix_.end( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstIterator Row<MT,false,false,true>::end() const
+{
+ return matrix_.cend( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the row.
+//
+// \return Iterator just past the last element of the row.
+//
+// This function returns an iterator just past the last element of the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstIterator Row<MT,false,false,true>::cend() const
+{
+ return matrix_.cend( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Row.
+//
+// \param rhs Sparse row to be copied.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Row sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two rows don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+inline Row<MT,false,false,true>& Row<MT,false,false,true>::operator=( const Row& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Row sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ left.reserve( rhs.nonZeros() );
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for dense vectors.
+//
+// \param rhs Dense vector to be assigned.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,false,false,true>&
+ Row<MT,false,false,true>::operator=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ left.reset();
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for sparse vectors.
+//
+// \param rhs Sparse vector to be assigned.
+// \return Reference to the assigned row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,false,false,true>&
+ Row<MT,false,false,true>::operator=( const SparseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<VT>, const VT& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<VT> tmp( right );
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ left.reserve( right.nonZeros() );
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a dense vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be added to the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,false,false,true>&
+ Row<MT,false,false,true>::operator+=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a sparse vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be added to the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,false,false,true>&
+ Row<MT,false,false,true>::operator+=( const SparseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a dense vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be subtracted from the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline Row<MT,false,false,true>&
+ Row<MT,false,false,true>::operator-=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a sparse vector
+// (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be subtracted from the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower or upper triangular matrix and the
+// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline Row<MT,false,false,true>&
+ Row<MT,false,false,true>::operator-=( const SparseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ left.reserve( tmp.nonZeros() );
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the sparse row.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,false,true>&
+ Row<MT,false,false,true>::operator*=( const Vector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the sparse row.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side vector
+inline Row<MT,false,false,true>&
+ Row<MT,false,false,true>::operator/=( const DenseVector<VT,true>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_<VT> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( DivType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const DivType tmp( *this / (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse row
+// and a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse row.
+//
+// Via this operator it is possible to scale the sparse row. Note however that the function is
+// subject to three restrictions. First, this operator cannot be used for rows on lower or upper
+// unitriangular matrices. The attempt to scale such a row results in a compilation error!
+// Second, this operator can only be used for numeric data types. And third, the elements of
+// the sparse row must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Row<MT,false,false,true> >&
+ Row<MT,false,false,true>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse row by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the sparse row.
+//
+// Via this operator it is possible to scale the sparse row. Note however that the function is
+// subject to three restrictions. First, this operator cannot be used for rows on lower or upper
+// unitriangular matrices. The attempt to scale such a row results in a compilation error!
+// Second, this operator can only be used for numeric data types. And third, the elements of
+// the sparse row must either support the multiplication assignment operator for the given
+// floating point data type or the division assignment operator for the given integral data
+// type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Row<MT,false,false,true> >&
+ Row<MT,false,false,true>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= tmp;
+ }
+ else {
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the sparse row.
+//
+// \return The size of the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Row<MT,false,false,true>::size() const noexcept
+{
+ return matrix_.columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse row.
+//
+// \return The capacity of the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Row<MT,false,false,true>::capacity() const noexcept
+{
+ return matrix_.capacity( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the row.
+//
+// \return The number of non-zero elements in the row.
+//
+// Note that the number of non-zero elements is always less than or equal to the current number
+// of columns of the matrix containing the row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Row<MT,false,false,true>::nonZeros() const
+{
+ return matrix_.nonZeros( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Row<MT,false,false,true>::reset()
+{
+ matrix_.reset( row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse row.
+//
+// \param index The index of the element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+//
+// This function sets the value of an element of the sparse row. In case the sparse row already
+// contains an element with index \a index its value is modified, else a new element with the
+// given \a value is inserted.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator
+ Row<MT,false,false,true>::set( size_t index, const ElementType& value )
+{
+ return matrix_.set( index, row_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse row.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid sparse row access index.
+//
+// This function inserts a new element into the sparse row. However, duplicate elements
+// are not allowed. In case the sparse row already contains an element at index \a index,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator
+ Row<MT,false,false,true>::insert( size_t index, const ElementType& value )
+{
+ return matrix_.insert( index, row_, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse row.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Row<MT,false,false,true>::erase( size_t index )
+{
+ matrix_.erase( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse row.
+//
+// \param pos Iterator to the element to be erased.
+// \return void
+//
+// This function erases an element from the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator
+ Row<MT,false,false,true>::erase( Iterator pos )
+{
+ return matrix_.erase( row_, pos );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse row.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the sparse row.
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator
+ Row<MT,false,false,true>::erase( Iterator first, Iterator last )
+{
+ return matrix_.erase( row_, first, last );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse row.
+//
+// \param n The new minimum capacity of the sparse row.
+// \return void
+//
+// This function increases the capacity of the sparse row to at least \a n elements. The
+// current values of the row elements are preserved.
+*/
+template< typename MT > // Type of the sparse matrix
+void Row<MT,false,false,true>::reserve( size_t n )
+{
+ matrix_.reserve( row_, n );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse row by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the row scaling.
+// \return Reference to the sparse row.
+//
+// This function scales all elements of the row by the given scalar value \a scalar. Note that
+// the function cannot be used to scale a row on a lower or upper unitriangular matrix. The
+// attempt to scale such a row results in a compile time error!
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the scalar value
+inline Row<MT,false,false,true>& Row<MT,false,false,true>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Calculating a new sparse row capacity.
+//
+// \return The new sparse row capacity.
+//
+// This function calculates a new row capacity based on the current capacity of the sparse
+// row. Note that the new capacity is restricted to the interval \f$[7..size]\f$.
+*/
+template< typename MT > // Type of the sparse matrix
+inline size_t Row<MT,false,false,true>::extendCapacity() const
+{
+ using blaze::max;
+ using blaze::min;
+
+ size_t nonzeros( 2UL*capacity()+1UL );
+ nonzeros = max( nonzeros, 7UL );
+ nonzeros = min( nonzeros, size() );
+
+ BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific row element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// row. It specifically searches for the element with index \a index. In case the element is
+// found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse row (the end() iterator) is returned. Note that
+// the returned sparse row iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator
+ Row<MT,false,false,true>::find( size_t index )
+{
+ return matrix_.find( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific row element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// row. It specifically searches for the element with index \a index. In case the element is
+// found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse row (the end() iterator) is returned. Note that
+// the returned sparse row iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstIterator
+ Row<MT,false,false,true>::find( size_t index ) const
+{
+ return matrix_.find( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator
+ Row<MT,false,false,true>::lowerBound( size_t index )
+{
+ return matrix_.lowerBound( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstIterator
+ Row<MT,false,false,true>::lowerBound( size_t index ) const
+{
+ return matrix_.lowerBound( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::Iterator
+ Row<MT,false,false,true>::upperBound( size_t index )
+{
+ return matrix_.upperBound( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse row iterator
+// is subject to invalidation due to inserting operations via the subscript operator or the
+// insert() function!
+*/
+template< typename MT > // Type of the sparse matrix
+inline typename Row<MT,false,false,true>::ConstIterator
+ Row<MT,false,false,true>::upperBound( size_t index ) const
+{
+ return matrix_.upperBound( index, row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the sparse row.
+//
+// \param index The index of the new element. The index must be smaller than the number of matrix columns.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse row with elements. It appends
+// a new element to the end of the sparse row without any memory allocation. Therefore it is
+// strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the sparse row
+// - the current number of non-zero elements must be smaller than the capacity of the row
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT > // Type of the sparse matrix
+inline void Row<MT,false,false,true>::append( size_t index, const ElementType& value, bool check )
+{
+ matrix_.append( index, row_, value, check );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse row can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse row, \a false if not.
+//
+// This function returns whether the given address can alias with the sparse row. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,false,false,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse row is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse row, \a false if not.
+//
+// This function returns whether the given address is aliased with the sparse row. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Row<MT,false,false,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,false,true>::assign( const DenseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ for( size_t i=0UL; i<size(); ++i )
+ {
+ if( matrix_.nonZeros( row_ ) == matrix_.capacity( row_ ) )
+ matrix_.reserve( row_, extendCapacity() );
+
+ matrix_.append( i, row_, (~rhs)[i], true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,false,true>::assign( const SparseVector<VT,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ for( ConstIterator_<VT> element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ matrix_.append( element->index(), row_, element->value(), true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,false,true>::addAssign( const DenseVector<VT,true>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ matrix_.reset( row_ );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,false,true>::addAssign( const SparseVector<VT,true>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ matrix_.reset( row_ );
+ matrix_.reserve( row_, tmp.nonZeros() );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side dense vector
+inline void Row<MT,false,false,true>::subAssign( const DenseVector<VT,true>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ matrix_.reset( row_ );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the sparse matrix
+template< typename VT > // Type of the right-hand side sparse vector
+inline void Row<MT,false,false,true>::subAssign( const SparseVector<VT,true>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ matrix_.reset( row_ );
+ matrix_.reserve( row_, tmp.nonZeros() );
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/submatrix/BaseTemplate.h b/src/cpu/blaze/math/views/submatrix/BaseTemplate.h
new file mode 100644
index 00000000..7a23c47c
--- /dev/null
+++ b/src/cpu/blaze/math/views/submatrix/BaseTemplate.h
@@ -0,0 +1,509 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/submatrix/BaseTemplate.h
+// \brief Header file for the implementation of the Submatrix base template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_SUBMATRIX_BASETEMPLATE_H_
+#define _BLAZE_MATH_VIEWS_SUBMATRIX_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/typetraits/IsColumnMajorMatrix.h>
+#include <blaze/math/typetraits/IsDenseMatrix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup submatrix Submatrix
+// \ingroup views
+*/
+/*!\brief View on a specific submatrix of a dense or sparse matrix.
+// \ingroup submatrix
+//
+// The Submatrix class template represents a view on a specific submatrix of a dense or sparse
+// matrix primitive. The type of the matrix is specified via the first template parameter:
+
+ \code
+ template< typename MT, bool AF, bool SO, bool DF >
+ class Submatrix;
+ \endcode
+
+// - MT: specifies the type of the matrix primitive. Submatrix can be used with every matrix
+// primitive, but does not work with any matrix expression type.
+// - AF: the alignment flag specifies whether the submatrix is aligned (\a blaze::aligned) or
+// unaligned (\a blaze::unaligned). The default value is \a blaze::unaligned.
+// - SO: specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix. This
+// template parameter doesn't have to be explicitly defined, but is automatically derived
+// from the first template parameter.
+// - DF: specifies whether the given matrix type is a dense or sparse matrix type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+//
+// \n \section submatrix_setup Setup of Submatrices
+//
+// A view on a dense or sparse submatrix can be created very conveniently via the \c submatrix()
+// function:
+
+ \code
+ using DenseMatrixType = blaze::DynamicMatrix<double,blaze::rowMajor>;
+
+ DenseMatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a dense submatrix of size 8x16, starting in row 0 and column 4
+ blaze::Submatrix<DenseMatrixType> sm = submatrix( A, 0UL, 4UL, 8UL, 16UL );
+ \endcode
+
+ \code
+ using SparseMatrixType = blaze::CompressedMatrix<double,blaze::rowMajor>;
+
+ SparseMatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a sparse submatrix of size 8x16, starting in row 0 and column 4
+ blaze::Submatrix<SparseMatrixType> sm = submatrix( A, 0UL, 4UL, 8UL, 16UL );
+ \endcode
+
+// This view can be treated as any other dense or sparse matrix, i.e. it can be assigned to, it
+// can be copied from, and it can be used in arithmetic operations. The view can also be used on
+// both sides of an assignment: The submatrix can either be used as an alias to grant write access
+// to a specific submatrix of a matrix primitive on the left-hand side of an assignment or to grant
+// read-access to a specific submatrix of a matrix primitive or expression on the right-hand side
+// of an assignment. The following example demonstrates this in detail:
+
+ \code
+ using DenseMatrixType = blaze::DynamicMatrix<double,blaze::columnMajor>;
+ using SparseMatrixType = blaze::CompressedMatrix<double,blaze::rowMajor>;
+
+ DenseMatrixType A, B;
+ SparseMatrixType C;
+ // ... Resizing and initialization
+
+ // Creating a dense submatrix of size 8x4, starting in row 0 and column 2
+ blaze::Submatrix<DenseMatrixType> sm = submatrix( A, 0UL, 2UL, 8UL, 4UL );
+
+ // Setting the submatrix of A to a 8x4 submatrix of B
+ sm = submatrix( B, 0UL, 0UL, 8UL, 4UL );
+
+ // Copying the sparse matrix C into another 8x4 submatrix of A
+ submatrix( A, 8UL, 2UL, 8UL, 4UL ) = C;
+
+ // Assigning part of the result of a matrix addition to the first submatrix
+ sm = submatrix( B + C, 0UL, 0UL, 8UL, 4UL );
+ \endcode
+
+// \n \section submatrix_element_access Element access
+//
+// A submatrix can be used like any other dense or sparse matrix. For instance, the elements of
+// the submatrix can be directly accessed with the function call operator:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<double,blaze::rowMajor>;
+ MatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a 8x8 submatrix, starting from position (4,4)
+ blaze::Submatrix<MatrixType> sm = submatrix( A, 4UL, 4UL, 8UL, 8UL );
+
+ // Setting the element (0,0) of the submatrix, which corresponds to
+ // the element at position (4,4) in matrix A
+ sm(0,0) = 2.0;
+ \endcode
+
+// Alternatively, the elements of a submatrix can be traversed via (const) iterators. Just as
+// with matrices, in case of non-const submatrices, \c begin() and \c end() return an Iterator,
+// which allows a manipulation of the non-zero values, in case of constant submatrices a
+// ConstIterator is returned:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<int,blaze::rowMajor>;
+ using SubmatrixType = blaze::Submatrix<MatrixType>;
+
+ MatrixType A( 256UL, 512UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to a specific submatrix of matrix A
+ SubmatrixType sm = submatrix( A, 16UL, 16UL, 64UL, 128UL );
+
+ // Traversing the elements of the 0th row via iterators to non-const elements
+ for( SubmatrixType::Iterator it=sm.begin(0); it!=sm.end(0); ++it ) {
+ *it = ...; // OK: Write access to the dense submatrix value.
+ ... = *it; // OK: Read access to the dense submatrix value.
+ }
+
+ // Traversing the elements of the 1st row via iterators to const elements
+ for( SubmatrixType::ConstIterator it=sm.begin(1); it!=sm.end(1); ++it ) {
+ *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = *it; // OK: Read access to the dense submatrix value.
+ }
+ \endcode
+
+ \code
+ using MatrixType = blaze::CompressedMatrix<int,blaze::rowMajor>;
+ using SubmatrixType = blaze::Submatrix<MatrixType>;
+
+ MatrixType A( 256UL, 512UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to a specific submatrix of matrix A
+ SubmatrixType sm = submatrix( A, 16UL, 16UL, 64UL, 128UL );
+
+ // Traversing the elements of the 0th row via iterators to non-const elements
+ for( SubmatrixType::Iterator it=sm.begin(0); it!=sm.end(0); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+
+ // Traversing the elements of the 1st row via iterators to const elements
+ for( SubmatrixType::ConstIterator it=sm.begin(1); it!=sm.end(1); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+ \endcode
+
+// \n \section submatrix_element_insertion Element Insertion
+//
+// Inserting/accessing elements in a sparse submatrix can be done by several alternative functions.
+// The following example demonstrates all options:
+
+ \code
+ using MatrixType = blaze::CompressedMatrix<double,blaze::rowMajor>;
+ MatrixType A( 256UL, 512UL ); // Non-initialized matrix of size 256x512
+
+ using SubmatrixType = blaze::Submatrix<MatrixType>;
+ SubmatrixType sm = submatrix( A, 10UL, 10UL, 16UL, 16UL ); // View on a 16x16 submatrix of A
+
+ // The function call operator provides access to all possible elements of the sparse submatrix,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse submatrix, the element is inserted into the
+ // submatrix.
+ sm(2,4) = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element is
+ // not contained in the submatrix it is inserted into the submatrix, if it is already contained
+ // in the submatrix its value is modified.
+ sm.set( 2UL, 5UL, -1.2 );
+
+ // An alternative for inserting elements into the submatrix is the \c insert() function. However,
+ // it inserts the element only in case the element is not already contained in the submatrix.
+ sm.insert( 2UL, 6UL, 3.7 );
+
+ // Just as in the case of sparse matrices, elements can also be inserted via the \c append()
+ // function. In case of submatrices, \c append() also requires that the appended element's
+ // index is strictly larger than the currently largest non-zero index in the according row
+ // or column of the submatrix and that the according row's or column's capacity is large enough
+ // to hold the new element. Note however that due to the nature of a submatrix, which may be an
+ // alias to the middle of a sparse matrix, the \c append() function does not work as efficiently
+ // for a submatrix as it does for a matrix.
+ sm.reserve( 2UL, 10UL );
+ sm.append( 2UL, 10UL, -2.1 );
+ \endcode
+
+// \n \section submatrix_common_operations Common Operations
+//
+// The current size of the matrix, i.e. the number of rows or columns can be obtained via the
+// \c rows() and \c columns() functions, the current total capacity via the \c capacity() function,
+// and the number of non-zero elements via the \c nonZeros() function. However, since submatrices
+// are views on a specific submatrix of a matrix, several operations are not possible on views,
+// such as resizing and swapping:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<int,blaze::rowMajor>;
+ using SubmatrixType = blaze::Submatrix<MatrixType>;
+
+ MatrixType A;
+ // ... Resizing and initialization
+
+ // Creating a view on the a 8x12 submatrix of matrix A
+ SubmatrixType sm = submatrix( A, 0UL, 0UL, 8UL, 12UL );
+
+ sm.rows(); // Returns the number of rows of the submatrix
+ sm.columns(); // Returns the number of columns of the submatrix
+ sm.capacity(); // Returns the capacity of the submatrix
+ sm.nonZeros(); // Returns the number of non-zero elements contained in the submatrix
+
+ sm.resize( 10UL, 8UL ); // Compilation error: Cannot resize a submatrix of a matrix
+
+ SubmatrixType sm2 = submatrix( A, 8UL, 0UL, 12UL, 8UL );
+ swap( sm, sm2 ); // Compilation error: Swap operation not allowed
+ \endcode
+
+// \n \section submatrix_arithmetic_operations Arithmetic Operations
+//
+// The following example gives an impression of the use of Submatrix within arithmetic operations.
+// All operations (addition, subtraction, multiplication, scaling, ...) can be performed on all
+// possible combinations of dense and sparse matrices with fitting element types:
+
+ \code
+ using DenseMatrixType = blaze::DynamicMatrix<double,blaze::rowMajor>;
+ using SparseMatrixType = blaze::CompressedMatrix<double,blaze::rowMajor>;
+ DenseMatrixType D1, D2, D3;
+ SparseMatrixType S1, S2;
+
+ using SparseVectorType = blaze::CompressedVector<double,blaze::columnVector>;
+ SparseVectorType a, b;
+
+ // ... Resizing and initialization
+
+ using SubmatrixType = blaze::Submatrix<DenseMatrixType>;
+ SubmatrixType sm = submatrix( D1, 0UL, 0UL, 8UL, 8UL ); // View on the 8x8 submatrix of matrix D1
+ // starting from row 0 and column 0
+
+ submatrix( D1, 0UL, 8UL, 8UL, 8UL ) = D2; // Dense matrix initialization of the 8x8 submatrix
+ // starting in row 0 and column 8
+ sm = S1; // Sparse matrix initialization of the second 8x8 submatrix
+
+ D3 = sm + D2; // Dense matrix/dense matrix addition
+ S2 = S1 - submatrix( D1, 8UL, 0UL, 8UL, 8UL ); // Sparse matrix/dense matrix subtraction
+ D2 = sm * submatrix( D1, 8UL, 8UL, 8UL, 8UL ); // Dense matrix/dense matrix multiplication
+
+ submatrix( D1, 8UL, 0UL, 8UL, 8UL ) *= 2.0; // In-place scaling of a submatrix of D1
+ D2 = submatrix( D1, 8UL, 8UL, 8UL, 8UL ) * 2.0; // Scaling of the a submatrix of D1
+ D2 = 2.0 * sm; // Scaling of the a submatrix of D1
+
+ submatrix( D1, 0UL, 8UL, 8UL, 8UL ) += D2; // Addition assignment
+ submatrix( D1, 8UL, 0UL, 8UL, 8UL ) -= S1; // Subtraction assignment
+ submatrix( D1, 8UL, 8UL, 8UL, 8UL ) *= sm; // Multiplication assignment
+
+ a = submatrix( D1, 4UL, 4UL, 8UL, 8UL ) * b; // Dense matrix/sparse vector multiplication
+ \endcode
+
+// \n \section submatrix_aligned_submatrix Aligned Submatrices
+//
+// Usually submatrices can be defined anywhere within a matrix. They may start at any position and
+// may have an arbitrary extension (only restricted by the extension of the underlying matrix).
+// However, in contrast to matrices themselves, which are always properly aligned in memory and
+// therefore can provide maximum performance, this means that submatrices in general have to be
+// considered to be unaligned. This can be made explicit by the \a blaze::unaligned flag:
+
+ \code
+ using blaze::unaligned;
+
+ using DenseMatrixType = blaze::DynamicMatrix<double,blaze::rowMajor>;
+
+ DenseMatrixType A;
+ // ... Resizing and initialization
+
+ // Identical creations of an unaligned submatrix of size 8x8, starting in row 0 and column 0
+ blaze::Submatrix<DenseMatrixType> sm1 = submatrix ( A, 0UL, 0UL, 8UL, 8UL );
+ blaze::Submatrix<DenseMatrixType> sm2 = submatrix<unaligned>( A, 0UL, 0UL, 8UL, 8UL );
+ blaze::Submatrix<DenseMatrixType,unaligned> sm3 = submatrix ( A, 0UL, 0UL, 8UL, 8UL );
+ blaze::Submatrix<DenseMatrixType,unaligned> sm4 = submatrix<unaligned>( A, 0UL, 0UL, 8UL, 8UL );
+ \endcode
+
+// All of these calls to the \c submatrix() function are identical. Whether the alignment flag is
+// explicitly specified or not, it always returns an unaligned submatrix. Whereas this may provide
+// full flexibility in the creation of submatrices, this might result in performance restrictions
+// (even in case the specified submatrix could be aligned). However, it is also possible to create
+// aligned submatrices. Aligned submatrices are identical to unaligned submatrices in all aspects,
+// except that they may pose additional alignment restrictions and therefore have less flexibility
+// during creation, but don't suffer from performance penalties and provide the same performance
+// as the underlying matrix. Aligned submatrices are created by explicitly specifying the
+// \a blaze::aligned flag:
+
+ \code
+ using blaze::aligned;
+
+ // Creating an aligned submatrix of size 8x8, starting in row 0 and column 0
+ blaze::Submatrix<DenseMatrixType,aligned> sv = submatrix<aligned>( A, 0UL, 0UL, 8UL, 8UL );
+ \endcode
+
+// The alignment restrictions refer to system dependent address restrictions for the used element
+// type and the available vectorization mode (SSE, AVX, ...). The following source code gives some
+// examples for a double precision dense matrix, assuming that AVX is available, which packs 4
+// \c double values into a SIMD vector:
+
+ \code
+ using blaze::rowMajor;
+
+ using MatrixType = blaze::DynamicMatrix<double,rowMajor>;
+ using SubmatrixType = blaze::Submatrix<MatrixType,aligned>;
+
+ MatrixType D( 13UL, 17UL );
+ // ... Resizing and initialization
+
+ // OK: Starts at position (0,0) and the number of rows and columns are a multiple of 4
+ SubmatrixType dsm1 = submatrix<aligned>( D, 0UL, 0UL, 8UL, 12UL );
+
+ // OK: First row and column and the number of rows and columns are all a multiple of 4
+ SubmatrixType dsm2 = submatrix<aligned>( D, 4UL, 12UL, 8UL, 16UL );
+
+ // OK: First row and column are a multiple of 4 and the submatrix includes the last row and column
+ SubmatrixType dsm3 = submatrix<aligned>( D, 4UL, 0UL, 9UL, 17UL );
+
+ // Error: First row is not a multiple of 4
+ SubmatrixType dsm4 = submatrix<aligned>( D, 2UL, 4UL, 12UL, 12UL );
+
+ // Error: First column is not a multiple of 4
+ SubmatrixType dsm5 = submatrix<aligned>( D, 0UL, 2UL, 8UL, 8UL );
+
+ // Error: The number of rows is not a multiple of 4 and the submatrix does not include the last row
+ SubmatrixType dsm6 = submatrix<aligned>( D, 0UL, 0UL, 7UL, 8UL );
+
+ // Error: The number of columns is not a multiple of 4 and the submatrix does not include the last column
+ SubmatrixType dsm6 = submatrix<aligned>( D, 0UL, 0UL, 8UL, 11UL );
+ \endcode
+
+// Note that the discussed alignment restrictions are only valid for aligned dense submatrices.
+// In contrast, aligned sparse submatrices at this time don't pose any additional restrictions.
+// Therefore aligned and unaligned sparse submatrices are truly fully identical. Still, in case
+// the blaze::aligned flag is specified during setup, an aligned submatrix is created:
+
+ \code
+ using blaze::aligned;
+
+ using SparseMatrixType = blaze::CompressedMatrix<double,blaze::rowMajor>;
+
+ SparseMatrixType A;
+ // ... Resizing and initialization
+
+ // Creating an aligned submatrix of size 8x8, starting in row 0 and column 0
+ blaze::Submatrix<SparseMatrixType,aligned> sv = submatrix<aligned>( A, 0UL, 0UL, 8UL, 8UL );
+ \endcode
+
+// \n \section submatrix_on_submatrix Submatrix on Submatrix
+//
+// It is also possible to create a submatrix view on another submatrix. In this context it is
+// important to remember that the type returned by the \c submatrix() function is the same type
+// as the type of the given submatrix, since the view on a submatrix is just another view on the
+// underlying dense matrix:
+
+ \code
+ using MatrixType = blaze::DynamicMatrix<double,blaze::rowMajor>;
+ using SubmatrixType = blaze::Submatrix<MatrixType>;
+
+ MatrixType D1;
+
+ // ... Resizing and initialization
+
+ // Creating a submatrix view on the dense matrix D1
+ SubmatrixType sm1 = submatrix( D1, 4UL, 4UL, 8UL, 16UL );
+
+ // Creating a submatrix view on the dense submatrix sm1
+ SubmatrixType sm2 = submatrix( sm1, 1UL, 1UL, 4UL, 8UL );
+ \endcode
+
+// \n \section submatrix_on_symmetric_matrices Submatrix on Symmetric Matrices
+//
+// Submatrices can also be created on symmetric matrices (see the SymmetricMatrix class template):
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+ using blaze::Submatrix;
+
+ using SymmetricDynamicType = SymmetricMatrix< DynamicMatrix<int> >;
+ using SubmatrixType = Submatrix< SymmetricDynamicType >;
+
+ // Setup of a 16x16 symmetric matrix
+ SymmetricDynamicType A( 16UL );
+
+ // Creating a dense submatrix of size 8x12, starting in row 2 and column 4
+ SubmatrixType sm = submatrix( A, 2UL, 4UL, 8UL, 12UL );
+ \endcode
+
+// It is important to note, however, that (compound) assignments to such submatrices have a
+// special restriction: The symmetry of the underlying symmetric matrix must not be broken!
+// Since the modification of element \f$ a_{ij} \f$ of a symmetric matrix also modifies the
+// element \f$ a_{ji} \f$, the matrix to be assigned must be structured such that the symmetry
+// of the symmetric matrix is preserved. Otherwise a \a std::invalid_argument exception is
+// thrown:
+
+ \code
+ using blaze::DynamicMatrix;
+ using blaze::SymmetricMatrix;
+
+ // Setup of two default 4x4 symmetric matrices
+ SymmetricMatrix< DynamicMatrix<int> > A1( 4 ), A2( 4 );
+
+ // Setup of the 3x2 dynamic matrix
+ //
+ // ( 0 9 )
+ // B = ( 9 8 )
+ // ( 0 7 )
+ //
+ DynamicMatrix<int> B( 3UL, 2UL );
+ B(0,0) = 1;
+ B(0,1) = 2;
+ B(1,0) = 3;
+ B(1,1) = 4;
+ B(2,1) = 5;
+ B(2,2) = 6;
+
+ // OK: Assigning B to a submatrix of A1 such that the symmetry can be preserved
+ //
+ // ( 0 0 1 2 )
+ // A1 = ( 0 0 3 4 )
+ // ( 1 3 5 6 )
+ // ( 2 4 6 0 )
+ //
+ submatrix( A1, 0UL, 2UL, 3UL, 2UL ) = B; // OK
+
+ // Error: Assigning B to a submatrix of A2 such that the symmetry cannot be preserved!
+ // The elements marked with X cannot be assigned unambiguously!
+ //
+ // ( 0 1 2 0 )
+ // A2 = ( 1 3 X 0 )
+ // ( 2 X 6 0 )
+ // ( 0 0 0 0 )
+ //
+ submatrix( A2, 0UL, 1UL, 3UL, 2UL ) = B; // Assignment throws an exception!
+ \endcode
+*/
+template< typename MT // Type of the matrix
+ , bool AF = unaligned // Alignment flag
+ , bool SO = IsColumnMajorMatrix<MT>::value // Storage order
+ , bool DF = IsDenseMatrix<MT>::value > // Density flag
+class Submatrix
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/submatrix/Dense.h b/src/cpu/blaze/math/views/submatrix/Dense.h
new file mode 100644
index 00000000..f984705a
--- /dev/null
+++ b/src/cpu/blaze/math/views/submatrix/Dense.h
@@ -0,0 +1,11127 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/submatrix/Dense.h
+// \brief Submatrix specialization for dense matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_SUBMATRIX_DENSE_H_
+#define _BLAZE_MATH_VIEWS_SUBMATRIX_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/Submatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/DenseMatrix.h>
+#include <blaze/math/expressions/View.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/StorageOrder.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsDiagonal.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSparseMatrix.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/typetraits/RequiresEvaluation.h>
+#include <blaze/math/views/submatrix/BaseTemplate.h>
+#include <blaze/system/Blocking.h>
+#include <blaze/system/CacheSize.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED ROW-MAJOR DENSE SUBMATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Submatrix for unaligned row-major dense submatrices.
+// \ingroup views
+//
+// This specialization of Submatrix adapts the class template to the requirements of unaligned
+// row-major dense submatrices.
+*/
+template< typename MT > // Type of the dense matrix
+class Submatrix<MT,unaligned,false,true>
+ : public DenseMatrix< Submatrix<MT,unaligned,false,true>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Submatrix<MT,unaligned,false,true> This; //!< Type of this Submatrix instance.
+ typedef DenseMatrix<This,false> BaseType; //!< Base type of this Submatrix instance.
+ typedef SubmatrixTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the submatrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the submatrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Submatrix& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant submatrix value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant submatrix value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant submatrix value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant submatrix value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+ //**********************************************************************************************
+
+ //**SubmatrixIterator class definition**********************************************************
+ /*!\brief Iterator over the elements of the sparse submatrix.
+ */
+ template< typename IteratorType > // Type of the dense matrix iterator
+ class SubmatrixIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! The iterator category.
+ typedef typename std::iterator_traits<IteratorType>::iterator_category IteratorCategory;
+
+ //! Type of the underlying elements.
+ typedef typename std::iterator_traits<IteratorType>::value_type ValueType;
+
+ //! Pointer return type.
+ typedef typename std::iterator_traits<IteratorType>::pointer PointerType;
+
+ //! Reference return type.
+ typedef typename std::iterator_traits<IteratorType>::reference ReferenceType;
+
+ //! Difference between two iterators.
+ typedef typename std::iterator_traits<IteratorType>::difference_type DifferenceType;
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the SubmatrixIterator class.
+ */
+ inline SubmatrixIterator()
+ : iterator_ ( ) // Iterator to the current submatrix element
+ , isAligned_( false ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor of the SubmatrixIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ // \param isMemoryAligned Memory alignment flag.
+ */
+ inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
+ : iterator_ ( iterator ) // Iterator to the current submatrix element
+ , isAligned_( isMemoryAligned ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different SubmatrixIterator instances.
+ //
+ // \param it The submatrix iterator to be copied.
+ */
+ template< typename IteratorType2 >
+ inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
+ : iterator_ ( it.base() ) // Iterator to the current submatrix element
+ , isAligned_( it.isAligned() ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline SubmatrixIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline SubmatrixIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline SubmatrixIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubmatrixIterator operator++( int ) {
+ return SubmatrixIterator( iterator_++, isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline SubmatrixIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubmatrixIterator operator--( int ) {
+ return SubmatrixIterator( iterator_--, isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return *iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element of the dense submatrix.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element of the submatrix iterator.
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might
+ // result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const noexcept {
+ if( isAligned_ )
+ return loada();
+ else
+ return loadu();
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element of the dense submatrix.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element of the submatrix
+ // iterator. This function must \b NOT be called explicitly! It is used internally for
+ // the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const noexcept {
+ return iterator_.loada();
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element of the dense submatrix.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element of the submatrix
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const noexcept {
+ return iterator_.loadu();
+ }
+ //*******************************************************************************************
+
+ //**Store function***************************************************************************
+ /*!\brief Store of a SIMD element of the dense submatrix.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs a store of the current SIMD element of the submatrix iterator.
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might
+ // result in erroneous results and/or in compilation errors.
+ */
+ inline void store( const SIMDType& value ) const {
+ storeu( value );
+ }
+ //*******************************************************************************************
+
+ //**Storea function**************************************************************************
+ /*!\brief Aligned store of a SIMD element of the dense submatrix.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned store of the current SIMD element of the submatrix
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline void storea( const SIMDType& value ) const {
+ iterator_.storea( value );
+ }
+ //*******************************************************************************************
+
+ //**Storeu function**************************************************************************
+ /*!\brief Unaligned store of a SIMD element of the dense submatrix.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an unaligned store of the current SIMD element of the submatrix
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline void storeu( const SIMDType& value ) const {
+ if( isAligned_ ) {
+ iterator_.storea( value );
+ }
+ else {
+ iterator_.storeu( value );
+ }
+ }
+ //*******************************************************************************************
+
+ //**Stream function**************************************************************************
+ /*!\brief Aligned, non-temporal store of a SIMD element of the dense submatrix.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned, non-temporal store of the current SIMD element of the
+ // submatrix iterator. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void stream( const SIMDType& value ) const {
+ iterator_.stream( value );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const SubmatrixIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const SubmatrixIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const SubmatrixIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const SubmatrixIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const SubmatrixIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const SubmatrixIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a SubmatrixIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
+ return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a SubmatrixIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
+ return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a SubmatrixIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
+ return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the submatrix iterator.
+ //
+ // \return The current position of the submatrix iterator.
+ */
+ inline IteratorType base() const {
+ return iterator_;
+ }
+ //*******************************************************************************************
+
+ //**IsAligned function***********************************************************************
+ /*!\brief Access to the iterator's memory alignment flag.
+ //
+ // \return \a true in case the iterator is aligned, \a false if it is not.
+ */
+ inline bool isAligned() const noexcept {
+ return isAligned_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current submatrix element.
+ bool isAligned_; //!< Memory alignment flag.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef SubmatrixIterator< ConstIterator_<MT> > ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, SubmatrixIterator< Iterator_<MT> > > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t i ) noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Submatrix& operator=( const ElementType& rhs );
+ inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+ inline Submatrix& operator=( const Submatrix& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline Submatrix& operator=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator+=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator-=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename MT2, bool SO2 >
+ inline Submatrix& operator*=( const Matrix<MT2,SO2>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t row() const noexcept;
+ inline size_t rows() const noexcept;
+ inline size_t column() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline Submatrix& transpose();
+ inline Submatrix& ctranspose();
+ template< typename Other > inline Submatrix& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
+ !IsDiagonal<MT2>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
+ HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
+ !IsDiagonal<MT2>::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool AF2, bool SO2 >
+ inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool AF2, bool SO2 >
+ inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool hasOverlap() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the submatrix.
+ const size_t row_; //!< The first row of the submatrix.
+ const size_t column_; //!< The first column of the submatrix.
+ const size_t m_; //!< The number of rows of the submatrix.
+ const size_t n_; //!< The number of columns of the submatrix.
+ const bool isAligned_; //!< Memory alignment flag.
+ /*!< The alignment flag indicates whether the submatrix is fully aligned
+ with respect to the given element type and the available instruction
+ set. In case the submatrix is fully aligned it is possible to use
+ aligned loads and stores instead of unaligned loads and stores. In
+ order to be aligned, the first element of each row/column must be
+ aligned. */
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
+
+ template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend const Submatrix<MT2,AF1,SO2,DF2>
+ submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Submatrix.
+//
+// \param matrix The dense matrix containing the submatrix.
+// \param rindex The index of the first row of the submatrix in the given dense matrix.
+// \param cindex The index of the first column of the submatrix in the given dense matrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// In case the submatrix is not properly specified (i.e. if the specified submatrix is not
+// contained in the given dense matrix) a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,false,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
+ : matrix_ ( matrix ) // The dense matrix containing the submatrix
+ , row_ ( rindex ) // The first row of the submatrix
+ , column_ ( cindex ) // The first column of the submatrix
+ , m_ ( m ) // The number of rows of the submatrix
+ , n_ ( n ) // The number of columns of the submatrix
+ , isAligned_( simdEnabled && matrix.data() != nullptr && checkAlignment( data() ) &&
+ ( m < 2UL || ( matrix.spacing() & size_t(-SIMDSIZE) ) == 0UL ) )
+{
+ if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the dense submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::Reference
+ Submatrix<MT,unaligned,false,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the dense submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::ConstReference
+ Submatrix<MT,unaligned,false,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::Reference
+ Submatrix<MT,unaligned,false,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::ConstReference
+ Submatrix<MT,unaligned,false,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
+// may use techniques such as padding to improve the alignment of the data.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::Pointer
+ Submatrix<MT,unaligned,false,true>::data() noexcept
+{
+ return matrix_.data() + row_*spacing() + column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
+// may use techniques such as padding to improve the alignment of the data.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::ConstPointer
+ Submatrix<MT,unaligned,false,true>::data() const noexcept
+{
+ return matrix_.data() + row_*spacing() + column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::Pointer
+ Submatrix<MT,unaligned,false,true>::data( size_t i ) noexcept
+{
+ return matrix_.data() + (row_+i)*spacing() + column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements of row/column \a i.
+//
+// \param i The row/column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in row/column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::ConstPointer
+ Submatrix<MT,unaligned,false,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data() + (row_+i)*spacing() + column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::Iterator
+ Submatrix<MT,unaligned,false,true>::begin( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return Iterator( matrix_.begin( row_ + i ) + column_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::ConstIterator
+ Submatrix<MT,unaligned,false,true>::begin( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ConstIterator( matrix_.cbegin( row_ + i ) + column_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::ConstIterator
+ Submatrix<MT,unaligned,false,true>::cbegin( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ConstIterator( matrix_.cbegin( row_ + i ) + column_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::Iterator
+ Submatrix<MT,unaligned,false,true>::end( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return Iterator( matrix_.begin( row_ + i ) + column_ + n_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::ConstIterator
+ Submatrix<MT,unaligned,false,true>::end( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ConstIterator( matrix_.cbegin( row_ + i ) + column_ + n_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,false,true>::ConstIterator
+ Submatrix<MT,unaligned,false,true>::cend( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ConstIterator( matrix_.cbegin( row_ + i ) + column_ + n_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all submatrix elements.
+//
+// \param rhs Scalar value to be assigned to all submatrix elements.
+// \return Reference to the assigned submatrix.
+//
+// This function homogeneously assigns the given value to all dense matrix elements. Note that in
+// case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
+// of the underlying matrix are modified.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,false,true>&
+ Submatrix<MT,unaligned,false,true>::operator=( const ElementType& rhs )
+{
+ const size_t iend( row_ + m_ );
+
+ for( size_t i=row_; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all submatrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to submatrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the submatrix
+// by means of an initializer list. The submatrix elements are assigned the values from the given
+// initializer list. Missing values are initialized as default. Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,false,true>&
+ Submatrix<MT,unaligned,false,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ if( list.size() != rows() || determineColumns( list ) > columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), ElementType() );
+ ++i;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Submatrix.
+//
+// \param rhs Sparse submatrix to be copied.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Submatrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The dense submatrix is initialized as a copy of the given dense submatrix. In case the current
+// sizes of the two submatrices don't match, a \a std::invalid_argument exception is thrown. Also,
+// if the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,false,true>&
+ Submatrix<MT,unaligned,false,true>::operator=( const Submatrix& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
+ return *this;
+
+ if( rows() != rhs.rows() || columns() != rhs.columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be assigned.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The dense submatrix is initialized as a copy of the given matrix. In case the current sizes
+// of the two matrices don't match, a \a std::invalid_argument exception is thrown. Also, if
+// the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline Submatrix<MT,unaligned,false,true>&
+ Submatrix<MT,unaligned,false,true>::operator=( const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ if( IsSparseMatrix<MT2>::value )
+ reset();
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<MT2> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
+ Submatrix<MT,unaligned,false,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
+ (~rhs).canAlias( &matrix_ ) ) {
+ const AddType tmp( *this + (~rhs) );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
+ Submatrix<MT,unaligned,false,true>::operator+=( const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
+ Submatrix<MT,unaligned,false,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
+ (~rhs).canAlias( &matrix_ ) ) {
+ const SubType tmp( *this - (~rhs ) );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
+ Submatrix<MT,unaligned,false,true>::operator-=( const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO2 > // Storage order of the right-hand side matrix
+inline Submatrix<MT,unaligned,false,true>&
+ Submatrix<MT,unaligned,false,true>::operator*=( const Matrix<MT2,SO2>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense submatrix
+// and a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the dense submatrix.
+//
+// This operator cannot be used for submatrices on lower or upper unitriangular matrices. The
+// attempt to scale such a submatrix results in a compilation error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,false,true> >&
+ Submatrix<MT,unaligned,false,true>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) * rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense submatrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the dense submatrix.
+//
+// This operator cannot be used for submatrices on lower or upper unitriangular matrices. The
+// attempt to scale such a submatrix results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,false,true> >&
+ Submatrix<MT,unaligned,false,true>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) / rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first row of the submatrix in the underlying dense matrix.
+//
+// \return The index of the first row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::row() const noexcept
+{
+ return row_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of rows of the dense submatrix.
+//
+// \return The number of rows of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first column of the submatrix in the underlying dense matrix.
+//
+// \return The index of the first column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::column() const noexcept
+{
+ return column_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of columns of the dense submatrix.
+//
+// \return The number of columns of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the
+// total number of elements of a row/column. In case the storage order is set to \a rowMajor
+// the function returns the spacing between two rows, in case the storage flag is set to
+// \a columnMajor the function returns the spacing between two columns.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense submatrix.
+//
+// \return The capacity of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::capacity() const noexcept
+{
+ return rows() * columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::capacity( size_t i ) const noexcept
+{
+ UNUSED_PARAMETER( i );
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ return columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the dense submatrix
+//
+// \return The number of non-zero elements in the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::nonZeros() const
+{
+ const size_t iend( row_ + m_ );
+ const size_t jend( column_ + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=row_; i<iend; ++i )
+ for( size_t j=column_; j<jend; ++j )
+ if( !isDefault( matrix_(i,j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,false,true>::nonZeros( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t jend( column_ + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=column_; j<jend; ++j )
+ if( !isDefault( matrix_(row_+i,j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Submatrix<MT,unaligned,false,true>::reset()
+{
+ using blaze::clear;
+
+ for( size_t i=row_; i<row_+m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT > // Type of the dense matrix
+inline void Submatrix<MT,unaligned,false,true>::reset( size_t i )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ clear( matrix_(row_+i,j) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the dense submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,false,true>& Submatrix<MT,unaligned,false,true>::transpose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( trans( *this ) );
+ smpAssign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the dense submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,false,true>& Submatrix<MT,unaligned,false,true>::ctranspose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( ctrans( *this ) );
+ smpAssign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the dense submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the submatrix scaling.
+// \return Reference to the dense submatrix.
+//
+// This function scales all elements of the submatrix by the given scalar value \a scalar. Note
+// that the function cannot be used to scale a submatrix on a lower or upper unitriangular matrix.
+// The attempt to scale such a submatrix results in a compile time error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline Submatrix<MT,unaligned,false,true>&
+ Submatrix<MT,unaligned,false,true>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t iend( row_ + m_ );
+
+ for( size_t i=row_; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ matrix_(i,j) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
+//
+// \return \a true in case an overlap exists, \a false if not.
+//
+// This function checks if in the context of a symmetric matrix the submatrix has an overlap with
+// its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
+// \a false.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,unaligned,false,true>::hasOverlap() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
+
+ if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
+ return false;
+ else return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,unaligned,false,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given dense submatrix \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense submatrix
+ , bool AF2 // Alignment flag of the foreign dense submatrix
+ , bool SO2 > // Storage order of the foreign dense submatrix
+inline bool Submatrix<MT,unaligned,false,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
+{
+ return ( matrix_.isAliased( &alias->matrix_ ) &&
+ ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
+ ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,unaligned,false,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given dense submatrix \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense submatrix
+ , bool AF2 // Alignment flag of the foreign dense submatrix
+ , bool SO2 > // Storage order of the foreign dense submatrix
+inline bool Submatrix<MT,unaligned,false,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
+{
+ return ( matrix_.isAliased( &alias->matrix_ ) &&
+ ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
+ ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is properly aligned in memory.
+//
+// \return \a true in case the submatrix is aligned, \a false if not.
+//
+// This function returns whether the submatrix is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of each row/column of the submatrix are guaranteed to
+// conform to the alignment restrictions of the underlying element type.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,unaligned,false,true>::isAligned() const noexcept
+{
+ return isAligned_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can be used in SMP assignments.
+//
+// \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the submatrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the submatrix).
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,unaligned,false,true>::canSMPAssign() const noexcept
+{
+ return ( rows() > SMP_DMATASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense submatrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the column index (in case of a row-major matrix) or
+// the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
+ Submatrix<MT,unaligned,false,true>::load( size_t i, size_t j ) const noexcept
+{
+ if( isAligned_ )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
+ Submatrix<MT,unaligned,false,true>::loada( size_t i, size_t j ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ return matrix_.loada( row_+i, column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
+ Submatrix<MT,unaligned,false,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ return matrix_.loadu( row_+i, column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense submatrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than the
+// number of columns. Additionally, the column index (in case of a row-major matrix) or the row
+// index (in case of a column-major matrix) must be a multiple of the number of values inside
+// the SIMD element. This function must \b NOT be called explicitly! It is used internally
+// for the performance optimized evaluation of expression templates. Calling this function
+// explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,unaligned,false,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( isAligned_ )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,unaligned,false,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ matrix_.storea( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,unaligned,false,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ matrix_.storeu( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the dense
+// submatrix. The row index must be smaller than the number of rows and the column index must be
+// smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,unaligned,false,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ if( isAligned_ )
+ matrix_.stream( row_+i, column_+j, value );
+ else
+ matrix_.storeu( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
+ Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_+i,column_+j ) = (~rhs)(i,j );
+ matrix_(row_+i,column_+j+1UL) = (~rhs)(i,j+1UL);
+ }
+ if( jpos < n_ ) {
+ matrix_(row_+i,column_+jpos) = (~rhs)(i,jpos);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
+ Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ if( useStreaming && isAligned_ &&
+ m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
+ !(~rhs).isAliased( &matrix_ ) )
+ {
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+ Iterator left( begin(i) );
+ ConstIterator_<MT2> right( (~rhs).begin(i) );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<n_; ++j ) {
+ *left = *right;
+ }
+ }
+ }
+ else
+ {
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+ Iterator left( begin(i) );
+ ConstIterator_<MT2> right( (~rhs).begin(i) );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<n_; ++j ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ matrix_(row_+i,column_+j) = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,false,true>::assign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,false,true>::assign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
+ Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT2>::value ) {
+ matrix_(row_+i,column_+i) += (~rhs)(i,i);
+ }
+ else {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_+i,column_+j ) += (~rhs)(i,j );
+ matrix_(row_+i,column_+j+1UL) += (~rhs)(i,j+1UL);
+ }
+ if( jpos < n_ ) {
+ matrix_(row_+i,column_+jpos) += (~rhs)(i,jpos);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
+ Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT2>::value )
+ ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( jend & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+ Iterator left( begin(i) + jbegin );
+ ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jend; ++j ) {
+ *left += *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ matrix_(row_+i,column_+j) += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,false,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,false,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
+ Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT2>::value ) {
+ matrix_(row_+i,column_+i) -= (~rhs)(i,i);
+ }
+ else {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_+i,column_+j ) -= (~rhs)(i,j );
+ matrix_(row_+i,column_+j+1UL) -= (~rhs)(i,j+1UL);
+ }
+ if( jpos < n_ ) {
+ matrix_(row_+i,column_+jpos) -= (~rhs)(i,jpos);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
+ Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT2>::value )
+ ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( jend & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+ Iterator left( begin(i) + jbegin );
+ ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jend; ++j ) {
+ *left -= *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ matrix_(row_+i,column_+j) -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,false,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,false,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED COLUMN-MAJOR DENSE SUBMATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Submatrix for unaligned column-major dense submatrices.
+// \ingroup submatrix
+//
+// This specialization of Submatrix adapts the class template to the requirements of unaligned
+// column-major dense submatrices.
+*/
+template< typename MT > // Type of the dense matrix
+class Submatrix<MT,unaligned,true,true>
+ : public DenseMatrix< Submatrix<MT,unaligned,true,true>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Submatrix<MT,unaligned,true,true> This; //!< Type of this Submatrix instance.
+ typedef DenseMatrix<This,true> BaseType; //!< Base type of this Submatrix instance.
+ typedef SubmatrixTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the submatrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the submatrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Submatrix& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant submatrix value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant submatrix value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant submatrix value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant submatrix value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+ //**********************************************************************************************
+
+ //**SubmatrixIterator class definition**********************************************************
+ /*!\brief Iterator over the elements of the sparse submatrix.
+ */
+ template< typename IteratorType > // Type of the dense matrix iterator
+ class SubmatrixIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! The iterator category.
+ typedef typename std::iterator_traits<IteratorType>::iterator_category IteratorCategory;
+
+ //! Type of the underlying elements.
+ typedef typename std::iterator_traits<IteratorType>::value_type ValueType;
+
+ //! Pointer return type.
+ typedef typename std::iterator_traits<IteratorType>::pointer PointerType;
+
+ //! Reference return type.
+ typedef typename std::iterator_traits<IteratorType>::reference ReferenceType;
+
+ //! Difference between two iterators.
+ typedef typename std::iterator_traits<IteratorType>::difference_type DifferenceType;
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the SubmatrixIterator class.
+ */
+ inline SubmatrixIterator()
+ : iterator_ ( ) // Iterator to the current submatrix element
+ , isAligned_( false ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor of the SubmatrixIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ // \param finalIterator The final iterator for SIMD operations.
+ // \param remainingElements The number of remaining elements beyond the final iterator.
+ // \param isMemoryAligned Memory alignment flag.
+ */
+ inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
+ : iterator_ ( iterator ) // Iterator to the current submatrix element
+ , isAligned_( isMemoryAligned ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different SubmatrixIterator instances.
+ //
+ // \param it The submatrix iterator to be copied.
+ */
+ template< typename IteratorType2 >
+ inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
+ : iterator_ ( it.base() ) // Iterator to the current submatrix element
+ , isAligned_( it.isAligned() ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline SubmatrixIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline SubmatrixIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline SubmatrixIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubmatrixIterator operator++( int ) {
+ return SubmatrixIterator( iterator_++, isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline SubmatrixIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubmatrixIterator operator--( int ) {
+ return SubmatrixIterator( iterator_--, isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return *iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element of the dense submatrix.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element of the submatrix iterator.
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might
+ // result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const noexcept {
+ if( isAligned_ )
+ return loada();
+ else
+ return loadu();
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element of the dense submatrix.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element of the submatrix
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const noexcept {
+ return iterator_.loada();
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element of the dense submatrix.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element of the submatrix
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const noexcept {
+ return iterator_.loadu();
+ }
+ //*******************************************************************************************
+
+ //**Store function***************************************************************************
+ /*!\brief Store of a SIMD element of the dense submatrix.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs a store of the current SIMD element of the submatrix iterator.
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might
+ // result in erroneous results and/or in compilation errors.
+ */
+ inline void store( const SIMDType& value ) const {
+ storeu( value );
+ }
+ //*******************************************************************************************
+
+ //**Storea function**************************************************************************
+ /*!\brief Aligned store of a SIMD element of the dense submatrix.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned store of the current SIMD element of the submatrix
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline void storea( const SIMDType& value ) const {
+ iterator_.storea( value );
+ }
+ //*******************************************************************************************
+
+ //**Storeu function**************************************************************************
+ /*!\brief Unaligned store of a SIMD element of the dense submatrix.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an unaligned store of the current SIMD element of the submatrix
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline void storeu( const SIMDType& value ) const {
+ if( isAligned_ ) {
+ iterator_.storea( value );
+ }
+ else {
+ iterator_.storeu( value );
+ }
+ }
+ //*******************************************************************************************
+
+ //**Stream function**************************************************************************
+ /*!\brief Aligned, non-temporal store of a SIMD element of the dense submatrix.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned, non-temporal store of the current SIMD element of the
+ // submatrix iterator. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void stream( const SIMDType& value ) const {
+ iterator_.stream( value );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const SubmatrixIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const SubmatrixIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const SubmatrixIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const SubmatrixIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const SubmatrixIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const SubmatrixIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a SubmatrixIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
+ return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a SubmatrixIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
+ return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a SubmatrixIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param inc The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
+ return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the submatrix iterator.
+ //
+ // \return The current position of the submatrix iterator.
+ */
+ inline IteratorType base() const {
+ return iterator_;
+ }
+ //*******************************************************************************************
+
+ //**IsAligned function***********************************************************************
+ /*!\brief Access to the iterator's memory alignment flag.
+ //
+ // \return \a true in case the iterator is aligned, \a false if it is not.
+ */
+ inline bool isAligned() const noexcept {
+ return isAligned_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current submatrix element.
+ bool isAligned_; //!< Memory alignment flag.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef SubmatrixIterator< ConstIterator_<MT> > ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, SubmatrixIterator< Iterator_<MT> > > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t j ) noexcept;
+ inline ConstPointer data ( size_t j ) const noexcept;
+ inline Iterator begin ( size_t j );
+ inline ConstIterator begin ( size_t j ) const;
+ inline ConstIterator cbegin( size_t j ) const;
+ inline Iterator end ( size_t j );
+ inline ConstIterator end ( size_t j ) const;
+ inline ConstIterator cend ( size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Submatrix& operator=( const ElementType& rhs );
+ inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+ inline Submatrix& operator=( const Submatrix& rhs );
+
+ template< typename MT2, bool SO >
+ inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t row() const noexcept;
+ inline size_t rows() const noexcept;
+ inline size_t column() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline Submatrix& transpose();
+ inline Submatrix& ctranspose();
+ template< typename Other > inline Submatrix& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
+ !IsDiagonal<MT2>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
+ HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
+ !IsDiagonal<MT2>::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool AF2, bool SO2 >
+ inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool AF2, bool SO2 >
+ inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool hasOverlap() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the submatrix.
+ const size_t row_; //!< The first row of the submatrix.
+ const size_t column_; //!< The first column of the submatrix.
+ const size_t m_; //!< The number of rows of the submatrix.
+ const size_t n_; //!< The number of columns of the submatrix.
+ const bool isAligned_; //!< Memory alignment flag.
+ /*!< The alignment flag indicates whether the submatrix is fully aligned
+ with respect to the given element type and the available instruction
+ set. In case the submatrix is fully aligned it is possible to use
+ aligned loads and stores instead of unaligned loads and stores. In
+ order to be aligned, the first element of each row/column must be
+ aligned. */
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
+
+ template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend const Submatrix<MT2,AF1,SO2,DF2>
+ submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Submatrix.
+//
+// \param matrix The dense matrix containing the submatrix.
+// \param rindex The index of the first row of the submatrix in the given dense matrix.
+// \param cindex The index of the first column of the submatrix in the given dense matrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// In case the submatrix is not properly specified (i.e. if the specified submatrix is not
+// contained in the given dense matrix) a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,true,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
+ : matrix_ ( matrix ) // The dense matrix containing the submatrix
+ , row_ ( rindex ) // The first row of the submatrix
+ , column_ ( cindex ) // The first column of the submatrix
+ , m_ ( m ) // The number of rows of the submatrix
+ , n_ ( n ) // The number of columns of the submatrix
+ , isAligned_( simdEnabled && matrix.data() != nullptr && checkAlignment( data() ) &&
+ ( n < 2UL || ( matrix.spacing() & size_t(-SIMDSIZE) ) == 0UL ) )
+{
+ if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the dense submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::Reference
+ Submatrix<MT,unaligned,true,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the dense submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::ConstReference
+ Submatrix<MT,unaligned,true,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::Reference
+ Submatrix<MT,unaligned,true,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::ConstReference
+ Submatrix<MT,unaligned,true,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
+// may use techniques such as padding to improve the alignment of the data.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::Pointer
+ Submatrix<MT,unaligned,true,true>::data() noexcept
+{
+ return matrix_.data() + row_ + column_*spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
+// may use techniques such as padding to improve the alignment of the data.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::ConstPointer
+ Submatrix<MT,unaligned,true,true>::data() const noexcept
+{
+ return matrix_.data() + row_ + column_*spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::Pointer
+ Submatrix<MT,unaligned,true,true>::data( size_t j ) noexcept
+{
+ return matrix_.data() + row_ + (column_+j)*spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::ConstPointer
+ Submatrix<MT,unaligned,true,true>::data( size_t j ) const noexcept
+{
+ return matrix_.data() + row_ + (column_+j)*spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::Iterator
+ Submatrix<MT,unaligned,true,true>::begin( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return Iterator( matrix_.begin( column_ + j ) + row_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::ConstIterator
+ Submatrix<MT,unaligned,true,true>::begin( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ConstIterator( matrix_.cbegin( column_ + j ) + row_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::ConstIterator
+ Submatrix<MT,unaligned,true,true>::cbegin( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ConstIterator( matrix_.cbegin( column_ + j ) + row_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::Iterator
+ Submatrix<MT,unaligned,true,true>::end( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return Iterator( matrix_.begin( column_ + j ) + row_ + m_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::ConstIterator
+ Submatrix<MT,unaligned,true,true>::end( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ConstIterator( matrix_.cbegin( column_ + j ) + row_ + m_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,unaligned,true,true>::ConstIterator
+ Submatrix<MT,unaligned,true,true>::cend( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ConstIterator( matrix_.cbegin( column_ + j ) + row_ + m_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all submatrix elements.
+//
+// \param rhs Scalar value to be assigned to all submatrix elements.
+// \return Reference to the assigned submatrix.
+//
+// This function homogeneously assigns the given value to all dense matrix elements. Note that in
+// case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
+// of the underlying matrix are modified.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,true,true>&
+ Submatrix<MT,unaligned,true,true>::operator=( const ElementType& rhs )
+{
+ const size_t jend( column_ + n_ );
+
+ for( size_t j=column_; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all submatrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to submatrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the submatrix
+// by means of an initializer list. The submatrix elements are assigned the values from the given
+// initializer list. Missing values are initialized as default. Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,true,true>&
+ Submatrix<MT,unaligned,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ if( list.size() != rows() || determineColumns( list ) > columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ matrix_(row_+i,column_+j) = element;
+ ++j;
+ }
+ for( ; j<n_; ++j ) {
+ matrix_(row_+i,column_+j) = ElementType();
+ }
+ ++i;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Submatrix.
+//
+// \param rhs Sparse submatrix to be copied.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Submatrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The dense submatrix is initialized as a copy of the given dense submatrix. In case the current
+// sizes of the two submatrices don't match, a \a std::invalid_argument exception is thrown. Also,
+// if the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,true,true>&
+ Submatrix<MT,unaligned,true,true>::operator=( const Submatrix& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
+ return *this;
+
+ if( rows() != rhs.rows() || columns() != rhs.columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be assigned.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The dense submatrix is initialized as a copy of the given matrix. In case the current sizes
+// of the two matrices don't match, a \a std::invalid_argument exception is thrown. Also, if
+// the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,unaligned,true,true>&
+ Submatrix<MT,unaligned,true,true>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ if( IsSparseMatrix<MT2>::value )
+ reset();
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<MT2> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
+ Submatrix<MT,unaligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
+ (~rhs).canAlias( &matrix_ ) ) {
+ const AddType tmp( *this + (~rhs) );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
+ Submatrix<MT,unaligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
+ Submatrix<MT,unaligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
+ (~rhs).canAlias( &matrix_ ) ) {
+ const SubType tmp( *this - (~rhs ) );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
+ Submatrix<MT,unaligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,unaligned,true,true>&
+ Submatrix<MT,unaligned,true,true>::operator*=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense submatrix
+// and a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the dense submatrix.
+//
+// This operator cannot be used for submatrices on lower or upper unitriangular matrices. The
+// attempt to scale such a submatrix results in a compilation error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,true,true> >&
+ Submatrix<MT,unaligned,true,true>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) * rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense submatrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the dense submatrix.
+//
+// This operator cannot be used for submatrices on lower or upper unitriangular matrices. The
+// attempt to scale such a submatrix results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,true,true> >&
+ Submatrix<MT,unaligned,true,true>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) / rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first row of the submatrix in the underlying dense matrix.
+//
+// \return The index of the first row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::row() const noexcept
+{
+ return row_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of rows of the dense submatrix.
+//
+// \return The number of rows of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first column of the submatrix in the underlying dense matrix.
+//
+// \return The index of the first column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::column() const noexcept
+{
+ return column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of columns of the dense submatrix.
+//
+// \return The number of columns of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two columns.
+//
+// \return The spacing between the beginning of two columns.
+//
+// This function returns the spacing between the beginning of two columns, i.e. the total
+// number of elements of a column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense submatrix.
+//
+// \return The capacity of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::capacity() const noexcept
+{
+ return rows() * columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified column.
+//
+// \param j The index of the column.
+// \return The current capacity of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::capacity( size_t j ) const noexcept
+{
+ UNUSED_PARAMETER( j );
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the dense submatrix
+//
+// \return The number of non-zero elements in the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::nonZeros() const
+{
+ const size_t iend( row_ + m_ );
+ const size_t jend( column_ + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=column_; j<jend; ++j )
+ for( size_t i=row_; i<iend; ++i )
+ if( !isDefault( matrix_(i,j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified column.
+//
+// \param j The index of the column.
+// \return The number of non-zero elements of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,unaligned,true,true>::nonZeros( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t iend( row_ + m_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=row_; i<iend; ++i )
+ if( !isDefault( matrix_(i,column_+j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Submatrix<MT,unaligned,true,true>::reset()
+{
+ using blaze::clear;
+
+ for( size_t j=column_; j<column_+n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified column to the default initial values.
+//
+// \param j The index of the column.
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Submatrix<MT,unaligned,true,true>::reset( size_t j )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ clear( matrix_(i,column_+j) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the dense submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::transpose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( trans( *this ) );
+ smpAssign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the dense submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::ctranspose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( ctrans( *this ) );
+ smpAssign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the dense submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the submatrix scaling.
+// \return Reference to the dense submatrix.
+//
+// This function scales all elements of the submatrix by the given scalar value \a scalar. Note
+// that the function cannot be used to scale a submatrix on a lower or upper unitriangular matrix.
+// The attempt to scale such a submatrix results in a compile time error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t jend( column_ + n_ );
+
+ for( size_t j=column_; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ matrix_(i,j) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
+//
+// \return \a true in case an overlap exists, \a false if not.
+//
+// This function checks if in the context of a symmetric matrix the submatrix has an overlap with
+// its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
+// \a false.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,unaligned,true,true>::hasOverlap() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
+
+ if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
+ return false;
+ else return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,unaligned,true,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given dense submatrix \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense submatrix
+ , bool AF2 // Alignment flag of the foreign dense submatrix
+ , bool SO2 > // Storage order of the foreign dense submatrix
+inline bool Submatrix<MT,unaligned,true,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
+{
+ return ( matrix_.isAliased( &alias->matrix_ ) &&
+ ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
+ ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,unaligned,true,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given dense submatrix \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense submatrix
+ , bool AF2 // Alignment flag of the foreign dense submatrix
+ , bool SO2 > // Storage order of the foreign dense submatrix
+inline bool Submatrix<MT,unaligned,true,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
+{
+ return ( matrix_.isAliased( &alias->matrix_ ) &&
+ ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
+ ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is properly aligned in memory.
+//
+// \return \a true in case the submatrix is aligned, \a false if not.
+//
+// This function returns whether the submatrix is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of each column of the submatrix are guaranteed to
+// conform to the alignment restrictions of the underlying element type.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,unaligned,true,true>::isAligned() const noexcept
+{
+ return isAligned_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can be used in SMP assignments.
+//
+// \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the submatrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the submatrix).
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,unaligned,true,true>::canSMPAssign() const noexcept
+{
+ return ( columns() > SMP_DMATASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense submatrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
+ Submatrix<MT,unaligned,true,true>::load( size_t i, size_t j ) const noexcept
+{
+ if( isAligned_ )
+ return loada( i, j );
+ else
+ return loadu( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
+ Submatrix<MT,unaligned,true,true>::loada( size_t i, size_t j ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_.loada( row_+i, column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
+ Submatrix<MT,unaligned,true,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_.loadu( row_+i, column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense submatrix. The
+// row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,unaligned,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ if( isAligned_ )
+ storea( i, j, value );
+ else
+ storeu( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,unaligned,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ matrix_.storea( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,unaligned,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ matrix_.storeu( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense submatrix. The row index must be smaller than the number of rows and the column
+// index must be smaller than the number of columns. Additionally, the row index must be a
+// multiple of the number of values inside the SIMD element. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,unaligned,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ if( isAligned_ )
+ matrix_.stream( row_+i, column_+j, value );
+ else
+ matrix_.storeu( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
+ Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(row_+i ,column_+j) = (~rhs)(i ,j);
+ matrix_(row_+i+1UL,column_+j) = (~rhs)(i+1UL,j);
+ }
+ if( ipos < m_ ) {
+ matrix_(row_+ipos,column_+j) = (~rhs)(ipos,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
+ Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ if( useStreaming && isAligned_ &&
+ m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
+ !(~rhs).isAliased( &matrix_ ) )
+ {
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+ Iterator left( begin(j) );
+ ConstIterator_<MT2> right( (~rhs).begin(j) );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<m_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+ else
+ {
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+ Iterator left( begin(j) );
+ ConstIterator_<MT2> right( (~rhs).begin(j) );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<m_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ matrix_(row_+i,column_+j) = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,true,true>::assign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,true,true>::assign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
+ Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT2>::value ) {
+ matrix_(row_+j,column_+j) += (~rhs)(j,j);
+ }
+ else {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(row_+i ,column_+j) += (~rhs)(i ,j);
+ matrix_(row_+i+1UL,column_+j) += (~rhs)(i+1UL,j);
+ }
+ if( ipos < m_ ) {
+ matrix_(row_+ipos,column_+j) += (~rhs)(ipos,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
+ Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( iend & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+ Iterator left( begin(j) + ibegin );
+ ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<iend; ++i ) {
+ *left += *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ matrix_(row_+i,column_+j) += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,true,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,true,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
+ Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT2>::value ) {
+ matrix_(row_+j,column_+j) -= (~rhs)(j,j);
+ }
+ else {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(row_+i ,column_+j) -= (~rhs)(i ,j);
+ matrix_(row_+i+1UL,column_+j) -= (~rhs)(i+1UL,j);
+ }
+ if( ipos < m_ ) {
+ matrix_(row_+ipos,column_+j) -= (~rhs)(ipos,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
+ Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( iend & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+ Iterator left( begin(j) + ibegin );
+ ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<iend; ++i ) {
+ *left -= *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ matrix_(row_+i,column_+j) -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,true,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,unaligned,true,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR ALIGNED ROW-MAJOR DENSE SUBMATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Submatrix for aligned row-major dense submatrices.
+// \ingroup views
+//
+// This specialization of Submatrix adapts the class template to the requirements of aligned
+// row-major dense submatrices.
+*/
+template< typename MT > // Type of the dense matrix
+class Submatrix<MT,aligned,false,true>
+ : public DenseMatrix< Submatrix<MT,aligned,false,true>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Submatrix<MT,aligned,false,true> This; //!< Type of this Submatrix instance.
+ typedef DenseMatrix<This,false> BaseType; //!< Base type of this Submatrix instance.
+ typedef SubmatrixTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the submatrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the submatrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Submatrix& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant submatrix value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant submatrix value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant submatrix value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant submatrix value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t i ) noexcept;
+ inline ConstPointer data ( size_t i ) const noexcept;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Submatrix& operator=( const ElementType& rhs );
+ inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+ inline Submatrix& operator=( const Submatrix& rhs );
+
+ template< typename MT2, bool SO >
+ inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t row() const noexcept;
+ inline size_t rows() const noexcept;
+ inline size_t column() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline Submatrix& transpose();
+ inline Submatrix& ctranspose();
+ template< typename Other > inline Submatrix& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
+ !IsDiagonal<MT2>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
+ HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
+ !IsDiagonal<MT2>::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool AF2, bool SO2 >
+ inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool AF2, bool SO2 >
+ inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool hasOverlap() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the submatrix.
+ const size_t row_; //!< The first row of the submatrix.
+ const size_t column_; //!< The first column of the submatrix.
+ const size_t m_; //!< The number of rows of the submatrix.
+ const size_t n_; //!< The number of columns of the submatrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
+
+ template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend const Submatrix<MT2,AF1,SO2,DF2>
+ submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Submatrix.
+//
+// \param matrix The dense matrix containing the submatrix.
+// \param rindex The index of the first row of the submatrix in the given dense matrix.
+// \param cindex The index of the first column of the submatrix in the given dense matrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// In case the submatrix is not properly specified (i.e. if the specified submatrix is not
+// contained in the given dense matrix) a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,false,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
+ : matrix_( matrix ) // The dense matrix containing the submatrix
+ , row_ ( rindex ) // The first row of the submatrix
+ , column_( cindex ) // The first column of the submatrix
+ , m_ ( m ) // The number of rows of the submatrix
+ , n_ ( n ) // The number of columns of the submatrix
+{
+ if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
+ }
+
+ if( ( simdEnabled && matrix_.data() != nullptr && !checkAlignment( data() ) ) ||
+ ( m_ > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the dense submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::Reference
+ Submatrix<MT,aligned,false,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the dense submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::ConstReference
+ Submatrix<MT,aligned,false,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::Reference
+ Submatrix<MT,aligned,false,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::ConstReference
+ Submatrix<MT,aligned,false,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
+// may use techniques such as padding to improve the alignment of the data.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::Pointer
+ Submatrix<MT,aligned,false,true>::data() noexcept
+{
+ return matrix_.data() + row_*spacing() + column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
+// may use techniques such as padding to improve the alignment of the data.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::ConstPointer
+ Submatrix<MT,aligned,false,true>::data() const noexcept
+{
+ return matrix_.data() + row_*spacing() + column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements of row \a i.
+//
+// \param i The row index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix in row \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::Pointer
+ Submatrix<MT,aligned,false,true>::data( size_t i ) noexcept
+{
+ return matrix_.data() + (row_+i)*spacing() + column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements of row \a i.
+//
+// \param i The row index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix in row \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::ConstPointer
+ Submatrix<MT,aligned,false,true>::data( size_t i ) const noexcept
+{
+ return matrix_.data() + (row_+i)*spacing() + column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::Iterator
+ Submatrix<MT,aligned,false,true>::begin( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ( matrix_.begin( row_ + i ) + column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::ConstIterator
+ Submatrix<MT,aligned,false,true>::begin( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ( matrix_.cbegin( row_ + i ) + column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::ConstIterator
+ Submatrix<MT,aligned,false,true>::cbegin( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ( matrix_.cbegin( row_ + i ) + column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::Iterator
+ Submatrix<MT,aligned,false,true>::end( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ( matrix_.begin( row_ + i ) + column_ + n_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::ConstIterator
+ Submatrix<MT,aligned,false,true>::end( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ( matrix_.cbegin( row_ + i ) + column_ + n_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,false,true>::ConstIterator
+ Submatrix<MT,aligned,false,true>::cend( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
+ return ( matrix_.cbegin( row_ + i ) + column_ + n_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all submatrix elements.
+//
+// \param rhs Scalar value to be assigned to all submatrix elements.
+// \return Reference to the assigned submatrix.
+//
+// This function homogeneously assigns the given value to all dense matrix elements. Note that in
+// case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
+// of the underlying matrix are modified.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,false,true>&
+ Submatrix<MT,aligned,false,true>::operator=( const ElementType& rhs )
+{
+ const size_t iend( row_ + m_ );
+
+ for( size_t i=row_; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all submatrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to submatrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the submatrix
+// by means of an initializer list. The submatrix elements are assigned the values from the given
+// initializer list. Missing values are initialized as default. Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,false,true>&
+ Submatrix<MT,aligned,false,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ if( list.size() != rows() || determineColumns( list ) > columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), ElementType() );
+ ++i;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Submatrix.
+//
+// \param rhs Sparse submatrix to be copied.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Submatrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The dense submatrix is initialized as a copy of the given dense submatrix. In case the current
+// sizes of the two submatrices don't match, a \a std::invalid_argument exception is thrown. Also,
+// if the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,false,true>&
+ Submatrix<MT,aligned,false,true>::operator=( const Submatrix& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
+ return *this;
+
+ if( rows() != rhs.rows() || columns() != rhs.columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be assigned.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The dense submatrix is initialized as a copy of the given matrix. In case the current sizes
+// of the two matrices don't match, a \a std::invalid_argument exception is thrown. Also, if
+// the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,aligned,false,true>&
+ Submatrix<MT,aligned,false,true>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ if( IsSparseMatrix<MT2>::value )
+ reset();
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<MT2> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
+ Submatrix<MT,aligned,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
+ (~rhs).canAlias( &matrix_ ) ) {
+ const AddType tmp( *this + (~rhs) );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
+ Submatrix<MT,aligned,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
+ Submatrix<MT,aligned,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
+ (~rhs).canAlias( &matrix_ ) ) {
+ const SubType tmp( *this - (~rhs ) );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
+ Submatrix<MT,aligned,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,aligned,false,true>&
+ Submatrix<MT,aligned,false,true>::operator*=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense submatrix
+// and a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the dense submatrix.
+//
+// This operator cannot be used for submatrices on lower or upper unitriangular matrices. The
+// attempt to scale such a submatrix results in a compilation error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,false,true> >&
+ Submatrix<MT,aligned,false,true>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) * rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense submatrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the dense submatrix.
+//
+// This operator cannot be used for submatrices on lower or upper unitriangular matrices. The
+// attempt to scale such a submatrix results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,false,true> >&
+ Submatrix<MT,aligned,false,true>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) / rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first row of the submatrix in the underlying dense matrix.
+//
+// \return The index of the first row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::row() const noexcept
+{
+ return row_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of rows of the dense submatrix.
+//
+// \return The number of rows of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first column of the submatrix in the underlying dense matrix.
+//
+// \return The index of the first column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::column() const noexcept
+{
+ return column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of columns of the dense submatrix.
+//
+// \return The number of columns of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two rows/columns.
+//
+// \return The spacing between the beginning of two rows/columns.
+//
+// This function returns the spacing between the beginning of two rows/columns, i.e. the
+// total number of elements of a row/column. In case the storage order is set to \a rowMajor
+// the function returns the spacing between two rows, in case the storage flag is set to
+// \a columnMajor the function returns the spacing between two columns.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense submatrix.
+//
+// \return The capacity of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::capacity() const noexcept
+{
+ return rows() * columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::capacity( size_t i ) const noexcept
+{
+ UNUSED_PARAMETER( i );
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ return columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the dense submatrix
+//
+// \return The number of non-zero elements in the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::nonZeros() const
+{
+ const size_t iend( row_ + m_ );
+ const size_t jend( column_ + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=row_; i<iend; ++i )
+ for( size_t j=column_; j<jend; ++j )
+ if( !isDefault( matrix_(i,j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,false,true>::nonZeros( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t jend( column_ + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=column_; j<jend; ++j )
+ if( !isDefault( matrix_(row_+i,j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Submatrix<MT,aligned,false,true>::reset()
+{
+ using blaze::clear;
+
+ for( size_t i=row_; i<row_+m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT > // Type of the dense matrix
+inline void Submatrix<MT,aligned,false,true>::reset( size_t i )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ clear( matrix_(row_+i,j) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the dense submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::transpose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( trans( *this ) );
+ smpAssign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the dense submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::ctranspose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( ctrans( *this ) );
+ smpAssign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the dense submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the submatrix scaling.
+// \return Reference to the dense submatrix.
+//
+// This function scales all elements of the submatrix by the given scalar value \a scalar. Note
+// that the function cannot be used to scale a submatrix on a lower or upper unitriangular matrix.
+// The attempt to scale such a submatrix results in a compile time error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t iend( row_ + m_ );
+
+ for( size_t i=row_; i<iend; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ for( size_t j=jbegin; j<jend; ++j )
+ matrix_(i,j) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
+//
+// \return \a true in case an overlap exists, \a false if not.
+//
+// This function checks if in the context of a symmetric matrix the submatrix has an overlap with
+// its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
+// \a false.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,aligned,false,true>::hasOverlap() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
+
+ if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
+ return false;
+ else return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,aligned,false,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given dense submatrix \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense submatrix
+ , bool AF2 // Alignment flag of the foreign dense submatrix
+ , bool SO2 > // Storage order of the foreign dense submatrix
+inline bool Submatrix<MT,aligned,false,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
+{
+ return ( matrix_.isAliased( &alias->matrix_ ) &&
+ ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
+ ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,aligned,false,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given dense submatrix \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense submatrix
+ , bool AF2 // Alignment flag of the foreign dense submatrix
+ , bool SO2 > // Storage order of the foreign dense submatrix
+inline bool Submatrix<MT,aligned,false,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
+{
+ return ( matrix_.isAliased( &alias->matrix_ ) &&
+ ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
+ ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is properly aligned in memory.
+//
+// \return \a true in case the submatrix is aligned, \a false if not.
+//
+// This function returns whether the submatrix is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of each row of the submatrix are guaranteed to conform
+// to the alignment restrictions of the underlying element type.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,aligned,false,true>::isAligned() const noexcept
+{
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can be used in SMP assignments.
+//
+// \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the submatrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the submatrix).
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,aligned,false,true>::canSMPAssign() const noexcept
+{
+ return ( rows() > SMP_DMATASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense submatrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the column index (in case of a row-major matrix) or
+// the row index (in case of a column-major matrix) must be a multiple of the number of values
+// inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
+ Submatrix<MT,aligned,false,true>::load( size_t i, size_t j ) const noexcept
+{
+ return loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
+ Submatrix<MT,aligned,false,true>::loada( size_t i, size_t j ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ return matrix_.loada( row_+i, column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
+ Submatrix<MT,aligned,false,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ return matrix_.loadu( row_+i, column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense submatrix. The
+// row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the column index (in case of a row-major matrix)
+// or the row index (in case of a column-major matrix) must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,aligned,false,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ return storea( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the column index (in case of a row-major matrix) or the
+// row index (in case of a column-major matrix) must be a multiple of the number of values inside
+// the SIMD element. This function must \b NOT be called explicitly! It is used internally for
+// the performance optimized evaluation of expression templates. Calling this function explicitly
+// might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,aligned,false,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ return matrix_.storea( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense
+// submatrix. The row index must be smaller than the number of rows and the column index must
+// be smaller than the number of columns. Additionally, the column index (in case of a row-major
+// matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,aligned,false,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ matrix_.storeu( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense submatrix. The row index must be smaller than the number of rows and the column index
+// must be smaller than the number of columns. Additionally, the column index (in case of a
+// row-major matrix) or the row index (in case of a column-major matrix) must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,aligned,false,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
+ BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
+
+ matrix_.stream( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
+ Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_+i,column_+j ) = (~rhs)(i,j );
+ matrix_(row_+i,column_+j+1UL) = (~rhs)(i,j+1UL);
+ }
+ if( jpos < n_ ) {
+ matrix_(row_+i,column_+jpos) = (~rhs)(i,jpos);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
+ Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ if( useStreaming &&
+ m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
+ !(~rhs).isAliased( &matrix_ ) )
+ {
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+ Iterator left( begin(i) );
+ ConstIterator_<MT2> right( (~rhs).begin(i) );
+
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<n_; ++j ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+ else
+ {
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ size_t j( 0UL );
+ Iterator left( begin(i) );
+ ConstIterator_<MT2> right( (~rhs).begin(i) );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<n_; ++j ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ matrix_(row_+i,column_+j) = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,false,true>::assign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,false,true>::assign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
+ Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT2>::value ) {
+ matrix_(row_+i,column_+i) += (~rhs)(i,i);
+ }
+ else {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_+i,column_+j ) += (~rhs)(i,j );
+ matrix_(row_+i,column_+j+1UL) += (~rhs)(i,j+1UL);
+ }
+ if( jpos < n_ ) {
+ matrix_(row_+i,column_+jpos) += (~rhs)(i,jpos);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
+ Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT2>::value )
+ ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( jend & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+ Iterator left( begin(i) + jbegin );
+ ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jend; ++j ) {
+ *left += *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ matrix_(row_+i,column_+j) += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,false,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,false,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
+ Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t jpos( n_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ if( IsDiagonal<MT2>::value ) {
+ matrix_(row_+i,column_+i) -= (~rhs)(i,i);
+ }
+ else {
+ for( size_t j=0UL; j<jpos; j+=2UL ) {
+ matrix_(row_+i,column_+j ) -= (~rhs)(i,j );
+ matrix_(row_+i,column_+j+1UL) -= (~rhs)(i,j+1UL);
+ }
+ if( jpos < n_ ) {
+ matrix_(row_+i,column_+jpos) -= (~rhs)(i,jpos);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
+ Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT2>::value )
+ ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t jend ( ( IsLower<MT2>::value )
+ ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
+ :( n_ ) );
+ BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
+
+ const size_t jpos( jend & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
+
+ size_t j( jbegin );
+ Iterator left( begin(i) + jbegin );
+ ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
+
+ for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jpos; j+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; j<jend; ++j ) {
+ *left -= *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t i=ii; i<iend; ++i ) {
+ for( size_t j=jj; j<jend; ++j ) {
+ matrix_(row_+i,column_+j) -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,false,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,false,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR ALIGNED COLUMN-MAJOR DENSE SUBMATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Submatrix for aligned column-major dense submatrices.
+// \ingroup views
+//
+// This specialization of Submatrix adapts the class template to the requirements of aligned
+// column-major dense submatrices.
+*/
+template< typename MT > // Type of the dense matrix
+class Submatrix<MT,aligned,true,true>
+ : public DenseMatrix< Submatrix<MT,aligned,true,true>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Submatrix<MT,aligned,true,true> This; //!< Type of this Submatrix instance.
+ typedef DenseMatrix<This,true> BaseType; //!< Base type of this Submatrix instance.
+ typedef SubmatrixTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the submatrix elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the submatrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Submatrix& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant submatrix value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant submatrix value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+
+ //! Pointer to a constant submatrix value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant submatrix value.
+ typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<MT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = MT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Pointer data ( size_t j ) noexcept;
+ inline ConstPointer data ( size_t j ) const noexcept;
+ inline Iterator begin ( size_t j );
+ inline ConstIterator begin ( size_t j ) const;
+ inline ConstIterator cbegin( size_t j ) const;
+ inline Iterator end ( size_t j );
+ inline ConstIterator end ( size_t j ) const;
+ inline ConstIterator cend ( size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Submatrix& operator=( const ElementType& rhs );
+ inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
+ inline Submatrix& operator=( const Submatrix& rhs );
+
+ template< typename MT2, bool SO >
+ inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator+=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
+ operator-=( const Matrix<MT2,SO>& rhs );
+
+ template< typename MT2, bool SO >
+ inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t row() const noexcept;
+ inline size_t rows() const noexcept;
+ inline size_t column() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t spacing() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline Submatrix& transpose();
+ inline Submatrix& ctranspose();
+ template< typename Other > inline Submatrix& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
+ !IsDiagonal<MT2>::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename MT2 >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && MT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
+ HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
+ !IsDiagonal<MT2>::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool AF2, bool SO2 >
+ inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename MT2, bool AF2, bool SO2 >
+ inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
+
+ template< typename MT2 >
+ inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 >
+ inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
+
+ template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool hasOverlap() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The dense matrix containing the submatrix.
+ const size_t row_; //!< The first row of the submatrix.
+ const size_t column_; //!< The first column of the submatrix.
+ const size_t m_; //!< The number of rows of the submatrix.
+ const size_t n_; //!< The number of columns of the submatrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
+
+ template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend const Submatrix<MT2,AF1,SO2,DF2>
+ submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Submatrix.
+//
+// \param matrix The dense matrix containing the submatrix.
+// \param rindex The index of the first row of the submatrix in the given dense matrix.
+// \param cindex The index of the first column of the submatrix in the given dense matrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// In case the submatrix is not properly specified (i.e. if the specified submatrix is not
+// contained in the given dense matrix) a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,true,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
+ : matrix_( matrix ) // The dense matrix containing the submatrix
+ , row_ ( rindex ) // The first row of the submatrix
+ , column_( cindex ) // The first column of the submatrix
+ , m_ ( m ) // The number of rows of the submatrix
+ , n_ ( n ) // The number of columns of the submatrix
+{
+ if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
+ }
+
+ if( ( simdEnabled && matrix_.data() != nullptr && !checkAlignment( data() ) ) ||
+ ( n_ > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the dense submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::Reference
+ Submatrix<MT,aligned,true,true>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the dense submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::ConstReference
+ Submatrix<MT,aligned,true,true>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::Reference
+ Submatrix<MT,aligned,true,true>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::ConstReference
+ Submatrix<MT,aligned,true,true>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
+// may use techniques such as padding to improve the alignment of the data.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::Pointer
+ Submatrix<MT,aligned,true,true>::data() noexcept
+{
+ return matrix_.data() + row_ + column_*spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense submatrix. Note that
+// you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
+// may use techniques such as padding to improve the alignment of the data.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::ConstPointer
+ Submatrix<MT,aligned,true,true>::data() const noexcept
+{
+ return matrix_.data() + row_ + column_*spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::Pointer
+ Submatrix<MT,aligned,true,true>::data( size_t j ) noexcept
+{
+ return matrix_.data() + row_ + (column_+j)*spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the submatrix elements of column \a j.
+//
+// \param j The column index.
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage for the elements in column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::ConstPointer
+ Submatrix<MT,aligned,true,true>::data( size_t j ) const noexcept
+{
+ return matrix_.data() + row_ + (column_+j)*spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::Iterator
+ Submatrix<MT,aligned,true,true>::begin( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ( matrix_.begin( column_ + j ) + row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::ConstIterator
+ Submatrix<MT,aligned,true,true>::begin( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ( matrix_.cbegin( column_ + j ) + row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::ConstIterator
+ Submatrix<MT,aligned,true,true>::cbegin( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ( matrix_.cbegin( column_ + j ) + row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::Iterator
+ Submatrix<MT,aligned,true,true>::end( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ( matrix_.begin( column_ + j ) + row_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::ConstIterator
+ Submatrix<MT,aligned,true,true>::end( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ( matrix_.cbegin( column_ + j ) + row_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline typename Submatrix<MT,aligned,true,true>::ConstIterator
+ Submatrix<MT,aligned,true,true>::cend( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
+ return ( matrix_.cbegin( column_ + j ) + row_ + m_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all submatrix elements.
+//
+// \param rhs Scalar value to be assigned to all submatrix elements.
+// \return Reference to the assigned submatrix.
+//
+// This function homogeneously assigns the given value to all dense matrix elements. Note that in
+// case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
+// of the underlying matrix are modified.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,true,true>&
+ Submatrix<MT,aligned,true,true>::operator=( const ElementType& rhs )
+{
+ const size_t jend( column_ + n_ );
+
+ for( size_t j=column_; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ matrix_(i,j) = rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all submatrix elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to submatrix.
+//
+// This assignment operator offers the option to directly assign to all elements of the submatrix
+// by means of an initializer list. The submatrix elements are assigned the values from the given
+// initializer list. Missing values are initialized as default. Note that in case the size
+// of the top-level initializer list exceeds the number of rows or the size of any nested list
+// exceeds the number of columns, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,true,true>&
+ Submatrix<MT,aligned,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
+{
+ if( list.size() != rows() || determineColumns( list ) > columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
+ }
+
+ size_t i( 0UL );
+
+ for( const auto& rowList : list ) {
+ size_t j( 0UL );
+ for( const auto& element : rowList ) {
+ matrix_(row_+i,column_+j) = element;
+ ++j;
+ }
+ for( ; j<n_; ++j ) {
+ matrix_(row_+i,column_+j) = ElementType();
+ }
+ ++i;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Submatrix.
+//
+// \param rhs Sparse submatrix to be copied.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Submatrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The dense submatrix is initialized as a copy of the given dense submatrix. In case the current
+// sizes of the two submatrices don't match, a \a std::invalid_argument exception is thrown. Also,
+// if the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,true,true>&
+ Submatrix<MT,aligned,true,true>::operator=( const Submatrix& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
+ return *this;
+
+ if( rows() != rhs.rows() || columns() != rhs.columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be assigned.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The dense submatrix is initialized as a copy of the given dense submatrix. In case the
+// current sizes of the two matrices don't match, a \a std::invalid_argument exception is
+// thrown. Also, if the underlying matrix \a MT is a symmetric matrix and the assignment
+// would violate its symmetry, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,aligned,true,true>&
+ Submatrix<MT,aligned,true,true>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ if( IsSparseMatrix<MT2>::value )
+ reset();
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<MT2> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
+ Submatrix<MT,aligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
+ (~rhs).canAlias( &matrix_ ) ) {
+ const AddType tmp( *this + (~rhs) );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
+ Submatrix<MT,aligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
+ Submatrix<MT,aligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
+ (~rhs).canAlias( &matrix_ ) ) {
+ const SubType tmp( *this - (~rhs ) );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, ~rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
+ Submatrix<MT,aligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the dense submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,aligned,true,true>&
+ Submatrix<MT,aligned,true,true>::operator*=( const Matrix<MT2,SO>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a dense submatrix
+// and a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the dense submatrix.
+//
+// This operator cannot be used for submatrices on lower or upper unitriangular matrices. The
+// attempt to scale such a submatrix results in a compilation error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,true,true> >&
+ Submatrix<MT,aligned,true,true>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) * rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense submatrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the dense submatrix.
+//
+// This operator cannot be used for submatrices on lower or upper unitriangular matrices. The
+// attempt to scale such a submatrix results in a compilation error!
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,true,true> >&
+ Submatrix<MT,aligned,true,true>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) / rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first row of the submatrix in the underlying dense matrix.
+//
+// \return The index of the first row.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::row() const noexcept
+{
+ return row_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of rows of the dense submatrix.
+//
+// \return The number of rows of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first column of the submatrix in the underlying dense matrix.
+//
+// \return The index of the first column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::column() const noexcept
+{
+ return column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of columns of the dense submatrix.
+//
+// \return The number of columns of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the spacing between the beginning of two columns.
+//
+// \return The spacing between the beginning of two columns.
+//
+// This function returns the spacing between the beginning of two columns, i.e. the total
+// number of elements of a column.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::spacing() const noexcept
+{
+ return matrix_.spacing();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense submatrix.
+//
+// \return The capacity of the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::capacity() const noexcept
+{
+ return rows() * columns();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified column.
+//
+// \param j The index of the column.
+// \return The current capacity of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::capacity( size_t j ) const noexcept
+{
+ UNUSED_PARAMETER( j );
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return rows();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the dense submatrix
+//
+// \return The number of non-zero elements in the dense submatrix.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::nonZeros() const
+{
+ const size_t iend( row_ + m_ );
+ const size_t jend( column_ + n_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t j=column_; j<jend; ++j )
+ for( size_t i=row_; i<iend; ++i )
+ if( !isDefault( matrix_(i,j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified column.
+//
+// \param j The index of the column.
+// \return The number of non-zero elements of column \a j.
+*/
+template< typename MT > // Type of the dense matrix
+inline size_t Submatrix<MT,aligned,true,true>::nonZeros( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t iend( row_ + m_ );
+ size_t nonzeros( 0UL );
+
+ for( size_t i=row_; i<iend; ++i )
+ if( !isDefault( matrix_(i,column_+j) ) )
+ ++nonzeros;
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Submatrix<MT,aligned,true,true>::reset()
+{
+ using blaze::clear;
+
+ for( size_t j=column_; j<column_+n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ clear( matrix_(i,j) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified column to the default initial values.
+//
+// \param j The index of the column.
+// \return void
+*/
+template< typename MT > // Type of the dense matrix
+inline void Submatrix<MT,aligned,true,true>::reset( size_t j )
+{
+ using blaze::clear;
+
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ clear( matrix_(i,column_+j) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the dense submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::transpose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( trans( *this ) );
+ smpAssign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the dense submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT > // Type of the dense matrix
+inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::ctranspose()
+{
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( ctrans( *this ) );
+ smpAssign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the dense submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the submatrix scaling.
+// \return Reference to the dense submatrix.
+//
+// This function scales all elements of the submatrix by the given scalar value \a scalar. Note
+// that the function cannot be used to scale a submatrix on a lower or upper unitriangular matrix.
+// The attempt to scale such a submatrix results in a compile time error!
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the scalar value
+inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ const size_t jend( column_ + n_ );
+
+ for( size_t j=column_; j<jend; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ for( size_t i=ibegin; i<iend; ++i )
+ matrix_(i,j) *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
+//
+// \return \a true in case an overlap exists, \a false if not.
+//
+// This function checks if in the context of a symmetric matrix the submatrix has an overlap with
+// its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
+// \a false.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,aligned,true,true>::hasOverlap() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
+
+ if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
+ return false;
+ else return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,aligned,true,true>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given dense submatrix \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense submatrix
+ , bool AF2 // Alignment flag of the foreign dense submatrix
+ , bool SO2 > // Storage order of the foreign dense submatrix
+inline bool Submatrix<MT,aligned,true,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
+{
+ return ( matrix_.isAliased( &alias->matrix_ ) &&
+ ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
+ ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,aligned,true,true>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given dense submatrix \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 // Data type of the foreign dense submatrix
+ , bool AF2 // Alignment flag of the foreign dense submatrix
+ , bool SO2 > // Storage order of the foreign dense submatrix
+inline bool Submatrix<MT,aligned,true,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
+{
+ return ( matrix_.isAliased( &alias->matrix_ ) &&
+ ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
+ ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is properly aligned in memory.
+//
+// \return \a true in case the submatrix is aligned, \a false if not.
+//
+// This function returns whether the submatrix is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of each column of the submatrix are guaranteed to
+// conform to the alignment restrictions of the underlying element type.
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,aligned,true,true>::isAligned() const noexcept
+{
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can be used in SMP assignments.
+//
+// \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the submatrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the submatrix).
+*/
+template< typename MT > // Type of the dense matrix
+inline bool Submatrix<MT,aligned,true,true>::canSMPAssign() const noexcept
+{
+ return ( columns() > SMP_DMATASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense submatrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
+ Submatrix<MT,aligned,true,true>::load( size_t i, size_t j ) const noexcept
+{
+ return loada( i, j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number
+// of values inside the SIMD element. This function must \b NOT be called explicitly! It is
+// used internally for the performance optimized evaluation of expression templates. Calling
+// this function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
+ Submatrix<MT,aligned,true,true>::loada( size_t i, size_t j ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_.loada( row_+i, column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
+ Submatrix<MT,aligned,true,true>::loadu( size_t i, size_t j ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_.loadu( row_+i, column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store of a specific SIMD element of the dense submatrix. The row
+// index must be smaller than the number of rows and the column index must be smaller than
+// the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,aligned,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ storea( i, j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,aligned,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ matrix_.storea( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store of a specific SIMD element of the dense submatrix.
+// The row index must be smaller than the number of rows and the column index must be smaller
+// than the number of columns. Additionally, the row index must be a multiple of the number of
+// values inside the SIMD element. This function must \b NOT be called explicitly! It is used
+// internally for the performance optimized evaluation of expression templates. Calling this
+// function explicitly might result in erroneous results and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,aligned,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ matrix_.storeu( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the submatrix.
+//
+// \param i Access index for the row. The index has to be in the range [0..M-1].
+// \param j Access index for the column. The index has to be in the range [0..N-1].
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store of a specific SIMD element of the
+// dense submatrix. The row index must be smaller than the number of rows and the column
+// index must be smaller than the number of columns. Additionally, the row index must be
+// a multiple of the number of values inside the SIMD element. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename MT > // Type of the dense matrix
+BLAZE_ALWAYS_INLINE void
+ Submatrix<MT,aligned,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
+ BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
+
+ matrix_.stream( row_+i, column_+j, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
+ Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(row_+i ,column_+j) = (~rhs)(i ,j);
+ matrix_(row_+i+1UL,column_+j) = (~rhs)(i+1UL,j);
+ }
+ if( ipos < m_ ) {
+ matrix_(row_+ipos,column_+j) = (~rhs)(ipos,j);
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
+ Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ if( useStreaming &&
+ m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
+ !(~rhs).isAliased( &matrix_ ) )
+ {
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+ Iterator left( begin(j) );
+ ConstIterator_<MT2> right( (~rhs).begin(j) );
+
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<m_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+ else
+ {
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ size_t i( 0UL );
+ Iterator left( begin(j) );
+ ConstIterator_<MT2> right( (~rhs).begin(j) );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<m_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ matrix_(row_+i,column_+j) = (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,true,true>::assign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,true,true>::assign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
+ Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT2>::value ) {
+ matrix_(row_+j,column_+j) += (~rhs)(j,j);
+ }
+ else {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(row_+i ,column_+j) += (~rhs)(i ,j);
+ matrix_(row_+i+1UL,column_+j) += (~rhs)(i+1UL,j);
+ }
+ if( ipos < m_ ) {
+ matrix_(row_+ipos,column_+j) += (~rhs)(ipos,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
+ Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( iend & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+ Iterator left( begin(j) + ibegin );
+ ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<iend; ++i ) {
+ *left += *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ matrix_(row_+i,column_+j) += (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,true,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,true,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
+ Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t ipos( m_ & size_t(-2) );
+ BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ if( IsDiagonal<MT2>::value ) {
+ matrix_(row_+j,column_+j) -= (~rhs)(j,j);
+ }
+ else {
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ matrix_(row_+i ,column_+j) -= (~rhs)(i ,j);
+ matrix_(row_+i+1UL,column_+j) -= (~rhs)(i+1UL,j);
+ }
+ if( ipos < m_ ) {
+ matrix_(row_+ipos,column_+j) -= (~rhs)(ipos,j);
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a column-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
+ Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
+ :( 0UL ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
+ :( m_ ) );
+ BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
+
+ const size_t ipos( iend & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( ibegin );
+ Iterator left( begin(j) + ibegin );
+ ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<iend; ++i ) {
+ *left -= *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side dense matrix
+inline void Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ const size_t block( BLOCK_SIZE );
+
+ for( size_t jj=0UL; jj<n_; jj+=block ) {
+ const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
+ for( size_t ii=0UL; ii<m_; ii+=block ) {
+ const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
+ for( size_t j=jj; j<jend; ++j ) {
+ for( size_t i=ii; i<iend; ++i ) {
+ matrix_(row_+i,column_+j) -= (~rhs)(i,j);
+ }
+ }
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,true,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t j=0UL; j<n_; ++j )
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ matrix_(row_+element->index(),column_+j) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT > // Type of the dense matrix
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,aligned,true,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
+
+ for( size_t i=0UL; i<m_; ++i )
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ matrix_(row_+i,column_+element->index()) -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/submatrix/Sparse.h b/src/cpu/blaze/math/views/submatrix/Sparse.h
new file mode 100644
index 00000000..7d814b88
--- /dev/null
+++ b/src/cpu/blaze/math/views/submatrix/Sparse.h
@@ -0,0 +1,4940 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/submatrix/Sparse.h
+// \brief Submatrix specialization for sparse matrices
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_SUBMATRIX_SPARSE_H_
+#define _BLAZE_MATH_VIEWS_SUBMATRIX_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <vector>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/ColumnMajorMatrix.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseMatrix.h>
+#include <blaze/math/constraints/Matrix.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/RowMajorMatrix.h>
+#include <blaze/math/constraints/SparseMatrix.h>
+#include <blaze/math/constraints/Submatrix.h>
+#include <blaze/math/constraints/Symmetric.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/UniTriangular.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseMatrix.h>
+#include <blaze/math/expressions/View.h>
+#include <blaze/math/Functions.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/StorageOrder.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubmatrixTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsHermitian.h>
+#include <blaze/math/typetraits/IsLower.h>
+#include <blaze/math/typetraits/IsStrictlyLower.h>
+#include <blaze/math/typetraits/IsStrictlyUpper.h>
+#include <blaze/math/typetraits/IsSymmetric.h>
+#include <blaze/math/typetraits/IsUniLower.h>
+#include <blaze/math/typetraits/IsUniUpper.h>
+#include <blaze/math/typetraits/IsUpper.h>
+#include <blaze/math/views/submatrix/BaseTemplate.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR ROW-MAJOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Submatrix for row-major sparse submatrices.
+// \ingroup views
+//
+// This specialization of Submatrix adapts the class template to the requirements of row-major
+// sparse submatrices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+class Submatrix<MT,AF,false,false>
+ : public SparseMatrix< Submatrix<MT,AF,false,false>, false >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Submatrix<MT,AF,false,false> This; //!< Type of this Submatrix instance.
+ typedef SparseMatrix<This,false> BaseType; //!< Base type of this Submatrix instance.
+ typedef SubmatrixTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the submatrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Submatrix& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant submatrix value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant submatrix value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+ //**********************************************************************************************
+
+ //**SubmatrixElement class definition***********************************************************
+ /*!\brief Access proxy for a specific element of the sparse submatrix.
+ */
+ template< typename MatrixType // Type of the sparse matrix
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class SubmatrixElement : private SparseElement
+ {
+ private:
+ //*******************************************************************************************
+ //! Compilation switch for the return type of the value member function.
+ /*! The \a returnConst compile time constant expression represents a compilation switch for
+ the return type of the value member function. In case the given matrix type \a MatrixType
+ is const qualified, \a returnConst will be set to 1 and the value member function will
+ return a reference to const. Otherwise \a returnConst will be set to 0 and the value
+ member function will offer write access to the sparse matrix elements. */
+ enum : bool { returnConst = IsConst<MatrixType>::value };
+ //*******************************************************************************************
+
+ //**Type definitions*************************************************************************
+ //! Type of the underlying sparse elements.
+ typedef typename std::iterator_traits<IteratorType>::value_type SET;
+
+ typedef Reference_<SET> RT; //!< Reference type of the underlying sparse element.
+ typedef ConstReference_<SET> CRT; //!< Reference-to-const type of the underlying sparse element.
+ //*******************************************************************************************
+
+ public:
+ //**Type definitions*************************************************************************
+ typedef ValueType_<SET> ValueType; //!< The value type of the row element.
+ typedef size_t IndexType; //!< The index type of the row element.
+ typedef IfTrue_<returnConst,CRT,RT> Reference; //!< Reference return type
+ typedef CRT ConstReference; //!< Reference-to-const return type.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SubmatrixElement class.
+ //
+ // \param pos Iterator to the current position within the sparse submatrix.
+ // \param offset The offset within the according row/column of the sparse matrix.
+ */
+ inline SubmatrixElement( IteratorType pos, size_t offset )
+ : pos_ ( pos ) // Iterator to the current position within the sparse submatrix
+ , offset_( offset ) // Row offset within the according sparse matrix
+ {}
+ //*******************************************************************************************
+
+ //**Assignment operator**********************************************************************
+ /*!\brief Assignment to the accessed sparse submatrix element.
+ //
+ // \param v The new value of the sparse submatrix element.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator=( const T& v ) {
+ *pos_ = v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment to the accessed sparse submatrix element.
+ //
+ // \param v The right-hand side value for the addition.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator+=( const T& v ) {
+ *pos_ += v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment to the accessed sparse submatrix element.
+ //
+ // \param v The right-hand side value for the subtraction.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator-=( const T& v ) {
+ *pos_ -= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Multiplication assignment operator*******************************************************
+ /*!\brief Multiplication assignment to the accessed sparse submatrix element.
+ //
+ // \param v The right-hand side value for the multiplication.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator*=( const T& v ) {
+ *pos_ *= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Division assignment operator*************************************************************
+ /*!\brief Division assignment to the accessed sparse submatrix element.
+ //
+ // \param v The right-hand side value for the division.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator/=( const T& v ) {
+ *pos_ /= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse submatrix element at the current iterator position.
+ //
+ // \return Reference to the sparse submatrix element at the current iterator position.
+ */
+ inline const SubmatrixElement* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse submatrix element.
+ //
+ // \return The current value of the sparse submatrix element.
+ */
+ inline Reference value() const {
+ return pos_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline IndexType index() const {
+ return pos_->index() - offset_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current position within the sparse submatrix.
+ size_t offset_; //!< Offset within the according row/column of the sparse matrix.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**SubmatrixIterator class definition**********************************************************
+ /*!\brief Iterator over the elements of the sparse submatrix.
+ */
+ template< typename MatrixType // Type of the sparse matrix
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class SubmatrixIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef SubmatrixElement<MatrixType,IteratorType> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Default constructor**********************************************************************
+ /*!\brief Default constructor for the SubmatrixIterator class.
+ */
+ inline SubmatrixIterator()
+ : pos_ () // Iterator to the current sparse element
+ , offset_() // The offset of the according row/column of the sparse matrix
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SubmatrixIterator class.
+ //
+ // \param iterator Iterator to the current sparse element.
+ // \param index The starting index within the according row/column of the sparse matrix.
+ */
+ inline SubmatrixIterator( IteratorType iterator, size_t index )
+ : pos_ ( iterator ) // Iterator to the current sparse element
+ , offset_( index ) // The offset of the according row/column of the sparse matrix
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different SubmatrixIterator instances.
+ //
+ // \param it The submatrix iterator to be copied.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline SubmatrixIterator( const SubmatrixIterator<MatrixType2,IteratorType2>& it )
+ : pos_ ( it.base() ) // Iterator to the current sparse element.
+ , offset_( it.offset() ) // The offset of the according row/column of the sparse matrix
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline SubmatrixIterator& operator++() {
+ ++pos_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubmatrixIterator operator++( int ) {
+ const SubmatrixIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse submatrix element.
+ //
+ // \return Reference to the current sparse submatrix element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, offset_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse submatrix element.
+ //
+ // \return Pointer to the current sparse submatrix element.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, offset_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side submatrix iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline bool operator==( const SubmatrixIterator<MatrixType2,IteratorType2>& rhs ) const {
+ return base() == rhs.base();
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side submatrix iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline bool operator!=( const SubmatrixIterator<MatrixType2,IteratorType2>& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two submatrix iterators.
+ //
+ // \param rhs The right-hand side submatrix iterator.
+ // \return The number of elements between the two submatrix iterators.
+ */
+ inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
+ return pos_ - rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the submatrix iterator.
+ //
+ // \return The current position of the submatrix iterator.
+ */
+ inline IteratorType base() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ //**Offset function**************************************************************************
+ /*!\brief Access to the offset of the submatrix iterator.
+ //
+ // \return The offset of the submatrix iterator.
+ */
+ inline size_t offset() const noexcept {
+ return offset_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse element.
+ size_t offset_; //!< The offset of the according row/column of the sparse matrix.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef SubmatrixIterator< const MT, ConstIterator_<MT> > ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, SubmatrixIterator< MT, Iterator_<MT> > > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Submatrix& operator=( const Submatrix& rhs );
+
+ template< typename MT2, bool SO > inline Submatrix& operator= ( const Matrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline Submatrix& operator+=( const Matrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline Submatrix& operator-=( const Matrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t row() const noexcept;
+ inline size_t rows() const noexcept;
+ inline size_t column() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void reserve( size_t nonzeros );
+ void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t i );
+ inline Submatrix& transpose();
+ inline Submatrix& ctranspose();
+ template< typename Other > inline Submatrix& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+
+ template< typename MT2, bool SO > inline void assign ( const DenseMatrix<MT2,SO>& rhs );
+ template< typename MT2 > inline void assign ( const SparseMatrix<MT2,false>& rhs );
+ template< typename MT2 > inline void assign ( const SparseMatrix<MT2,true>& rhs );
+ template< typename MT2, bool SO > inline void addAssign( const DenseMatrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline void addAssign( const SparseMatrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline void subAssign( const DenseMatrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline void subAssign( const SparseMatrix<MT2,SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool hasOverlap() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The sparse matrix containing the submatrix.
+ const size_t row_; //!< The first row of the submatrix.
+ const size_t column_; //!< The first column of the submatrix.
+ const size_t m_; //!< The number of rows of the submatrix.
+ const size_t n_; //!< The number of columns of the submatrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend const Submatrix<MT2,AF1,SO2,DF2>
+ submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Submatrix.
+//
+// \param matrix The sparse matrix containing the submatrix.
+// \param rindex The index of the first row of the submatrix in the given sparse matrix.
+// \param cindex The index of the first column of the submatrix in the given sparse matrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// In case the submatrix is not properly specified (i.e. if the specified submatrix is not
+// contained in the given sparse matrix) a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline Submatrix<MT,AF,false,false>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
+ : matrix_( matrix ) // The sparse matrix containing the submatrix
+ , row_ ( rindex ) // The first row of the submatrix
+ , column_( cindex ) // The first column of the submatrix
+ , m_ ( m ) // The number of rows of the submatrix
+ , n_ ( n ) // The number of columns of the submatrix
+{
+ if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the sparse submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Reference
+ Submatrix<MT,AF,false,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the sparse submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstReference
+ Submatrix<MT,AF,false,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Reference
+ Submatrix<MT,AF,false,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstReference
+ Submatrix<MT,AF,false,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::begin( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid sparse submatrix row access index" );
+
+ if( column_ == 0UL )
+ return Iterator( matrix_.begin( i + row_ ), column_ );
+ else
+ return Iterator( matrix_.lowerBound( i + row_, column_ ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstIterator
+ Submatrix<MT,AF,false,false>::begin( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid sparse submatrix row access index" );
+
+ if( column_ == 0UL )
+ return ConstIterator( matrix_.cbegin( i + row_ ), column_ );
+ else
+ return ConstIterator( matrix_.lowerBound( i + row_, column_ ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator to the first non-zero element of row/column \a i.
+//
+// This function returns a row/column iterator to the first non-zero element of row/column \a i.
+// In case the storage order is set to \a rowMajor the function returns an iterator to the first
+// non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
+// returns an iterator to the first non-zero element of column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstIterator
+ Submatrix<MT,AF,false,false>::cbegin( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid sparse submatrix row access index" );
+
+ if( column_ == 0UL )
+ return ConstIterator( matrix_.cbegin( i + row_ ), column_ );
+ else
+ return ConstIterator( matrix_.lowerBound( i + row_, column_ ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::end( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid sparse submatrix row access index" );
+
+ if( matrix_.columns() == column_ + n_ )
+ return Iterator( matrix_.end( i + row_ ), column_ );
+ else
+ return Iterator( matrix_.lowerBound( i + row_, column_ + n_ ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstIterator
+ Submatrix<MT,AF,false,false>::end( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid sparse submatrix row access index" );
+
+ if( matrix_.columns() == column_ + n_ )
+ return ConstIterator( matrix_.cend( i + row_ ), column_ );
+ else
+ return ConstIterator( matrix_.lowerBound( i + row_, column_ + n_ ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
+//
+// \param i The row/column index.
+// \return Iterator just past the last non-zero element of row/column \a i.
+//
+// This function returns an row/column iterator just past the last non-zero element of row/column
+// \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
+// past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
+// the function returns an iterator just past the last non-zero element of column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstIterator
+ Submatrix<MT,AF,false,false>::cend( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid sparse submatrix row access index" );
+
+ if( matrix_.columns() == column_ + n_ )
+ return ConstIterator( matrix_.cend( i + row_ ), column_ );
+ else
+ return ConstIterator( matrix_.lowerBound( i + row_, column_ + n_ ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Submatrix.
+//
+// \param rhs Sparse submatrix to be copied.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Submatrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The sparse submatrix is initialized as a copy of the given sparse submatrix. In case the
+// current sizes of the two submatrices don't match, a \a std::invalid_argument exception is
+// thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline Submatrix<MT,AF,false,false>&
+ Submatrix<MT,AF,false,false>::operator=( const Submatrix& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
+ return *this;
+
+ if( rows() != rhs.rows() || columns() != rhs.columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ left.reset();
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be assigned.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The sparse submatrix is initialized as a copy of the given matrix. In case the current sizes
+// of the two matrices don't match, a \a std::invalid_argument exception is thrown. Also, if
+// the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,AF,false,false>&
+ Submatrix<MT,AF,false,false>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ typedef CompositeType_<MT2> Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<MT2> tmp( right );
+ left.reset();
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the sparse submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,AF,false,false>&
+ Submatrix<MT,AF,false,false>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the sparse submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,AF,false,false>&
+ Submatrix<MT,AF,false,false>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the sparse submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,AF,false,false>&
+ Submatrix<MT,AF,false,false>::operator*=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse submatrix
+// and a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse submatrix.
+//
+// Via this operator it is possible to scale the sparse submatrix. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for submatrices on lower
+// or upper unitriangular matrices. The attempt to scale such a submatrix results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse row must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Submatrix<MT,AF,false,false> >&
+ Submatrix<MT,AF,false,false>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value() *= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse submatrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the sparse submatrix.
+//
+// Via this operator it is possible to scale the sparse submatrix. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for submatrices on lower
+// or upper unitriangular matrices. The attempt to scale such a submatrix results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse submatrix must either support the multiplication assignment operator for the
+// given floating point data type or the division assignment operator for the given integral
+// data type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Submatrix<MT,AF,false,false> >&
+ Submatrix<MT,AF,false,false>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value() *= tmp;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value() /= rhs;
+ }
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first row of the submatrix in the underlying sparse matrix.
+//
+// \return The index of the first row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,false,false>::row() const noexcept
+{
+ return row_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of rows of the sparse submatrix.
+//
+// \return The number of rows of the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,false,false>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first column of the submatrix in the underlying sparse matrix.
+//
+// \return The index of the first column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,false,false>::column() const noexcept
+{
+ return column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of columns of the sparse submatrix.
+//
+// \return The number of columns of the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,false,false>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse submatrix.
+//
+// \return The capacity of the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,false,false>::capacity() const noexcept
+{
+ return nonZeros() + matrix_.capacity() - matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The current capacity of row/column \a i.
+//
+// This function returns the current capacity of the specified row/column. In case the
+// storage order is set to \a rowMajor the function returns the capacity of row \a i,
+// in case the storage flag is set to \a columnMajor the function returns the capacity
+// of column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,false,false>::capacity( size_t i ) const noexcept
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return nonZeros( i ) + matrix_.capacity( row_+i ) - matrix_.nonZeros( row_+i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the sparse submatrix
+//
+// \return The number of non-zero elements in the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,false,false>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<rows(); ++i )
+ nonzeros += nonZeros( i );
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified row/column.
+//
+// \param i The index of the row/column.
+// \return The number of non-zero elements of row/column \a i.
+//
+// This function returns the current number of non-zero elements in the specified row/column.
+// In case the storage order is set to \a rowMajor the function returns the number of non-zero
+// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
+// the number of non-zero elements in column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,false,false>::nonZeros( size_t i ) const
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return end(i) - begin(i);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,false,false>::reset()
+{
+ for( size_t i=row_; i<row_+m_; ++i )
+ {
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ matrix_.erase( i, matrix_.lowerBound( i, jbegin ), matrix_.lowerBound( i, jend ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified row/column to the default initial values.
+//
+// \param i The index of the row/column.
+// \return void
+//
+// This function resets the values in the specified row/column to their default value. In case
+// the storage order is set to \a rowMajor the function resets the values in row \a i, in case
+// the storage order is set to \a columnMajor the function resets the values in column \a i.
+// Note that the capacity of the row/column remains unchanged.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,false,false>::reset( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+
+ const size_t index( row_ + i );
+
+ const size_t jbegin( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( max( i+1UL, column_ ) )
+ :( max( i, column_ ) ) )
+ :( column_ ) );
+ const size_t jend ( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( min( i, column_+n_ ) )
+ :( min( i+1UL, column_+n_ ) ) )
+ :( column_+n_ ) );
+
+ matrix_.erase( index, matrix_.lowerBound( index, jbegin ), matrix_.lowerBound( index, jend ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse submatrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+//
+// This function sets the value of an element of the sparse submatrix. In case the sparse matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ return Iterator( matrix_.set( row_+i, column_+j, value ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse submatrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse submatrix access index.
+//
+// This function inserts a new element into the sparse submatrix. However, duplicate elements are
+// not allowed. In case the sparse submatrix already contains an element with row index \a i and
+// column index \a j, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ return Iterator( matrix_.insert( row_+i, column_+j, value ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse submatrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,false,false>::erase( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ matrix_.erase( row_ + i, column_ + j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse submatrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the sparse submatrix. In case the storage order is set
+// to \a rowMajor the function erases an element from row \a i, in case the storage flag is set
+// to \a columnMajor the function erases an element from column \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::erase( size_t i, Iterator pos )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return Iterator( matrix_.erase( row_+i, pos.base() ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse submatrix.
+//
+// \param i The row/column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of element from the sparse submatrix. In case the storage order
+// is set to \a rowMajor the function erases a range of elements element from row \a i, in case
+// the storage flag is set to \a columnMajor the function erases a range of elements from column
+// \a i.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::erase( size_t i, Iterator first, Iterator last )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ return Iterator( matrix_.erase( row_+i, first.base(), last.base() ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse submatrix.
+//
+// \param nonzeros The new minimum capacity of the sparse submatrix.
+// \return void
+//
+// This function increases the capacity of the sparse submatrix to at least \a nonzeros elements.
+// The current values of the submatrix elements and the individual capacities of the submatrix
+// rows are preserved.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,false,false>::reserve( size_t nonzeros )
+{
+ const size_t current( capacity() );
+
+ if( nonzeros > current ) {
+ matrix_.reserve( matrix_.capacity() + nonzeros - current );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific row/column of the sparse submatrix.
+//
+// \param i The row/column index of the new element \f$[0..M-1]\f$ or \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified row/column.
+// \return void
+//
+// This function increases the capacity of row/column \a i of the sparse submatrix to at least
+// \a nonzeros elements, but not beyond the current number of columns/rows, respectively. The
+// current values of the sparse submatrix and all other individual row/column capacities are
+// preserved. In case the storage order is set to \a rowMajor, the function reserves capacity
+// for row \a i and the index has to be in the range \f$[0..M-1]\f$. In case the storage order
+// is set to \a columnMajor, the function reserves capacity for column \a i and the index has
+// to be in the range \f$[0..N-1]\f$.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+void Submatrix<MT,AF,false,false>::reserve( size_t i, size_t nonzeros )
+{
+ const size_t current( capacity( i ) );
+ const size_t index ( row_ + i );
+
+ if( nonzeros > current ) {
+ matrix_.reserve( index, matrix_.capacity( index ) + nonzeros - current );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all rows/columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all row/column-specific reserve()
+// calls. The function removes all excessive capacity from all rows (in case of a rowMajor
+// matrix) or columns (in case of a columnMajor matrix). Note that this function does not
+// remove the overall capacity but only reduces the capacity per row/column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+void Submatrix<MT,AF,false,false>::trim()
+{
+ for( size_t i=0UL; i<rows(); ++i )
+ trim( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific row/column of the sparse matrix.
+//
+// \param i The index of the row/column to be trimmed (\f$[0..M-1]\f$ or \f$[0..N-1]\f$).
+// \return void
+//
+// This function can be used to reverse the effect of a row/column-specific reserve() call.
+// It removes all excessive capacity from the specified row (in case of a rowMajor matrix)
+// or column (in case of a columnMajor matrix). The excessive capacity is assigned to the
+// subsequent row/column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+void Submatrix<MT,AF,false,false>::trim( size_t i )
+{
+ BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
+ matrix_.trim( row_ + i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the sparse submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline Submatrix<MT,AF,false,false>& Submatrix<MT,AF,false,false>::transpose()
+{
+ using blaze::assign;
+
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( trans( *this ) );
+ reset();
+ assign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the sparse submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline Submatrix<MT,AF,false,false>& Submatrix<MT,AF,false,false>::ctranspose()
+{
+ using blaze::assign;
+
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( ctrans( *this ) );
+ reset();
+ assign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the submatrix scaling.
+// \return Reference to the sparse submatrix.
+//
+// This function scales all elements of the submatrix by the given scalar value \a scalar. Note
+// that the function cannot be used to scale a submatrix on a lower or upper unitriangular matrix.
+// The attempt to scale such a submatrix results in a compile time error!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the scalar value
+inline Submatrix<MT,AF,false,false>& Submatrix<MT,AF,false,false>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value() *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
+//
+// \return \a true in case an overlap exists, \a false if not.
+//
+// This function checks if in the context of a symmetric matrix the submatrix has an overlap with
+// its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
+// \a false.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline bool Submatrix<MT,AF,false,false>::hasOverlap() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
+
+ if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
+ return false;
+ else return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific submatrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// submatrix. It specifically searches for the element with row index \a i and column index
+// \a j. In case the element is found, the function returns an row/column iterator to the
+// element. Otherwise an iterator just past the last non-zero element of row \a i or column
+// \a j (the end() iterator) is returned. Note that the returned sparse submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or
+// the insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::find( size_t i, size_t j )
+{
+ const Iterator_<MT> pos( matrix_.find( row_ + i, column_ + j ) );
+
+ if( pos != matrix_.end( row_ + i ) )
+ return Iterator( pos, column_ );
+ else
+ return end( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific submatrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// submatrix. It specifically searches for the element with row index \a i and column index
+// \a j. In case the element is found, the function returns an row/column iterator to the
+// element. Otherwise an iterator just past the last non-zero element of row \a i or column
+// \a j (the end() iterator) is returned. Note that the returned sparse submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or
+// the insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstIterator
+ Submatrix<MT,AF,false,false>::find( size_t i, size_t j ) const
+{
+ const ConstIterator_<MT> pos( matrix_.find( row_ + i, column_ + j ) );
+
+ if( pos != matrix_.end( row_ + i ) )
+ return ConstIterator( pos, column_ );
+ else
+ return end( i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major submatrix, this function returns a row iterator to the first element
+// with an index not less then the given column index. In case of a column-major submatrix, the
+// function returns a column iterator to the first element with an index not less then the given
+// row index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::lowerBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.lowerBound( row_ + i, column_ + j ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major submatrix, this function returns a row iterator to the first element
+// with an index not less then the given column index. In case of a column-major submatrix, the
+// function returns a column iterator to the first element with an index not less then the given
+// row index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstIterator
+ Submatrix<MT,AF,false,false>::lowerBound( size_t i, size_t j ) const
+{
+ return ConstIterator( matrix_.lowerBound( row_ + i, column_ + j ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major submatrix, this function returns a row iterator to the first element
+// with an index greater then the given column index. In case of a column-major submatrix, the
+// function returns a column iterator to the first element with an index greater then the given
+// row index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::Iterator
+ Submatrix<MT,AF,false,false>::upperBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.upperBound( row_ + i, column_ + j ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major submatrix, this function returns a row iterator to the first element
+// with an index greater then the given column index. In case of a column-major submatrix, the
+// function returns a column iterator to the first element with an index greater then the given
+// row index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,false,false>::ConstIterator
+ Submatrix<MT,AF,false,false>::upperBound( size_t i, size_t j ) const
+{
+ return ConstIterator( matrix_.upperBound( row_ + i, column_ + j ), column_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the specified row/column of the sparse submatrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse submatrix with elements. It appends
+// a new element to the end of the specified row/column without any additional memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse submatrix
+// - the current number of non-zero elements in the submatrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a sparse submatrix:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::CompressedMatrix<double,rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType> SubmatrixType;
+
+ MatrixType A( 42, 54 );
+ SubmatrixType B = submatrix( A, 10, 10, 4, 3 );
+
+ B.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ B.append( 0, 1, 1.0 ); // Appending the value 1 in row 0 with column index 1
+ B.finalize( 0 ); // Finalizing row 0
+ B.append( 1, 1, 2.0 ); // Appending the value 2 in row 1 with column index 1
+ B.finalize( 1 ); // Finalizing row 1
+ B.finalize( 2 ); // Finalizing the empty row 2 to prepare row 3
+ B.append( 3, 0, 3.0 ); // Appending the value 3 in row 3 with column index 0
+ B.finalize( 3 ); // Finalizing row 3
+ \endcode
+
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,false,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( column_ + n_ == matrix_.columns() ) {
+ matrix_.append( row_ + i, column_ + j, value, check );
+ }
+ else if( !check || !isDefault( value ) ) {
+ matrix_.insert( row_ + i, column_ + j, value );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a row/column.
+//
+// \param i The index of the row/column to be finalized \f$[0..M-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a submatrix with elements.
+// After completion of row/column \a i via the append() function, this function can be called to
+// finalize row/column \a i and prepare the next row/column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,false,false>::finalize( size_t i )
+{
+ matrix_.trim( row_ + i );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,AF,false,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,AF,false,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can be used in SMP assignments.
+//
+// \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the submatrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline bool Submatrix<MT,AF,false,false>::canSMPAssign() const noexcept
+{
+ return false;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void Submatrix<MT,AF,false,false>::assign( const DenseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ reserve( 0UL, rows() * columns() );
+
+ for( size_t i=0UL; i<rows(); ++i ) {
+ for( size_t j=0UL; j<columns(); ++j ) {
+ if( IsSymmetric<MT>::value || IsHermitian<MT>::value )
+ set( i, j, (~rhs)(i,j) );
+ else
+ append( i, j, (~rhs)(i,j), true );
+ }
+ finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,AF,false,false>::assign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ reserve( 0UL, (~rhs).nonZeros() );
+
+ for( size_t i=0UL; i<(~rhs).rows(); ++i ) {
+ for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element ) {
+ if( IsSymmetric<MT>::value || IsHermitian<MT>::value )
+ set( i, element->index(), element->value() );
+ else
+ append( i, element->index(), element->value(), true );
+ }
+ finalize( i );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,AF,false,false>::assign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsIterator;
+
+ // Counting the number of elements per row
+ std::vector<size_t> rowLengths( m_, 0UL );
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ ++rowLengths[element->index()];
+ }
+
+ // Resizing the sparse matrix
+ for( size_t i=0UL; i<m_; ++i ) {
+ reserve( i, rowLengths[i] );
+ }
+
+ // Appending the elements to the rows of the sparse submatrix
+ for( size_t j=0UL; j<n_; ++j ) {
+ for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
+ if( IsSymmetric<MT>::value || IsHermitian<MT>::value )
+ set( element->index(), j, element->value() );
+ else
+ append( element->index(), j, element->value(), true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void Submatrix<MT,AF,false,false>::addAssign( const DenseMatrix<MT2,SO>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline void Submatrix<MT,AF,false,false>::addAssign( const SparseMatrix<MT2,SO>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void Submatrix<MT,AF,false,false>::subAssign( const DenseMatrix<MT2,SO>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand sparse matrix
+inline void Submatrix<MT,AF,false,false>::subAssign( const SparseMatrix<MT2,SO>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR SPARSE MATRICES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Submatrix for column-major sparse submatrices.
+// \ingroup views
+//
+// This specialization of Submatrix adapts the class template to the requirements of column-major
+// sparse submatrices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+class Submatrix<MT,AF,true,false>
+ : public SparseMatrix< Submatrix<MT,AF,true,false>, true >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the sparse matrix expression.
+ typedef If_< IsExpression<MT>, MT, MT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Submatrix<MT,AF,true,false> This; //!< Type of this Submatrix instance.
+ typedef SparseMatrix<This,true> BaseType; //!< Base type of this Submatrix instance.
+ typedef SubmatrixTrait_<MT> ResultType; //!< Result type for expression template evaluations.
+ typedef OppositeType_<ResultType> OppositeType; //!< Result type with opposite storage order for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<MT> ElementType; //!< Type of the submatrix elements.
+ typedef ReturnType_<MT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Submatrix& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant submatrix value.
+ typedef ConstReference_<MT> ConstReference;
+
+ //! Reference to a non-constant submatrix value.
+ typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
+ //**********************************************************************************************
+
+ //**SubmatrixElement class definition***********************************************************
+ /*!\brief Access proxy for a specific element of the sparse submatrix.
+ */
+ template< typename MatrixType // Type of the sparse matrix
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class SubmatrixElement : private SparseElement
+ {
+ private:
+ //*******************************************************************************************
+ //! Compilation switch for the return type of the value member function.
+ /*! The \a returnConst compile time constant expression represents a compilation switch for
+ the return type of the value member function. In case the given matrix type \a MatrixType
+ is const qualified, \a returnConst will be set to 1 and the value member function will
+ return a reference to const. Otherwise \a returnConst will be set to 0 and the value
+ member function will offer write access to the sparse matrix elements. */
+ enum : bool { returnConst = IsConst<MatrixType>::value };
+ //*******************************************************************************************
+
+ //**Type definitions*************************************************************************
+ //! Type of the underlying sparse elements.
+ typedef typename std::iterator_traits<IteratorType>::value_type SET;
+
+ typedef Reference_<SET> RT; //!< Reference type of the underlying sparse element.
+ typedef ConstReference_<SET> CRT; //!< Reference-to-const type of the underlying sparse element.
+ //*******************************************************************************************
+
+ public:
+ //**Type definitions*************************************************************************
+ typedef ValueType_<SET> ValueType; //!< The value type of the row element.
+ typedef size_t IndexType; //!< The index type of the row element.
+ typedef IfTrue_<returnConst,CRT,RT> Reference; //!< Reference return type
+ typedef CRT ConstReference; //!< Reference-to-const return type.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SubmatrixElement class.
+ //
+ // \param pos Iterator to the current position within the sparse submatrix.
+ // \param offset The offset within the according row/column of the sparse matrix.
+ */
+ inline SubmatrixElement( IteratorType pos, size_t offset )
+ : pos_ ( pos ) // Iterator to the current position within the sparse submatrix
+ , offset_( offset ) // Row offset within the according sparse matrix
+ {}
+ //*******************************************************************************************
+
+ //**Assignment operator**********************************************************************
+ /*!\brief Assignment to the accessed sparse submatrix element.
+ //
+ // \param value The new value of the sparse submatrix element.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator=( const T& v ) {
+ *pos_ = v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment to the accessed sparse submatrix element.
+ //
+ // \param value The right-hand side value for the addition.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator+=( const T& v ) {
+ *pos_ += v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment to the accessed sparse submatrix element.
+ //
+ // \param value The right-hand side value for the subtraction.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator-=( const T& v ) {
+ *pos_ -= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Multiplication assignment operator*******************************************************
+ /*!\brief Multiplication assignment to the accessed sparse submatrix element.
+ //
+ // \param value The right-hand side value for the multiplication.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator*=( const T& v ) {
+ *pos_ *= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Division assignment operator*************************************************************
+ /*!\brief Division assignment to the accessed sparse submatrix element.
+ //
+ // \param value The right-hand side value for the division.
+ // \return Reference to the sparse submatrix element.
+ */
+ template< typename T > inline SubmatrixElement& operator/=( const T& v ) {
+ *pos_ /= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse submatrix element at the current iterator position.
+ //
+ // \return Reference to the sparse submatrix element at the current iterator position.
+ */
+ inline const SubmatrixElement* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse submatrix element.
+ //
+ // \return The current value of the sparse submatrix element.
+ */
+ inline Reference value() const {
+ return pos_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline IndexType index() const {
+ return pos_->index() - offset_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current position within the sparse submatrix.
+ size_t offset_; //!< Offset within the according row/column of the sparse matrix.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**SubmatrixIterator class definition**********************************************************
+ /*!\brief Iterator over the elements of the sparse submatrix.
+ */
+ template< typename MatrixType // Type of the sparse matrix
+ , typename IteratorType > // Type of the sparse matrix iterator
+ class SubmatrixIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef SubmatrixElement<MatrixType,IteratorType> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Default constructor**********************************************************************
+ /*!\brief Default constructor for the SubmatrixIterator class.
+ */
+ inline SubmatrixIterator()
+ : pos_ () // Iterator to the current sparse element
+ , offset_() // The offset of the according row/column of the sparse matrix
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SubmatrixIterator class.
+ //
+ // \param iterator Iterator to the current sparse element.
+ // \param index The starting index within the according row/column of the sparse matrix.
+ */
+ inline SubmatrixIterator( IteratorType iterator, size_t index )
+ : pos_ ( iterator ) // Iterator to the current sparse element
+ , offset_( index ) // The offset of the according row/column of the sparse matrix
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different SubmatrixIterator instances.
+ //
+ // \param it The submatrix iterator to be copied.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline SubmatrixIterator( const SubmatrixIterator<MatrixType2,IteratorType2>& it )
+ : pos_ ( it.base() ) // Iterator to the current sparse element.
+ , offset_( it.offset() ) // The offset of the according row/column of the sparse matrix
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline SubmatrixIterator& operator++() {
+ ++pos_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubmatrixIterator operator++( int ) {
+ const SubmatrixIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse submatrix element.
+ //
+ // \return Reference to the current sparse submatrix element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, offset_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse submatrix element.
+ //
+ // \return Pointer to the current sparse submatrix element.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, offset_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side submatrix iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline bool operator==( const SubmatrixIterator<MatrixType2,IteratorType2>& rhs ) const {
+ return base() == rhs.base();
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two SubmatrixIterator objects.
+ //
+ // \param rhs The right-hand side submatrix iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ template< typename MatrixType2, typename IteratorType2 >
+ inline bool operator!=( const SubmatrixIterator<MatrixType2,IteratorType2>& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two submatrix iterators.
+ //
+ // \param rhs The right-hand side submatrix iterator.
+ // \return The number of elements between the two submatrix iterators.
+ */
+ inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
+ return pos_ - rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the submatrix iterator.
+ //
+ // \return The current position of the submatrix iterator.
+ */
+ inline IteratorType base() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ //**Offset function**************************************************************************
+ /*!\brief Access to the offset of the submatrix iterator.
+ //
+ // \return The offset of the submatrix iterator.
+ */
+ inline size_t offset() const noexcept {
+ return offset_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse element.
+ size_t offset_; //!< The offset of the according row/column of the sparse matrix.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef SubmatrixIterator< const MT, ConstIterator_<MT> > ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<MT>, ConstIterator, SubmatrixIterator< MT, Iterator_<MT> > > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = MT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator()( size_t i, size_t j );
+ inline ConstReference operator()( size_t i, size_t j ) const;
+ inline Reference at( size_t i, size_t j );
+ inline ConstReference at( size_t i, size_t j ) const;
+ inline Iterator begin ( size_t i );
+ inline ConstIterator begin ( size_t i ) const;
+ inline ConstIterator cbegin( size_t i ) const;
+ inline Iterator end ( size_t i );
+ inline ConstIterator end ( size_t i ) const;
+ inline ConstIterator cend ( size_t i ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Submatrix& operator=( const Submatrix& rhs );
+
+ template< typename MT2, bool SO > inline Submatrix& operator= ( const Matrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline Submatrix& operator+=( const Matrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline Submatrix& operator-=( const Matrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t row() const noexcept;
+ inline size_t rows() const noexcept;
+ inline size_t column() const noexcept;
+ inline size_t columns() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t capacity( size_t i ) const noexcept;
+ inline size_t nonZeros() const;
+ inline size_t nonZeros( size_t i ) const;
+ inline void reset();
+ inline void reset( size_t i );
+ inline Iterator set( size_t i, size_t j, const ElementType& value );
+ inline Iterator insert( size_t i, size_t j, const ElementType& value );
+ inline void erase( size_t i, size_t j );
+ inline Iterator erase( size_t i, Iterator pos );
+ inline Iterator erase( size_t i, Iterator first, Iterator last );
+ inline void reserve( size_t nonzeros );
+ void reserve( size_t i, size_t nonzeros );
+ inline void trim();
+ inline void trim( size_t j );
+ inline Submatrix& transpose();
+ inline Submatrix& ctranspose();
+ template< typename Other > inline Submatrix& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t i, size_t j );
+ inline ConstIterator find ( size_t i, size_t j ) const;
+ inline Iterator lowerBound( size_t i, size_t j );
+ inline ConstIterator lowerBound( size_t i, size_t j ) const;
+ inline Iterator upperBound( size_t i, size_t j );
+ inline ConstIterator upperBound( size_t i, size_t j ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append ( size_t i, size_t j, const ElementType& value, bool check=false );
+ inline void finalize( size_t i );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+
+ template< typename MT2, bool SO > inline void assign ( const DenseMatrix<MT2,SO>& rhs );
+ template< typename MT2 > inline void assign ( const SparseMatrix<MT2,true>& rhs );
+ template< typename MT2 > inline void assign ( const SparseMatrix<MT2,false>& rhs );
+ template< typename MT2, bool SO > inline void addAssign( const DenseMatrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline void addAssign( const SparseMatrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline void subAssign( const DenseMatrix<MT2,SO>& rhs );
+ template< typename MT2, bool SO > inline void subAssign( const SparseMatrix<MT2,SO>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool hasOverlap() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand matrix_; //!< The sparse matrix containing the submatrix.
+ const size_t row_; //!< The first row of the submatrix.
+ const size_t column_; //!< The first column of the submatrix.
+ const size_t m_; //!< The number of rows of the submatrix.
+ const size_t n_; //!< The number of columns of the submatrix.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend const Submatrix<MT2,AF1,SO2,DF2>
+ submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
+ friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
+ friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
+ size_t row, size_t column );
+
+ template< typename MT2, bool AF2, bool SO2, bool DF2 >
+ friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Submatrix.
+//
+// \param matrix The sparse matrix containing the submatrix.
+// \param rindex The index of the first row of the submatrix in the given sparse matrix.
+// \param cindex The index of the first column of the submatrix in the given sparse matrix.
+// \param m The number of rows of the submatrix.
+// \param n The number of columns of the submatrix.
+// \exception std::invalid_argument Invalid submatrix specification.
+//
+// In case the submatrix is not properly specified (i.e. if the specified submatrix is not
+// contained in the given sparse matrix) a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline Submatrix<MT,AF,true,false>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
+ : matrix_( matrix ) // The sparse matrix containing the submatrix
+ , row_ ( rindex ) // The first row of the submatrix
+ , column_( cindex ) // The first column of the submatrix
+ , m_ ( m ) // The number of rows of the submatrix
+ , n_ ( n ) // The number of columns of the submatrix
+{
+ if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the sparse submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Reference
+ Submatrix<MT,AF,true,false>::operator()( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return matrix_(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief 2D-access to the sparse submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access indices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstReference
+ Submatrix<MT,AF,true,false>::operator()( size_t i, size_t j ) const
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Reference
+ Submatrix<MT,AF,true,false>::at( size_t i, size_t j )
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the submatrix elements.
+//
+// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
+// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid matrix access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access indices.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstReference
+ Submatrix<MT,AF,true,false>::at( size_t i, size_t j ) const
+{
+ if( i >= rows() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
+ }
+ if( j >= columns() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
+ }
+ return (*this)(i,j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::begin( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid sparse submatrix column access index" );
+
+ if( row_ == 0UL )
+ return Iterator( matrix_.begin( j + column_ ), row_ );
+ else
+ return Iterator( matrix_.lowerBound( row_, j + column_ ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstIterator
+ Submatrix<MT,AF,true,false>::begin( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid sparse submatrix column access index" );
+
+ if( row_ == 0UL )
+ return ConstIterator( matrix_.cbegin( j + column_ ), row_ );
+ else
+ return ConstIterator( matrix_.lowerBound( row_, j + column_ ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator to the first non-zero element of column \a j.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstIterator
+ Submatrix<MT,AF,true,false>::cbegin( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid sparse submatrix column access index" );
+
+ if( row_ == 0UL )
+ return ConstIterator( matrix_.cbegin( j + column_ ), row_ );
+ else
+ return ConstIterator( matrix_.lowerBound( row_, j + column_ ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::end( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid sparse submatrix column access index" );
+
+ if( matrix_.rows() == row_ + m_ )
+ return Iterator( matrix_.end( j + column_ ), row_ );
+ else
+ return Iterator( matrix_.lowerBound( row_ + m_, j + column_ ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstIterator
+ Submatrix<MT,AF,true,false>::end( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid sparse submatrix column access index" );
+
+ if( matrix_.rows() == row_ + m_ )
+ return ConstIterator( matrix_.cend( j + column_ ), row_ );
+ else
+ return ConstIterator( matrix_.lowerBound( row_ + m_, j + column_ ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last non-zero element of column \a j.
+//
+// \param j The column index.
+// \return Iterator just past the last non-zero element of column \a j.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstIterator
+ Submatrix<MT,AF,true,false>::cend( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid sparse submatrix column access index" );
+
+ if( matrix_.rows() == row_ + m_ )
+ return ConstIterator( matrix_.cend( j + column_ ), row_ );
+ else
+ return ConstIterator( matrix_.lowerBound( row_ + m_, j + column_ ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Submatrix.
+//
+// \param rhs Sparse submatrix to be copied.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Submatrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The sparse submatrix is initialized as a copy of the given sparse submatrix. In case the
+// current sizes of the two submatrices don't match, a \a std::invalid_argument exception is
+// thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline Submatrix<MT,AF,true,false>&
+ Submatrix<MT,AF,true,false>::operator=( const Submatrix& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
+ return *this;
+
+ if( rows() != rhs.rows() || columns() != rhs.columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
+ }
+
+ if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &matrix_ ) ) {
+ const ResultType tmp( rhs );
+ left.reset();
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different matrices.
+//
+// \param rhs Matrix to be assigned.
+// \return Reference to the assigned submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// The sparse submatrix is initialized as a copy of the given matrix. In case the current sizes
+// of the two matrices don't match, a \a std::invalid_argument exception is thrown. Also, if
+// the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
+// and the assignment would violate its lower, upper, or symmetry property, respectively, a
+// \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,AF,true,false>&
+ Submatrix<MT,AF,true,false>::operator=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ typedef CompositeType_<MT2> Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( matrix_, right, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
+ const ResultType_<MT2> tmp( right );
+ left.reset();
+ assign( left, tmp );
+ }
+ else {
+ left.reset();
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
+//
+// \param rhs The right-hand side matrix to be added to the submatrix.
+// \return Reference to the sparse submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,AF,true,false>&
+ Submatrix<MT,AF,true,false>::operator+=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
+//
+// \param rhs The right-hand side matrix to be subtracted from the submatrix.
+// \return Reference to the sparse submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,AF,true,false>&
+ Submatrix<MT,AF,true,false>::operator-=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a matrix (\f$ A*=B \f$).
+//
+// \param rhs The right-hand side matrix for the multiplication.
+// \return Reference to the sparse submatrix.
+// \exception std::invalid_argument Matrix sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted matrix.
+//
+// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
+// is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
+// symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
+// respectively, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side matrix
+ , bool SO > // Storage order of the right-hand side matrix
+inline Submatrix<MT,AF,true,false>&
+ Submatrix<MT,AF,true,false>::operator*=( const Matrix<MT2,SO>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<MT2> );
+
+ typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_MATRIX_TYPE ( MultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( columns() != (~rhs).rows() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse submatrix
+// and a scalar value (\f$ A*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the sparse submatrix.
+//
+// Via this operator it is possible to scale the sparse submatrix. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for submatrices on lower
+// or upper unitriangular matrices. The attempt to scale such a submatrix results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse row must support the multiplication assignment operator for the given scalar
+// built-in data type.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Submatrix<MT,AF,true,false> >&
+ Submatrix<MT,AF,true,false>::operator*=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( size_t i=0UL; i<columns(); ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value() *= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse submatrix by a scalar value
+// (\f$ A/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the sparse submatrix.
+//
+// Via this operator it is possible to scale the sparse submatrix. Note however that the function
+// is subject to three restrictions. First, this operator cannot be used for submatrices on lower
+// or upper unitriangular matrices. The attempt to scale such a submatrix results in a compilation
+// error! Second, this operator can only be used for numeric data types. And third, the elements
+// of the sparse submatrix must either support the multiplication assignment operator for the
+// given floating point data type or the division assignment operator for the given integral
+// data type.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Submatrix<MT,AF,true,false> >&
+ Submatrix<MT,AF,true,false>::operator/=( Other rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( size_t i=0UL; i<columns(); ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value() *= tmp;
+ }
+ }
+ else {
+ for( size_t i=0UL; i<columns(); ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value() /= rhs;
+ }
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first row of the submatrix in the underlying sparse matrix.
+//
+// \return The index of the first row.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,true,false>::row() const noexcept
+{
+ return row_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of rows of the sparse submatrix.
+//
+// \return The number of rows of the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,true,false>::rows() const noexcept
+{
+ return m_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the index of the first column of the submatrix in the underlying sparse matrix.
+//
+// \return The index of the first column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,true,false>::column() const noexcept
+{
+ return column_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of columns of the sparse submatrix.
+//
+// \return The number of columns of the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,true,false>::columns() const noexcept
+{
+ return n_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse submatrix.
+//
+// \return The capacity of the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,true,false>::capacity() const noexcept
+{
+ return nonZeros() + matrix_.capacity() - matrix_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current capacity of the specified column.
+//
+// \param j The index of the column.
+// \return The current capacity of column \a j.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,true,false>::capacity( size_t j ) const noexcept
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return nonZeros( j ) + matrix_.capacity( column_+j ) - matrix_.nonZeros( column_+j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the sparse submatrix
+//
+// \return The number of non-zero elements in the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,true,false>::nonZeros() const
+{
+ size_t nonzeros( 0UL );
+
+ for( size_t i=0UL; i<columns(); ++i )
+ nonzeros += nonZeros( i );
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the specified column.
+//
+// \param j The index of the column.
+// \return The number of non-zero elements of column \a j.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline size_t Submatrix<MT,AF,true,false>::nonZeros( size_t j ) const
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return end(j) - begin(j);
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,true,false>::reset()
+{
+ for( size_t j=column_; j<column_+n_; ++j )
+ {
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ matrix_.erase( j, matrix_.lowerBound( ibegin, j ), matrix_.lowerBound( iend, j ) );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset the specified column to the default initial values.
+//
+// \param j The index of the column.
+// \return void
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,true,false>::reset( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ const size_t index( column_ + j );
+
+ const size_t ibegin( ( IsLower<MT>::value )
+ ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
+ ?( max( j+1UL, row_ ) )
+ :( max( j, row_ ) ) )
+ :( row_ ) );
+ const size_t iend ( ( IsUpper<MT>::value )
+ ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
+ ?( min( j, row_+m_ ) )
+ :( min( j+1UL, row_+m_ ) ) )
+ :( row_+m_ ) );
+
+ matrix_.erase( index, matrix_.lowerBound( ibegin, index ), matrix_.lowerBound( iend, index ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse submatrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Iterator to the set element.
+//
+// This function sets the value of an element of the sparse submatrix. In case the sparse matrix
+// already contains an element with row index \a i and column index \a j its value is modified,
+// else a new element with the given \a value is inserted.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::set( size_t i, size_t j, const ElementType& value )
+{
+ return Iterator( matrix_.set( row_+i, column_+j, value ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse submatrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Iterator to the newly inserted element.
+// \exception std::invalid_argument Invalid sparse submatrix access index.
+//
+// This function inserts a new element into the sparse submatrix. However, duplicate elements are
+// not allowed. In case the sparse submatrix already contains an element with row index \a i and
+// column index \a j, a \a std::invalid_argument exception is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::insert( size_t i, size_t j, const ElementType& value )
+{
+ return Iterator( matrix_.insert( row_+i, column_+j, value ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse submatrix.
+//
+// \param i The row index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,true,false>::erase( size_t i, size_t j )
+{
+ BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+
+ matrix_.erase( row_ + i, column_ + j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse submatrix.
+//
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param pos Iterator to the element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from column \a j of the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::erase( size_t j, Iterator pos )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return Iterator( matrix_.erase( column_+j, pos.base() ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse submatrix.
+//
+// \param j The column index of the element to be erased. The index has to be in the range \f$[0..M-1]\f$.
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of element from column \a j of the sparse submatrix.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::erase( size_t j, Iterator first, Iterator last )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ return Iterator( matrix_.erase( column_+j, first.base(), last.base() ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse submatrix.
+//
+// \param nonzeros The new minimum capacity of the sparse submatrix.
+// \return void
+//
+// This function increases the capacity of the sparse submatrix to at least \a nonzeros elements.
+// The current values of the submatrix elements and the individual capacities of the submatrix
+// rows are preserved.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,true,false>::reserve( size_t nonzeros )
+{
+ const size_t current( capacity() );
+
+ if( nonzeros > current ) {
+ matrix_.reserve( matrix_.capacity() + nonzeros - current );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of a specific column of the sparse submatrix.
+//
+// \param j The column index of the new element \f$[0..M-1]\f$ or \f$[0..N-1]\f$.
+// \param nonzeros The new minimum capacity of the specified column.
+// \return void
+//
+// This function increases the capacity of column \a i of the sparse submatrix to at least
+// \a nonzeros elements, but not beyond the current number of rows. The current values of
+// the sparse submatrix and all other individual row/column capacities are preserved.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+void Submatrix<MT,AF,true,false>::reserve( size_t j, size_t nonzeros )
+{
+ const size_t current( capacity( j ) );
+ const size_t index ( column_ + j );
+
+ if( nonzeros > current ) {
+ matrix_.reserve( index, matrix_.capacity( index ) + nonzeros - current );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity from all columns.
+//
+// \return void
+//
+// The trim() function can be used to reverse the effect of all column-specific reserve() calls
+// It removes all excessive capacity from all columns. Note that this function does not remove
+// the overall capacity but only reduces the capacity per column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+void Submatrix<MT,AF,true,false>::trim()
+{
+ for( size_t j=0UL; j<columns(); ++j )
+ trim( j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Removing all excessive capacity of a specific column of the sparse matrix.
+//
+// \param j The index of the column to be trimmed (\f$[0..N-1]\f$).
+// \return void
+//
+// This function can be used to reverse the effect of a column-specific reserve() call. It
+// removes all excessive capacity from the specified column. The excessive capacity is assigned
+// to the subsequent column.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+void Submatrix<MT,AF,true,false>::trim( size_t j )
+{
+ BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
+ matrix_.trim( column_ + j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the sparse submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline Submatrix<MT,AF,true,false>& Submatrix<MT,AF,true,false>::transpose()
+{
+ using blaze::assign;
+
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( trans( *this ) );
+ reset();
+ assign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief In-place conjugate transpose of the submatrix.
+//
+// \return Reference to the transposed submatrix.
+// \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
+// \exception std::logic_error Invalid transpose operation.
+//
+// This function transposes the sparse submatrix in-place. Note that this function can only be used
+// for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
+// the function fails if ...
+//
+// - ... the submatrix contains elements from the upper part of the underlying lower matrix;
+// - ... the submatrix contains elements from the lower part of the underlying upper matrix;
+// - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
+//
+// In all cases, a \a std::logic_error is thrown.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline Submatrix<MT,AF,true,false>& Submatrix<MT,AF,true,false>::ctranspose()
+{
+ using blaze::assign;
+
+ if( m_ != n_ ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
+ }
+
+ if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
+ BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ const ResultType tmp( ctrans(*this) );
+ reset();
+ assign( left, tmp );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
+//
+// \param scalar The scalar value for the submatrix scaling.
+// \return Reference to the sparse submatrix.
+//
+// This function scales all elements of the submatrix by the given scalar value \a scalar. Note
+// that the function cannot be used to scale a submatrix on a lower or upper unitriangular matrix.
+// The attempt to scale such a submatrix results in a compile time error!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the scalar value
+inline Submatrix<MT,AF,true,false>& Submatrix<MT,AF,true,false>::scale( const Other& scalar )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
+
+ for( size_t i=0UL; i<columns(); ++i ) {
+ const Iterator last( end(i) );
+ for( Iterator element=begin(i); element!=last; ++element )
+ element->value() *= scalar;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
+//
+// \return \a true in case an overlap exists, \a false if not.
+//
+// This function checks if in the context of a symmetric matrix the submatrix has an overlap with
+// its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
+// \a false.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline bool Submatrix<MT,AF,true,false>::hasOverlap() const noexcept
+{
+ BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
+
+ if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
+ return false;
+ else return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific submatrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// submatrix. It specifically searches for the element with row index \a i and column index
+// \a j. In case the element is found, the function returns an row/column iterator to the
+// element. Otherwise an iterator just past the last non-zero element of row \a i or column
+// \a j (the end() iterator) is returned. Note that the returned sparse submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or
+// the insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::find( size_t i, size_t j )
+{
+ const Iterator_<MT> pos( matrix_.find( row_ + i, column_ + j ) );
+
+ if( pos != matrix_.end( column_ + j ) )
+ return Iterator( pos, row_ );
+ else
+ return end( j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific submatrix element.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// submatrix. It specifically searches for the element with row index \a i and column index
+// \a j. In case the element is found, the function returns an row/column iterator to the
+// element. Otherwise an iterator just past the last non-zero element of row \a i or column
+// \a j (the end() iterator) is returned. Note that the returned sparse submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or
+// the insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstIterator
+ Submatrix<MT,AF,true,false>::find( size_t i, size_t j ) const
+{
+ const ConstIterator_<MT> pos( matrix_.find( row_ + i, column_ + j ) );
+
+ if( pos != matrix_.end( column_ + j ) )
+ return ConstIterator( pos, row_ );
+ else
+ return end( j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major submatrix, this function returns a row iterator to the first element
+// with an index not less then the given column index. In case of a column-major submatrix, the
+// function returns a column iterator to the first element with an index not less then the given
+// row index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::lowerBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.lowerBound( row_ + i, column_ + j ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// In case of a row-major submatrix, this function returns a row iterator to the first element
+// with an index not less then the given column index. In case of a column-major submatrix, the
+// function returns a column iterator to the first element with an index not less then the given
+// row index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstIterator
+ Submatrix<MT,AF,true,false>::lowerBound( size_t i, size_t j ) const
+{
+ return ConstIterator( matrix_.lowerBound( row_ + i, column_ + j ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major submatrix, this function returns a row iterator to the first element
+// with an index greater then the given column index. In case of a column-major submatrix, the
+// function returns a column iterator to the first element with an index greater then the given
+// row index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::Iterator
+ Submatrix<MT,AF,true,false>::upperBound( size_t i, size_t j )
+{
+ return Iterator( matrix_.upperBound( row_ + i, column_ + j ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param i The row index of the search element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// In case of a row-major submatrix, this function returns a row iterator to the first element
+// with an index greater then the given column index. In case of a column-major submatrix, the
+// function returns a column iterator to the first element with an index greater then the given
+// row index. In combination with the upperBound() function this function can be used to create
+// a pair of iterators specifying a range of indices. Note that the returned submatrix iterator
+// is subject to invalidation due to inserting operations via the function call operator or the
+// insert() function!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline typename Submatrix<MT,AF,true,false>::ConstIterator
+ Submatrix<MT,AF,true,false>::upperBound( size_t i, size_t j ) const
+{
+ return ConstIterator( matrix_.upperBound( row_ + i, column_ + j ), row_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the specified row/column of the sparse submatrix.
+//
+// \param i The row index of the new element. The index has to be in the range \f$[0..M-1]\f$.
+// \param j The column index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse submatrix with elements. It appends
+// a new element to the end of the specified row/column without any additional memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the specified row/column of the sparse submatrix
+// - the current number of non-zero elements in the submatrix must be smaller than the capacity
+// of the matrix
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// In combination with the reserve() and the finalize() function, append() provides the most
+// efficient way to add new elements to a sparse submatrix:
+
+ \code
+ using blaze::rowMajor;
+
+ typedef blaze::CompressedMatrix<double,rowMajor> MatrixType;
+ typedef blaze::Submatrix<MatrixType> SubmatrixType;
+
+ MatrixType A( 42, 54 );
+ SubmatrixType B = submatrix( A, 10, 10, 4, 3 );
+
+ B.reserve( 3 ); // Reserving enough capacity for 3 non-zero elements
+ B.append( 0, 1, 1.0 ); // Appending the value 1 in row 0 with column index 1
+ B.finalize( 0 ); // Finalizing row 0
+ B.append( 1, 1, 2.0 ); // Appending the value 2 in row 1 with column index 1
+ B.finalize( 1 ); // Finalizing row 1
+ B.finalize( 2 ); // Finalizing the empty row 2 to prepare row 3
+ B.append( 3, 0, 3.0 ); // Appending the value 3 in row 3 with column index 0
+ B.finalize( 3 ); // Finalizing row 3
+ \endcode
+
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,true,false>::append( size_t i, size_t j, const ElementType& value, bool check )
+{
+ if( row_ + m_ == matrix_.rows() ) {
+ matrix_.append( row_ + i, column_ + j, value, check );
+ }
+ else if( !check || !isDefault( value ) ) {
+ matrix_.insert( row_ + i, column_ + j, value );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Finalizing the element insertion of a column.
+//
+// \param j The index of the column to be finalized \f$[0..M-1]\f$.
+// \return void
+//
+// This function is part of the low-level interface to efficiently fill a submatrix with elements.
+// After completion of column \a j via the append() function, this function can be called to
+// finalize column \a j and prepare the next column for insertion process via append().
+//
+// \note Although finalize() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline void Submatrix<MT,AF,true,false>::finalize( size_t j )
+{
+ matrix_.trim( column_ + j );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address can alias with the submatrix. In contrast
+// to the isAliased() function this function is allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,AF,true,false>::canAlias( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this submatrix, \a false if not.
+//
+// This function returns whether the given address is aliased with the submatrix. In contrast
+// to the canAlias() function this function is not allowed to use compile time expressions to
+// optimize the evaluation.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename Other > // Data type of the foreign expression
+inline bool Submatrix<MT,AF,true,false>::isAliased( const Other* alias ) const noexcept
+{
+ return matrix_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the submatrix can be used in SMP assignments.
+//
+// \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the submatrix can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current number of
+// rows and/or columns of the matrix).
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+inline bool Submatrix<MT,AF,true,false>::canSMPAssign() const noexcept
+{
+ return false;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void Submatrix<MT,AF,true,false>::assign( const DenseMatrix<MT2,SO>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ reserve( 0UL, rows() * columns() );
+
+ for( size_t j=0UL; j<columns(); ++j ) {
+ for( size_t i=0UL; i<rows(); ++i ) {
+ if( IsSymmetric<MT>::value || IsHermitian<MT>::value )
+ set( i, j, (~rhs)(i,j) );
+ else
+ append( i, j, (~rhs)(i,j), true );
+ }
+ finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a column-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,AF,true,false>::assign( const SparseMatrix<MT2,true>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ reserve( 0UL, (~rhs).nonZeros() );
+
+ for( size_t j=0UL; j<(~rhs).columns(); ++j ) {
+ for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element ) {
+ if( IsSymmetric<MT>::value || IsHermitian<MT>::value )
+ set( element->index(), j, element->value() );
+ else
+ append( element->index(), j, element->value(), true );
+ }
+ finalize( j );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a row-major sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 > // Type of the right-hand side sparse matrix
+inline void Submatrix<MT,AF,true,false>::assign( const SparseMatrix<MT2,false>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ typedef ConstIterator_<MT2> RhsIterator;
+
+ // Counting the number of elements per column
+ std::vector<size_t> columnLengths( n_, 0UL );
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ ++columnLengths[element->index()];
+ }
+
+ // Resizing the sparse matrix
+ for( size_t j=0UL; j<n_; ++j ) {
+ reserve( j, columnLengths[j] );
+ }
+
+ // Appending the elements to the columns of the sparse matrix
+ for( size_t i=0UL; i<m_; ++i ) {
+ for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
+ if( IsSymmetric<MT>::value || IsHermitian<MT>::value )
+ set( i, element->index(), element->value() );
+ else
+ append( i, element->index(), element->value(), true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void Submatrix<MT,AF,true,false>::addAssign( const DenseMatrix<MT2,SO>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand side sparse matrix
+inline void Submatrix<MT,AF,true,false>::addAssign( const SparseMatrix<MT2,SO>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( AddType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense matrix.
+//
+// \param rhs The right-hand side dense matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side dense matrix
+ , bool SO > // Storage order of the right-hand side dense matrix
+inline void Submatrix<MT,AF,true,false>::subAssign( const DenseMatrix<MT2,SO>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse matrix.
+//
+// \param rhs The right-hand side sparse matrix to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename MT // Type of the sparse matrix
+ , bool AF > // Alignment flag
+template< typename MT2 // Type of the right-hand side sparse matrix
+ , bool SO > // Storage order of the right-hand sparse matrix
+inline void Submatrix<MT,AF,true,false>::subAssign( const SparseMatrix<MT2,SO>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE ( SubType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" );
+ BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/subvector/BaseTemplate.h b/src/cpu/blaze/math/views/subvector/BaseTemplate.h
new file mode 100644
index 00000000..9bcd241a
--- /dev/null
+++ b/src/cpu/blaze/math/views/subvector/BaseTemplate.h
@@ -0,0 +1,440 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/subvector/BaseTemplate.h
+// \brief Header file for the implementation of the Subvector base template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_SUBVECTOR_BASETEMPLATE_H_
+#define _BLAZE_MATH_VIEWS_SUBVECTOR_BASETEMPLATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/typetraits/IsDenseVector.h>
+#include <blaze/math/typetraits/IsRowVector.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup subvector Subvector
+// \ingroup views
+*/
+/*!\brief View on a specific subvector of a dense or sparse vector.
+// \ingroup subvector
+//
+// The Subvector class template represents a view on a specific subvector of a dense or sparse
+// vector primitive. The type of the vector is specified via the first template parameter:
+
+ \code
+ template< typename VT, bool AF, bool TF, bool DF >
+ class Subvector;
+ \endcode
+
+// - VT: specifies the type of the vector primitive. Subvector can be used with every vector
+// primitive or view, but does not work with any vector expression type.
+// - AF: the alignment flag specifies whether the subvector is aligned (\a blaze::aligned) or
+// unaligned (\a blaze::unaligned). The default value is \a blaze::unaligned.
+// - TF: specifies whether the vector is a row vector (\a blaze::rowVector) or a column
+// vector (\a blaze::columnVector). This template parameter doesn't have to be explicitly
+// defined, but is automatically derived from the first template parameter.
+// - DF: specifies whether the given vector type is a dense or sparse vector type. This template
+// parameter doesn't have to be defined explicitly, it is automatically derived from the
+// first template parameter. Defining the parameter explicitly may result in a compilation
+// error!
+//
+//
+// \n \section subvector_setup Setup of Subvectors
+//
+// A view on a dense or sparse subvector can be created very conveniently via the \c subvector()
+// function:
+
+ \code
+ using DenseVectorType = blaze::DynamicVector<double,blaze::rowVector>;
+
+ DenseVectorType x;
+ // ... Resizing and initialization
+
+ // Create a dense subvector from index 8 with a size of 16 (i.e. in the range [8..23])
+ blaze::Subvector<DenseVectorType> sv = subvector( x, 8UL, 16UL );
+ \endcode
+
+ \code
+ using SparseVectorType = blaze::CompressedVector<double,blaze::rowVector>;
+
+ SparseVectorType x;
+ // ... Resizing and initialization
+
+ // Create a sparse subvector from index 5 with a size of 7 (i.e. in the range [5..11])
+ blaze::Subvector<SparseVectorType> sv = subvector( x, 5UL, 7UL );
+ \endcode
+
+// This view can be treated as any other dense or sparse vector, i.e. it can be assigned to, it
+// can be copied from, and it can be used in arithmetic operations. The view can also be used on
+// both sides of an assignment: The subvector can either be used as an alias to grant write access
+// to a specific subvector of a vector primitive on the left-hand side of an assignment or to grant
+// read-access to a specific subvector of a vector primitive or expression on the right-hand side
+// of an assignment. The following example demonstrates this in detail:
+
+ \code
+ using DenseVectorType = blaze::DynamicVector<double,blaze::rowVector>;
+ using SparseVectorType = blaze::CompressedVector<double,blaze::rowVector>;
+ using DenseMatrixType = blaze::DynamicMatrix<double,blaze::rowMajor>;
+
+ DenseVectorType x;
+ SparseVectorType y;
+ DenseMatrixType A;
+ // ... Resizing and initialization
+
+ // Create a subvector from index 0 with a size of 10 (i.e. in the range [0..9])
+ blaze::Subvector<DenseVectorType> sv = subvector( x, 0UL, 10UL );
+
+ // Setting the first ten elements of x to the 2nd row of matrix A
+ sv = row( A, 2UL );
+
+ // Setting the second ten elements of x to y
+ subvector( x, 10UL, 10UL ) = y;
+
+ // Setting the 3rd row of A to a subvector of x
+ row( A, 3UL ) = subvector( x, 3UL, 10UL );
+
+ // Setting x to a subvector of the result of the addition between y and the 1st row of A
+ x = subvector( y + row( A, 1UL ), 2UL, 5UL )
+ \endcode
+
+// \n \section subvector_element_access Element access
+//
+// A subvector can be used like any other dense or sparse vector. For instance, the elements of
+// the subvector can be directly accessed with the subscript operator.
+
+ \code
+ using VectorType = blaze::DynamicVector<double,blaze::rowVector>;
+ VectorType v;
+ // ... Resizing and initialization
+
+ // Creating an 8-dimensional subvector, starting from index 4
+ blaze::Subvector<VectorType> sv = subvector( v, 4UL, 8UL );
+
+ // Setting the 1st element of the subvector, which corresponds to
+ // the element at index 5 in vector v
+ sv[1] = 2.0;
+ \endcode
+
+// The numbering of the subvector elements is
+
+ \f[\left(\begin{array}{*{5}{c}}
+ 0 & 1 & 2 & \cdots & N-1 \\
+ \end{array}\right),\f]
+
+// where N is the specified size of the subvector. Alternatively, the elements of a subvector can
+// be traversed via iterators. Just as with vectors, in case of non-const subvectors, \c begin()
+// and \c end() return an Iterator, which allows a manipulation of the non-zero values, in case
+// of constant subvectors a ConstIterator is returned:
+
+ \code
+ using VectorType = blaze::DynamicVector<int,blaze::rowVector>;
+ using SubvectorType = blaze::Subvector<VectorType>;
+
+ VectorType v( 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to a specific subvector of vector v
+ SubvectorType sv = subvector( v, 16UL, 64UL );
+
+ for( SubvectorType::Iterator it=sv.begin(); it!=sv.end(); ++it ) {
+ *it = ...; // OK: Write access to the dense subvector value.
+ ... = *it; // OK: Read access to the dense subvector value.
+ }
+
+ for( SubvectorType::ConstIterator it=sv.begin(); it!=sv.end(); ++it ) {
+ *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = *it; // OK: Read access to the dense subvector value.
+ }
+ \endcode
+
+ \code
+ using VectorType = blaze::CompressedVector<int,blaze::rowVector>;
+ using SubvectorType = blaze::Subvector<VectorType>;
+
+ VectorType v( 256UL );
+ // ... Resizing and initialization
+
+ // Creating a reference to a specific subvector of vector v
+ SubvectorType sv = subvector( v, 16UL, 64UL );
+
+ for( SubvectorType::Iterator it=sv.begin(); it!=sv.end(); ++it ) {
+ it->value() = ...; // OK: Write access to the value of the non-zero element.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+
+ for( SubvectorType::ConstIterator it=sv.begin(); it!=sv.end(); ++it ) {
+ it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
+ ... = it->value(); // OK: Read access to the value of the non-zero element.
+ it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
+ ... = it->index(); // OK: Read access to the index of the sparse element.
+ }
+ \endcode
+
+// \n \section subvector_element_insertion Element Insertion
+//
+// Inserting/accessing elements in a sparse subvector can be done by several alternative functions.
+// The following example demonstrates all options:
+
+ \code
+ using VectorType = blaze::CompressedVector<double,blaze::rowVector>;
+ VectorType v( 256UL ); // Non-initialized vector of size 256
+
+ using SubvectorType = blaze::Subvector<VectorType>;
+ SubvectorType sv = subvector( v, 10UL, 60UL ); // View on the range [10..69] of v
+
+ // The subscript operator provides access to all possible elements of the sparse subvector,
+ // including the zero elements. In case the subscript operator is used to access an element
+ // that is currently not stored in the sparse subvector, the element is inserted into the
+ // subvector.
+ sv[42] = 2.0;
+
+ // The second operation for inserting elements is the set() function. In case the element is
+ // not contained in the subvector it is inserted into the subvector, if it is already contained
+ // in the subvector its value is modified.
+ sv.set( 45UL, -1.2 );
+
+ // An alternative for inserting elements into the subvector is the insert() function. However,
+ // it inserts the element only in case the element is not already contained in the subvector.
+ sv.insert( 50UL, 3.7 );
+
+ // Just as in case of vectors, elements can also be inserted via the append() function. In
+ // case of subvectors, append() also requires that the appended element's index is strictly
+ // larger than the currently largest non-zero index of the subvector and that the subvector's
+ // capacity is large enough to hold the new element. Note however that due to the nature of
+ // a subvector, which may be an alias to the middle of a sparse vector, the append() function
+ // does not work as efficiently for a subvector as it does for a vector.
+ sv.reserve( 10UL );
+ sv.append( 51UL, -2.1 );
+ \endcode
+
+// \n \section subvector_common_operations Common Operations
+//
+// The current number of subvector elements can be obtained via the \c size() function, the
+// current capacity via the \c capacity() function, and the number of non-zero elements via
+// the \c nonZeros() function. However, since subvector are views on a specific subvector of
+// a vector, several operations are not possible on views, such as resizing and swapping:
+
+ \code
+ using VectorType = blaze::DynamicVector<int,blaze::rowVector>;
+ using SubvectorType = blaze::Subvector<VectorType>;
+
+ VectorType v( 42UL );
+ // ... Resizing and initialization
+
+ // Creating a view on the range [5..15] of vector v
+ SubvectorType sv = subvector( v, 5UL, 10UL );
+
+ sv.size(); // Returns the number of elements in the subvector
+ sv.capacity(); // Returns the capacity of the subvector
+ sv.nonZeros(); // Returns the number of non-zero elements contained in the subvector
+
+ sv.resize( 84UL ); // Compilation error: Cannot resize a subvector of a vector
+
+ SubvectorType sv2 = subvector( v, 15UL, 10UL );
+ swap( sv, sv2 ); // Compilation error: Swap operation not allowed
+ \endcode
+
+// \n \section subvector_arithmetic_operations Arithmetic Operations
+//
+// The following example gives an impression of the use of Subvector within arithmetic operations.
+// All operations (addition, subtraction, multiplication, scaling, ...) can be performed on all
+// possible combinations of dense and sparse vectors with fitting element types:
+
+ \code
+ using DenseVectorType = blaze::DynamicVector<double,blaze::rowVector>;
+ using SparseVectorType = blaze::CompressedVector<double,blaze::rowVector>;
+ DenseVectorType d1, d2, d3;
+ SparseVectorType s1, s2;
+
+ // ... Resizing and initialization
+
+ using DenseMatrixType = blaze::DynamicMatrix<double,blaze::rowMajor>;
+ DenseMatrixType A;
+
+ using SubvectorType = blaze::Subvector<DenseVectorType>;
+ SubvectorType sv( subvector( d1, 0UL, 10UL ) ); // View on the range [0..9] of vector d1
+
+ sv = d2; // Dense vector initialization of the range [0..9]
+ subvector( d1, 10UL, 10UL ) = s1; // Sparse vector initialization of the range [10..19]
+
+ d3 = sv + d2; // Dense vector/dense vector addition
+ s2 = s1 + subvector( d1, 10UL, 10UL ); // Sparse vector/dense vector addition
+ d2 = sv * subvector( d1, 20UL, 10UL ); // Component-wise vector multiplication
+
+ subvector( d1, 3UL, 4UL ) *= 2.0; // In-place scaling of the range [3..6]
+ d2 = subvector( d1, 7UL, 3UL ) * 2.0; // Scaling of the range [7..9]
+ d2 = 2.0 * subvector( d1, 7UL, 3UL ); // Scaling of the range [7..9]
+
+ subvector( d1, 0UL , 10UL ) += d2; // Addition assignment
+ subvector( d1, 10UL, 10UL ) -= s2; // Subtraction assignment
+ subvector( d1, 20UL, 10UL ) *= sv; // Multiplication assignment
+
+ double scalar = subvector( d1, 5UL, 10UL ) * trans( s1 ); // Scalar/dot/inner product between two vectors
+
+ A = trans( s1 ) * subvector( d1, 4UL, 16UL ); // Outer product between two vectors
+ \endcode
+
+// \n \section subvector_aligned_subvector Aligned Subvectors
+//
+// Usually subvectors can be defined anywhere within a vector. They may start at any position and
+// may have an arbitrary size (only restricted by the size of the underlying vector). However, in
+// contrast to vectors themselves, which are always properly aligned in memory and therefore can
+// provide maximum performance, this means that subvectors in general have to be considered to be
+// unaligned. This can be made explicit by the \a blaze::unaligned flag:
+
+ \code
+ using blaze::unaligned;
+
+ using DenseVectorType = blaze::DynamicVector<double,blaze::rowVector>;
+
+ DenseVectorType x;
+ // ... Resizing and initialization
+
+ // Identical creations of an unaligned subvector in the range [8..23]
+ blaze::Subvector<DenseVectorType> sv1 = subvector ( x, 8UL, 16UL );
+ blaze::Subvector<DenseVectorType> sv2 = subvector<unaligned>( x, 8UL, 16UL );
+ blaze::Subvector<DenseVectorType,unaligned> sv3 = subvector ( x, 8UL, 16UL );
+ blaze::Subvector<DenseVectorType,unaligned> sv4 = subvector<unaligned>( x, 8UL, 16UL );
+ \endcode
+
+// All of these calls to the \c subvector() function are identical. Whether the alignment flag is
+// explicitly specified or not, it always returns an unaligned subvector. Whereas this may provide
+// full flexibility in the creation of subvectors, this might result in performance restrictions
+// (even in case the specified subvector could be aligned). However, it is also possible to create
+// aligned subvectors. Aligned subvectors are identical to unaligned subvectors in all aspects,
+// except that they may pose additional alignment restrictions and therefore have less flexibility
+// during creation, but don't suffer from performance penalties and provide the same performance
+// as the underlying vector. Aligned subvectors are created by explicitly specifying the
+// \a blaze::aligned flag:
+
+ \code
+ using blaze::aligned;
+
+ // Creating an aligned subvector in the range [8..23]
+ blaze::Subvector<DenseVectorType,aligned> sv = subvector<aligned>( x, 8UL, 16UL );
+ \endcode
+
+// The alignment restrictions refer to system dependent address restrictions for the used element
+// type and the available vectorization mode (SSE, AVX, ...). The following source code gives some
+// examples for a double precision dense vector, assuming that AVX is available, which packs 4
+// \c double values into a SIMD vector:
+
+ \code
+ using blaze::columnVector;
+
+ using VectorType = blaze::DynamicVector<double,columnVector>;
+ using SubvectorType = blaze::Subvector<VectorType,aligned>;
+
+ VectorType d( 17UL );
+ // ... Resizing and initialization
+
+ // OK: Starts at the beginning and the size is a multiple of 4
+ SubvectorType dsv1 = subvector<aligned>( d, 0UL, 12UL );
+
+ // OK: Start index and the size are both a multiple of 4
+ SubvectorType dsv2 = subvector<aligned>( d, 4UL, 8UL );
+
+ // OK: The start index is a multiple of 4 and the subvector includes the last element
+ SubvectorType dsv3 = subvector<aligned>( d, 8UL, 9UL );
+
+ // Error: Start index is not a multiple of 4
+ SubvectorType dsv4 = subvector<aligned>( d, 5UL, 8UL );
+
+ // Error: Size is not a multiple of 4 and the subvector does not include the last element
+ SubvectorType dsv5 = subvector<aligned>( d, 8UL, 5UL );
+ \endcode
+
+// Note that the discussed alignment restrictions are only valid for aligned dense subvectors.
+// In contrast, aligned sparse subvectors at this time don't pose any additional restrictions.
+// Therefore aligned and unaligned sparse subvectors are truly fully identical. Still, in case
+// the blaze::aligned flag is specified during setup, an aligned subvector is created:
+
+ \code
+ using blaze::aligned;
+
+ using SparseVectorType = blaze::CompressedVector<double,blaze::rowVector>;
+
+ SparseVectorType x;
+ // ... Resizing and initialization
+
+ // Creating an aligned subvector in the range [8..23]
+ blaze::SparseSubvector<SparseVectorType,aligned> sv = subvector<aligned>( x, 8UL, 16UL );
+ \endcode
+
+// \n \section subvector_on_subvector Subvectors on Subvectors
+//
+// It is also possible to create a subvector view on another subvector. In this context it is
+// important to remember that the type returned by the \c subvector() function is the same type
+// as the type of the given subvector, since the view on a subvector is just another view on the
+// underlying vector:
+
+ \code
+ using VectorType = blaze::DynamicVector<double,blaze::rowVector>;
+ using SubvectorType = blaze::Subvector<VectorType>;
+
+ VectorType d1;
+
+ // ... Resizing and initialization
+
+ // Creating a subvector view on the dense vector d1
+ SubvectorType sv1 = subvector( d1, 5UL, 10UL );
+
+ // Creating a subvector view on the dense subvector sv1
+ SubvectorType sv2 = subvector( sv1, 1UL, 5UL );
+ \endcode
+*/
+template< typename VT // Type of the vector
+ , bool AF = unaligned // Alignment flag
+ , bool TF = IsRowVector<VT>::value // Transpose flag
+ , bool DF = IsDenseVector<VT>::value > // Density flag
+class Subvector
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/subvector/Dense.h b/src/cpu/blaze/math/views/subvector/Dense.h
new file mode 100644
index 00000000..bd62fda4
--- /dev/null
+++ b/src/cpu/blaze/math/views/subvector/Dense.h
@@ -0,0 +1,5270 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/subvector/Dense.h
+// \brief Subvector specialization for dense vectors
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_SUBVECTOR_DENSE_H_
+#define _BLAZE_MATH_VIEWS_SUBVECTOR_DENSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/Subvector.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/Computation.h>
+#include <blaze/math/expressions/CrossExpr.h>
+#include <blaze/math/expressions/DenseVector.h>
+#include <blaze/math/expressions/Forward.h>
+#include <blaze/math/expressions/View.h>
+#include <blaze/math/InitializerList.h>
+#include <blaze/math/shims/Clear.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/SIMD.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/typetraits/AreSIMDCombinable.h>
+#include <blaze/math/typetraits/HasSIMDAdd.h>
+#include <blaze/math/typetraits/HasSIMDDiv.h>
+#include <blaze/math/typetraits/HasSIMDMult.h>
+#include <blaze/math/typetraits/HasSIMDSub.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/typetraits/IsSparseVector.h>
+#include <blaze/math/views/subvector/BaseTemplate.h>
+#include <blaze/system/CacheSize.h>
+#include <blaze/system/Inline.h>
+#include <blaze/system/Optimizations.h>
+#include <blaze/system/Thresholds.h>
+#include <blaze/util/AlignmentCheck.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED DENSE SUBVECTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Subvector for unaligned dense subvectors.
+// \ingroup views
+//
+// This specialization of Subvector adapts the class template to the requirements of unaligned
+// dense subvectors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+class Subvector<VT,unaligned,TF,true>
+ : public DenseVector< Subvector<VT,unaligned,TF,true>, TF >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense vector expression.
+ typedef If_< IsExpression<VT>, VT, VT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Subvector<VT,unaligned,TF,true> This; //!< Type of this Subvector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this Subvector instance.
+ typedef SubvectorTrait_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Type of the subvector elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the subvector elements.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Subvector& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant subvector value.
+ typedef ConstReference_<VT> ConstReference;
+
+ //! Reference to a non-constant subvector value.
+ typedef If_< IsConst<VT>, ConstReference, Reference_<VT> > Reference;
+
+ //! Pointer to a constant subvector value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant subvector value.
+ typedef If_< Or< IsConst<VT>, Not< HasMutableDataAccess<VT> > >, ConstPointer, ElementType* > Pointer;
+ //**********************************************************************************************
+
+ //**SubvectorIterator class definition**********************************************************
+ /*!\brief Iterator over the elements of the sparse subvector.
+ */
+ template< typename IteratorType > // Type of the dense vector iterator
+ class SubvectorIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ //! The iterator category.
+ typedef typename std::iterator_traits<IteratorType>::iterator_category IteratorCategory;
+
+ //! Type of the underlying elements.
+ typedef typename std::iterator_traits<IteratorType>::value_type ValueType;
+
+ //! Pointer return type.
+ typedef typename std::iterator_traits<IteratorType>::pointer PointerType;
+
+ //! Reference return type.
+ typedef typename std::iterator_traits<IteratorType>::reference ReferenceType;
+
+ //! Difference between two iterators.
+ typedef typename std::iterator_traits<IteratorType>::difference_type DifferenceType;
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Default constructor of the SubvectorIterator class.
+ */
+ inline SubvectorIterator()
+ : iterator_ ( ) // Iterator to the current subvector element
+ , isAligned_( false ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor of the SubvectorIterator class.
+ //
+ // \param iterator Iterator to the initial element.
+ // \param isMemoryAligned Memory alignment flag.
+ */
+ inline SubvectorIterator( IteratorType iterator, bool isMemoryAligned )
+ : iterator_ ( iterator ) // Iterator to the current subvector element
+ , isAligned_( isMemoryAligned ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different SubvectorIterator instances.
+ //
+ // \param it The subvector iterator to be copied
+ */
+ template< typename IteratorType2 >
+ inline SubvectorIterator( const SubvectorIterator<IteratorType2>& it )
+ : iterator_ ( it.base() ) // Iterator to the current subvector element
+ , isAligned_( it.isAligned() ) // Memory alignment flag
+ {}
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment operator.
+ //
+ // \param inc The increment of the iterator.
+ // \return The incremented iterator.
+ */
+ inline SubvectorIterator& operator+=( size_t inc ) {
+ iterator_ += inc;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment operator.
+ //
+ // \param dec The decrement of the iterator.
+ // \return The decremented iterator.
+ */
+ inline SubvectorIterator& operator-=( size_t dec ) {
+ iterator_ -= dec;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline SubvectorIterator& operator++() {
+ ++iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubvectorIterator operator++( int ) {
+ return SubvectorIterator( iterator_++, isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Prefix decrement operator****************************************************************
+ /*!\brief Pre-decrement operator.
+ //
+ // \return Reference to the decremented iterator.
+ */
+ inline SubvectorIterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix decrement operator***************************************************************
+ /*!\brief Post-decrement operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubvectorIterator operator--( int ) {
+ return SubvectorIterator( iterator_--, isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the element at the current iterator position.
+ //
+ // \return The resulting value.
+ */
+ inline ReferenceType operator*() const {
+ return *iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Load function****************************************************************************
+ /*!\brief Load of a SIMD element of the dense subvector.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs a load of the current SIMD element of the subvector iterator.
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might
+ // result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType load() const {
+ return loadu();
+ }
+ //*******************************************************************************************
+
+ //**Loada function***************************************************************************
+ /*!\brief Aligned load of a SIMD element of the dense subvector.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an aligned load of the current SIMD element of the subvector
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loada() const {
+ return iterator_.loada();
+ }
+ //*******************************************************************************************
+
+ //**Loadu function***************************************************************************
+ /*!\brief Unaligned load of a SIMD element of the dense subvector.
+ //
+ // \return The loaded SIMD element.
+ //
+ // This function performs an unaligned load of the current SIMD element of the subvector
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline SIMDType loadu() const {
+ if( isAligned_ ) {
+ return iterator_.loada();
+ }
+ else {
+ return iterator_.loadu();
+ }
+ }
+ //*******************************************************************************************
+
+ //**Store function***************************************************************************
+ /*!\brief Store of a SIMD element of the dense subvector.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs a store of the current SIMD element of the subvector iterator.
+ // This function must \b NOT be called explicitly! It is used internally for the performance
+ // optimized evaluation of expression templates. Calling this function explicitly might
+ // result in erroneous results and/or in compilation errors.
+ */
+ inline void store( const SIMDType& value ) const {
+ storeu( value );
+ }
+ //*******************************************************************************************
+
+ //**Storea function**************************************************************************
+ /*!\brief Aligned store of a SIMD element of the dense subvector.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned store of the current SIMD element of the subvector
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline void storea( const SIMDType& value ) const {
+ iterator_.storea( value );
+ }
+ //*******************************************************************************************
+
+ //**Storeu function**************************************************************************
+ /*!\brief Unaligned store of a SIMD element of the dense subvector.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an unaligned store of the current SIMD element of the subvector
+ // iterator. This function must \b NOT be called explicitly! It is used internally for the
+ // performance optimized evaluation of expression templates. Calling this function explicitly
+ // might result in erroneous results and/or in compilation errors.
+ */
+ inline void storeu( const SIMDType& value ) const {
+ if( isAligned_ ) {
+ iterator_.storea( value );
+ }
+ else {
+ iterator_.storeu( value );
+ }
+ }
+ //*******************************************************************************************
+
+ //**Stream function**************************************************************************
+ /*!\brief Aligned, non-temporal store of a SIMD element of the dense subvector.
+ //
+ // \param value The SIMD element to be stored.
+ // \return void
+ //
+ // This function performs an aligned, non-temporal store of the current SIMD element of the
+ // subvector iterator. This function must \b NOT be called explicitly! It is used internally
+ // for the performance optimized evaluation of expression templates. Calling this function
+ // explicitly might result in erroneous results and/or in compilation errors.
+ */
+ inline void stream( const SIMDType& value ) const {
+ iterator_.stream( value );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two SubvectorIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ inline bool operator==( const SubvectorIterator& rhs ) const {
+ return iterator_ == rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two SubvectorIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ inline bool operator!=( const SubvectorIterator& rhs ) const {
+ return iterator_ != rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-than operator***********************************************************************
+ /*!\brief Less-than comparison between two SubvectorIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller, \a false if not.
+ */
+ inline bool operator<( const SubvectorIterator& rhs ) const {
+ return iterator_ < rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-than operator********************************************************************
+ /*!\brief Greater-than comparison between two SubvectorIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater, \a false if not.
+ */
+ inline bool operator>( const SubvectorIterator& rhs ) const {
+ return iterator_ > rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Less-or-equal-than operator**************************************************************
+ /*!\brief Less-than comparison between two SubvectorIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
+ */
+ inline bool operator<=( const SubvectorIterator& rhs ) const {
+ return iterator_ <= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Greater-or-equal-than operator***********************************************************
+ /*!\brief Greater-than comparison between two SubvectorIterator objects.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
+ */
+ inline bool operator>=( const SubvectorIterator& rhs ) const {
+ return iterator_ >= rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two iterators.
+ //
+ // \param rhs The right-hand side iterator.
+ // \return The number of elements between the two iterators.
+ */
+ inline DifferenceType operator-( const SubvectorIterator& rhs ) const {
+ return iterator_ - rhs.iterator_;
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between a SubvectorIterator and an integral value.
+ //
+ // \param it The iterator to be incremented.
+ // \param inc The number of elements the iterator is incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const SubvectorIterator operator+( const SubvectorIterator& it, size_t inc ) {
+ return SubvectorIterator( it.iterator_ + inc, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Addition operator************************************************************************
+ /*!\brief Addition between an integral value and a SubvectorIterator.
+ //
+ // \param inc The number of elements the iterator is incremented.
+ // \param it The iterator to be incremented.
+ // \return The incremented iterator.
+ */
+ friend inline const SubvectorIterator operator+( size_t inc, const SubvectorIterator& it ) {
+ return SubvectorIterator( it.iterator_ + inc, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Subtraction between a SubvectorIterator and an integral value.
+ //
+ // \param it The iterator to be decremented.
+ // \param dec The number of elements the iterator is decremented.
+ // \return The decremented iterator.
+ */
+ friend inline const SubvectorIterator operator-( const SubvectorIterator& it, size_t dec ) {
+ return SubvectorIterator( it.iterator_ - dec, it.isAligned_ );
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the subvector iterator.
+ //
+ // \return The current position of the subvector iterator.
+ */
+ inline IteratorType base() const {
+ return iterator_;
+ }
+ //*******************************************************************************************
+
+ //**IsAligned function***********************************************************************
+ /*!\brief Access to the iterator's memory alignment flag.
+ //
+ // \return \a true in case the iterator is aligned, \a false if it is not.
+ */
+ inline bool isAligned() const {
+ return isAligned_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType iterator_; //!< Iterator to the current subvector element.
+ bool isAligned_; //!< Memory alignment flag.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef SubvectorIterator< ConstIterator_<VT> > ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<VT>, ConstIterator, SubvectorIterator< Iterator_<VT> > > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Subvector( Operand vector, size_t index, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Subvector& operator= ( const ElementType& rhs );
+ inline Subvector& operator= ( initializer_list<ElementType> list );
+ inline Subvector& operator= ( const Subvector& rhs );
+ template< typename VT2 > inline Subvector& operator= ( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator+=( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator-=( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator*=( const DenseVector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator*=( const SparseVector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator/=( const DenseVector<VT2,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Subvector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Subvector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline Subvector& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value &&
+ HasSIMDSub< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value &&
+ HasSIMDMult< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value &&
+ HasSIMDDiv< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename VT2, bool AF2, bool TF2 >
+ inline bool canAlias( const Subvector<VT2,AF2,TF2,true>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename VT2, bool AF2, bool TF2 >
+ inline bool isAliased( const Subvector<VT2,AF2,TF2,true>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedAssign<VT2> > assign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedAssign<VT2> > assign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 > inline void assign( const SparseVector<VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedAddAssign<VT2> > addAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedAddAssign<VT2> > addAssign ( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 > inline void addAssign( const SparseVector<VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedSubAssign<VT2> > subAssign ( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedSubAssign<VT2> > subAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 > inline void subAssign( const SparseVector<VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedMultAssign<VT2> > multAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedMultAssign<VT2> > multAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 > inline void multAssign( const SparseVector<VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedDivAssign<VT2> > divAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedDivAssign<VT2> > divAssign( const DenseVector <VT2,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand vector_; //!< The dense vector containing the subvector.
+ const size_t offset_; //!< The offset of the subvector within the dense vector.
+ const size_t size_; //!< The size of the subvector.
+ const bool isAligned_; //!< Memory alignment flag.
+ /*!< The alignment flag indicates whether the subvector is fully aligned
+ with respect to the given element type and the available instruction
+ set. In case the subvector is fully aligned it is possible to use
+ aligned loads and stores instead of unaligned loads and stores. In
+ order to be aligned, the first element of the subvector must be
+ aligned. */
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename VT2, bool AF2, bool TF2, bool DF2 > friend class Subvector;
+
+ template< bool AF1, typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend const Subvector<VT2,AF1,TF2,DF2>
+ subvector( const Subvector<VT2,AF2,TF2,DF2>& sv, size_t index, size_t size );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isIntact( const Subvector<VT2,AF2,TF2,DF2>& sv ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT2,AF2,TF2,DF2>& a, const Vector<VT2,TF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Vector<VT2,TF2>& a, const Subvector<VT2,AF2,TF2,DF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT2,AF2,TF2,DF2>& a, const Subvector<VT2,AF2,TF2,DF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryAddAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool trySubAssign( const Subvector<VT2,AF2,DF2,TF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryMultAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend DerestrictTrait_< Subvector<VT2,AF2,TF2,DF2> > derestrict( Subvector<VT2,AF2,TF2,DF2>& sv );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBVECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Subvector.
+//
+// \param vector The dense vector containing the subvector.
+// \param index The first index of the subvector in the given vector.
+// \param n The size of the subvector.
+// \exception std::invalid_argument Invalid subvector specification.
+//
+// In case the subvector is not properly specified (i.e. if the specified first index is larger
+// than the size of the given vector or the subvector is specified beyond the size of the vector)
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline Subvector<VT,unaligned,TF,true>::Subvector( Operand vector, size_t index, size_t n )
+ : vector_ ( vector ) // The vector containing the subvector
+ , offset_ ( index ) // The offset of the subvector within the dense vector
+ , size_ ( n ) // The size of the subvector
+ , isAligned_( simdEnabled && vector.data() != nullptr && checkAlignment( data() ) )
+{
+ if( index + n > vector.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid subvector specification" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::Reference
+ Subvector<VT,unaligned,TF,true>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" );
+ return vector_[offset_+index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector columns.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::ConstReference
+ Subvector<VT,unaligned,TF,true>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" );
+ return const_cast<const VT&>( vector_ )[offset_+index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid subvector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::Reference
+ Subvector<VT,unaligned,TF,true>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid subvector access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid subvector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::ConstReference
+ Subvector<VT,unaligned,TF,true>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid subvector access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the subvector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::Pointer
+ Subvector<VT,unaligned,TF,true>::data() noexcept
+{
+ return vector_.data() + offset_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the subvector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::ConstPointer
+ Subvector<VT,unaligned,TF,true>::data() const noexcept
+{
+ return vector_.data() + offset_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::Iterator
+ Subvector<VT,unaligned,TF,true>::begin()
+{
+ return Iterator( vector_.begin() + offset_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::ConstIterator
+ Subvector<VT,unaligned,TF,true>::begin() const
+{
+ return ConstIterator( vector_.cbegin() + offset_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::ConstIterator
+ Subvector<VT,unaligned,TF,true>::cbegin() const
+{
+ return ConstIterator( vector_.cbegin() + offset_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::Iterator
+ Subvector<VT,unaligned,TF,true>::end()
+{
+ return Iterator( vector_.begin() + offset_ + size_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::ConstIterator
+ Subvector<VT,unaligned,TF,true>::end() const
+{
+ return ConstIterator( vector_.cbegin() + offset_ + size_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,unaligned,TF,true>::ConstIterator
+ Subvector<VT,unaligned,TF,true>::cend() const
+{
+ return ConstIterator( vector_.cbegin() + offset_ + size_, isAligned_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all subvector elements.
+//
+// \param rhs Scalar value to be assigned to all subvector elements.
+// \return Reference to the assigned subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator=( const ElementType& rhs )
+{
+ const size_t iend( offset_ + size_ );
+
+ for( size_t i=offset_; i<iend; ++i )
+ vector_[i] = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all subvector elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to subvector.
+//
+// This assignment operator offers the option to directly assign to all elements of the subvector
+// by means of an initializer list. The subvector elements are assigned the values from the given
+// initializer list. Missing values are reset to their default state. Note that in case the size
+// of the initializer list exceeds the size of the subvector, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator=( initializer_list<ElementType> list )
+{
+ if( list.size() > size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to subvector" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), begin() ), end(), ElementType() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Subvector.
+//
+// \param rhs Dense subvector to be copied.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Subvector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two subvectors don't match, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator=( const Subvector& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( &rhs == this || ( &vector_ == &rhs.vector_ && offset_ == rhs.offset_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Subvector sizes do not match" );
+ }
+
+ if( !tryAssign( vector_, rhs, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &vector_ ) ) {
+ const ResultType tmp( rhs );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator=( const Vector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ if( IsSparseVector<VT2>::value )
+ reset();
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the dense subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator+=( const Vector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAddAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpAddAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the dense subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator-=( const Vector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !trySubAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpSubAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the dense subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator*=( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryMultAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpMultAssign( left, tmp );
+ }
+ else {
+ smpMultAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the dense subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator*=( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const ResultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( vector_, tmp, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::operator/=( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryDivAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpDivAssign( left, tmp );
+ }
+ else {
+ smpDivAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a subvector and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the assigned subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Subvector<VT,unaligned,TF,true> >&
+ Subvector<VT,unaligned,TF,true>::operator*=( Other rhs )
+{
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) * rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a subvector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the assigned subvector.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Subvector<VT,unaligned,TF,true> >&
+ Subvector<VT,unaligned,TF,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) / rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the dense subvector.
+//
+// \return The size of the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,unaligned,TF,true>::size() const noexcept
+{
+ return size_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense subvector.
+//
+// \return The capacity of the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,unaligned,TF,true>::capacity() const noexcept
+{
+ return vector_.capacity() - offset_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the subvector.
+//
+// \return The number of non-zero elements in the subvector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,unaligned,TF,true>::nonZeros() const
+{
+ size_t nonzeros( 0 );
+
+ const size_t iend( offset_ + size_ );
+ for( size_t i=offset_; i<iend; ++i ) {
+ if( !isDefault( vector_[i] ) )
+ ++nonzeros;
+ }
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline void Subvector<VT,unaligned,TF,true>::reset()
+{
+ using blaze::clear;
+
+ const size_t iend( offset_ + size_ );
+ for( size_t i=offset_; i<iend; ++i )
+ clear( vector_[i] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the dense subvector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the subvector scaling.
+// \return Reference to the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline Subvector<VT,unaligned,TF,true>&
+ Subvector<VT,unaligned,TF,true>::scale( const Other& scalar )
+{
+ const size_t iend( offset_ + size_ );
+ for( size_t i=offset_; i<iend; ++i )
+ vector_[i] *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense subvector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense subvector, \a false if not.
+//
+// This function returns whether the given address can alias with the dense subvector.
+// In contrast to the isAliased() function this function is allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool Subvector<VT,unaligned,TF,true>::canAlias( const Other* alias ) const noexcept
+{
+ return vector_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense subvector can alias with the given dense subvector \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense subvector, \a false if not.
+//
+// This function returns whether the given address can alias with the dense subvector.
+// In contrast to the isAliased() function this function is allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 // Data type of the foreign dense subvector
+ , bool AF2 // Alignment flag of the foreign dense subvector
+ , bool TF2 > // Transpose flag of the foreign dense subvector
+inline bool Subvector<VT,unaligned,TF,true>::canAlias( const Subvector<VT2,AF2,TF2,true>* alias ) const noexcept
+{
+ return ( vector_.isAliased( &alias->vector_ ) &&
+ ( offset_ + size_ > alias->offset_ ) && ( offset_ < alias->offset_ + alias->size_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense subvector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense subvector, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense subvector.
+// In contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool Subvector<VT,unaligned,TF,true>::isAliased( const Other* alias ) const noexcept
+{
+ return vector_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense subvector is aliased with the given dense subvector \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense subvector, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense subvector.
+// In contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 // Data type of the foreign dense subvector
+ , bool AF2 // Alignment flag of the foreign dense subvector
+ , bool TF2 > // Transpose flag of the foreign dense subvector
+inline bool Subvector<VT,unaligned,TF,true>::isAliased( const Subvector<VT2,AF2,TF2,true>* alias ) const noexcept
+{
+ return ( vector_.isAliased( &alias->vector_ ) &&
+ ( offset_ + size_ > alias->offset_ ) && ( offset_ < alias->offset_ + alias->size_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the subvector is properly aligned in memory.
+//
+// \return \a true in case the subvector is aligned, \a false if not.
+//
+// This function returns whether the subvector is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of the subvector are guaranteed to conform to the
+// alignment restrictions of the underlying element type.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline bool Subvector<VT,unaligned,TF,true>::isAligned() const noexcept
+{
+ return isAligned_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the subvector can be used in SMP assignments.
+//
+// \return \a true in case the subvector can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the subvector can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current size of the
+// subvector).
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline bool Subvector<VT,unaligned,TF,true>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the dense subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename Subvector<VT,unaligned,TF,true>::SIMDType
+ Subvector<VT,unaligned,TF,true>::load( size_t index ) const noexcept
+{
+ if( isAligned_ )
+ return loada( index );
+ else
+ return loadu( index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the dense subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename Subvector<VT,unaligned,TF,true>::SIMDType
+ Subvector<VT,unaligned,TF,true>::loada( size_t index ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ return vector_.loada( offset_+index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the dense subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense
+// subvector. The index must be smaller than the number of subvector elements and it must be
+// a multiple of the number of values inside the SIMD element. This function must \b NOT
+// be called explicitly! It is used internally for the performance optimized evaluation of
+// expression templates. Calling this function explicitly might result in erroneous results
+// and/or in compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename Subvector<VT,unaligned,TF,true>::SIMDType
+ Subvector<VT,unaligned,TF,true>::loadu( size_t index ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ return vector_.loadu( offset_+index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ Subvector<VT,unaligned,TF,true>::store( size_t index, const SIMDType& value ) noexcept
+{
+ if( isAligned_ )
+ storea( index, value );
+ else
+ storeu( index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ Subvector<VT,unaligned,TF,true>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ vector_.storea( offset_+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ Subvector<VT,unaligned,TF,true>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ vector_.storeu( offset_+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store a specific SIMD element of the
+// dense subvector. The index must be smaller than the number of subvector elements and it
+// must be a multiple of the number of values inside the SIMD element. This function
+// must \b NOT be called explicitly! It is used internally for the performance optimized
+// evaluation of expression templates. Calling this function explicitly might result in
+// erroneous results and/or in compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ Subvector<VT,unaligned,TF,true>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ if( isAligned_ )
+ vector_.stream( offset_+index, value );
+ else
+ vector_.storeu( offset_+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::assign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] = (~rhs)[i ];
+ vector_[offset_+i+1UL] = (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] = (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::assign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ if( useStreaming && isAligned_ &&
+ ( size_ > ( cacheSize/( sizeof(ElementType) * 3UL ) ) ) &&
+ !(~rhs).isAliased( &vector_ ) )
+ {
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left = *right;
+ }
+ }
+ else
+ {
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,unaligned,TF,true>::assign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ vector_[offset_+element->index()] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedAddAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::addAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] += (~rhs)[i ];
+ vector_[offset_+i+1UL] += (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] += (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedAddAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::addAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left += *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,unaligned,TF,true>::addAssign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ vector_[offset_+element->index()] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedSubAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::subAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] -= (~rhs)[i ];
+ vector_[offset_+i+1UL] -= (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] -= (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedSubAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::subAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left -= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,unaligned,TF,true>::subAssign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ vector_[offset_+element->index()] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedMultAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::multAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] *= (~rhs)[i ];
+ vector_[offset_+i+1UL] *= (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] *= (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedMultAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::multAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left *= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,unaligned,TF,true>::multAssign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ vector_[offset_+element->index()] = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedDivAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::divAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] /= (~rhs)[i ];
+ vector_[offset_+i+1UL] /= (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] /= (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,unaligned,TF,true>::BLAZE_TEMPLATE VectorizedDivAssign<VT2> >
+ Subvector<VT,unaligned,TF,true>::divAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left /= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR ALIGNED DENSE SUBVECTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Subvector for aligned dense subvectors.
+// \ingroup subvector
+//
+// This specialization of Subvector adapts the class template to the requirements of aligned
+// dense subvectors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+class Subvector<VT,aligned,TF,true>
+ : public DenseVector< Subvector<VT,aligned,TF,true>, TF >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the dense vector expression.
+ typedef If_< IsExpression<VT>, VT, VT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Subvector<VT,aligned,TF,true> This; //!< Type of this Subvector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this Subvector instance.
+ typedef SubvectorTrait_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Type of the subvector elements.
+ typedef SIMDTrait_<ElementType> SIMDType; //!< SIMD type of the subvector elements.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Subvector& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant subvector value.
+ typedef ConstReference_<VT> ConstReference;
+
+ //! Reference to a non-constant subvector value.
+ typedef If_< IsConst<VT>, ConstReference, Reference_<VT> > Reference;
+
+ //! Pointer to a constant subvector value.
+ typedef const ElementType* ConstPointer;
+
+ //! Pointer to a non-constant subvector value.
+ typedef If_< Or< IsConst<VT>, Not< HasMutableDataAccess<VT> > >, ConstPointer, ElementType* > Pointer;
+
+ //! Iterator over constant elements.
+ typedef ConstIterator_<VT> ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<VT>, ConstIterator, Iterator_<VT> > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = VT::simdEnabled };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Subvector( Operand vector, size_t index, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data () noexcept;
+ inline ConstPointer data () const noexcept;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Subvector& operator= ( const ElementType& rhs );
+ inline Subvector& operator= ( initializer_list<ElementType> list );
+ inline Subvector& operator= ( const Subvector& rhs );
+ template< typename VT2 > inline Subvector& operator= ( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator+=( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator-=( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator*=( const DenseVector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator*=( const SparseVector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator/=( const DenseVector<VT2,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Subvector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_< IsNumeric<Other>, Subvector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ template< typename Other > inline Subvector& scale( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedAddAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value &&
+ HasSIMDAdd< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedSubAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value &&
+ HasSIMDSub< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedMultAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value &&
+ HasSIMDMult< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ //! Helper structure for the explicit application of the SFINAE principle.
+ template< typename VT2 >
+ struct VectorizedDivAssign {
+ enum : bool { value = useOptimizedKernels &&
+ simdEnabled && VT2::simdEnabled &&
+ AreSIMDCombinable< ElementType, ElementType_<VT2> >::value &&
+ HasSIMDDiv< ElementType, ElementType_<VT2> >::value };
+ };
+ //**********************************************************************************************
+
+ //**SIMD properties*****************************************************************************
+ //! The number of elements packed within a single SIMD element.
+ enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
+ //**********************************************************************************************
+
+ public:
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other >
+ inline bool canAlias( const Other* alias ) const noexcept;
+
+ template< typename VT2, bool AF2, bool TF2 >
+ inline bool canAlias( const Subvector<VT2,AF2,TF2,true>* alias ) const noexcept;
+
+ template< typename Other >
+ inline bool isAliased( const Other* alias ) const noexcept;
+
+ template< typename VT2, bool AF2, bool TF2 >
+ inline bool isAliased( const Subvector<VT2,AF2,TF2,true>* alias ) const noexcept;
+
+ inline bool isAligned () const noexcept;
+ inline bool canSMPAssign() const noexcept;
+
+ BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
+ BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
+
+ BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
+ BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedAssign<VT2> > assign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedAssign<VT2> > assign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 > inline void assign( const SparseVector<VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedAddAssign<VT2> > addAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedAddAssign<VT2> > addAssign ( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 > inline void addAssign( const SparseVector<VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedSubAssign<VT2> > subAssign ( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedSubAssign<VT2> > subAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 > inline void subAssign( const SparseVector<VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedMultAssign<VT2> > multAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedMultAssign<VT2> > multAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 > inline void multAssign( const SparseVector<VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline DisableIf_< VectorizedDivAssign<VT2> > divAssign( const DenseVector <VT2,TF>& rhs );
+
+ template< typename VT2 >
+ inline EnableIf_< VectorizedDivAssign<VT2> > divAssign( const DenseVector <VT2,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand vector_; //!< The dense vector containing the subvector.
+ const size_t offset_; //!< The offset of the subvector within the dense vector.
+ const size_t size_; //!< The size of the subvector.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< typename VT2, bool AF2, bool TF2, bool DF2 > friend class Subvector;
+
+ template< bool AF1, typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend const Subvector<VT2,AF1,TF2,DF2>
+ subvector( const Subvector<VT2,AF2,TF2,DF2>& sv, size_t index, size_t size );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isIntact( const Subvector<VT2,AF2,TF2,DF2>& sv ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT2,AF2,TF2,DF2>& a, const Vector<VT2,TF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Vector<VT2,TF2>& a, const Subvector<VT2,AF2,TF2,DF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT2,AF2,TF2,DF2>& a, const Subvector<VT2,AF2,TF2,DF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryAddAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool trySubAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryMultAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend DerestrictTrait_< Subvector<VT2,AF2,TF2,DF2> > derestrict( Subvector<VT2,AF2,TF2,DF2>& sv );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBVECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Subvector.
+//
+// \param vector The dense vector containing the subvector.
+// \param index The first index of the subvector in the given vector.
+// \param n The size of the subvector.
+// \exception std::invalid_argument Invalid subvector specification.
+//
+// In case the subvector is not properly specified (i.e. if the specified first index is larger
+// than the size of the given vector or the subvector is specified beyond the size of the vector)
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline Subvector<VT,aligned,TF,true>::Subvector( Operand vector, size_t index, size_t n )
+ : vector_( vector ) // The vector containing the subvector
+ , offset_( index ) // The offset of the subvector within the dense vector
+ , size_ ( n ) // The size of the subvector
+{
+ if( index + n > vector.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid subvector specification" );
+ }
+
+ if( simdEnabled && vector_.data() != nullptr && !checkAlignment( data() ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid subvector alignment" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return Reference to the accessed value.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::Reference
+ Subvector<VT,aligned,TF,true>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" );
+ return vector_[offset_+index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector columns.
+// \return Reference to the accessed value.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::ConstReference
+ Subvector<VT,aligned,TF,true>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" );
+ return const_cast<const VT&>( vector_ )[offset_+index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid subvector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::Reference
+ Subvector<VT,aligned,TF,true>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid subvector access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid subvector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::ConstReference
+ Subvector<VT,aligned,TF,true>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid subvector access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the subvector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::Pointer Subvector<VT,aligned,TF,true>::data() noexcept
+{
+ return vector_.data() + offset_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Low-level data access to the subvector elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::ConstPointer
+ Subvector<VT,aligned,TF,true>::data() const noexcept
+{
+ return vector_.data() + offset_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::Iterator Subvector<VT,aligned,TF,true>::begin()
+{
+ return ( vector_.begin() + offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::ConstIterator
+ Subvector<VT,aligned,TF,true>::begin() const
+{
+ return ( vector_.cbegin() + offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::ConstIterator
+ Subvector<VT,aligned,TF,true>::cbegin() const
+{
+ return ( vector_.cbegin() + offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::Iterator Subvector<VT,aligned,TF,true>::end()
+{
+ return ( vector_.begin() + offset_ + size_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::ConstIterator
+ Subvector<VT,aligned,TF,true>::end() const
+{
+ return ( vector_.cbegin() + offset_ + size_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,aligned,TF,true>::ConstIterator
+ Subvector<VT,aligned,TF,true>::cend() const
+{
+ return ( vector_.cbegin() + offset_ + size_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Homogenous assignment to all subvector elements.
+//
+// \param rhs Scalar value to be assigned to all subvector elements.
+// \return Reference to the assigned subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator=( const ElementType& rhs )
+{
+ const size_t iend( offset_ + size_ );
+
+ for( size_t i=offset_; i<iend; ++i )
+ vector_[i] = rhs;
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief List assignment to all subvector elements.
+//
+// \param list The initializer list.
+// \exception std::invalid_argument Invalid assignment to subvector.
+//
+// This assignment operator offers the option to directly assign to all elements of the subvector
+// by means of an initializer list. The subvector elements are assigned the values from the given
+// initializer list. Missing values are reset to their default state. Note that in case the size
+// of the initializer list exceeds the size of the subvector, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator=( initializer_list<ElementType> list )
+{
+ if( list.size() > size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to subvector" );
+ }
+
+ std::fill( std::copy( list.begin(), list.end(), begin() ), end(), ElementType() );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Subvector.
+//
+// \param rhs Dense subvector to be copied.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Subvector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two subvectors don't match, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator=( const Subvector& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( &rhs == this || ( &vector_ == &rhs.vector_ && offset_ == rhs.offset_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Subvector sizes do not match" );
+ }
+
+ if( !tryAssign( vector_, rhs, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &vector_ ) ) {
+ const ResultType tmp( ~rhs );
+ smpAssign( left, tmp );
+ }
+ else {
+ smpAssign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Vector to be assigned.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator=( const Vector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpAssign( left, tmp );
+ }
+ else {
+ if( IsSparseVector<VT2>::value )
+ reset();
+ smpAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the dense subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator+=( const Vector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAddAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpAddAssign( left, tmp );
+ }
+ else {
+ smpAddAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the dense subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator-=( const Vector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !trySubAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpSubAssign( left, tmp );
+ }
+ else {
+ smpSubAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a dense vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector to be multiplied with the dense subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator*=( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryMultAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpMultAssign( left, tmp );
+ }
+ else {
+ smpMultAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a sparse vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side sparse vector to be multiplied with the dense subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator*=( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const ResultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( vector_, tmp, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ smpAssign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline Subvector<VT,aligned,TF,true>&
+ Subvector<VT,aligned,TF,true>::operator/=( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryDivAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value && right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ smpDivAssign( left, tmp );
+ }
+ else {
+ smpDivAssign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a subvector and
+// a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the assigned subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Subvector<VT,aligned,TF,true> >&
+ Subvector<VT,aligned,TF,true>::operator*=( Other rhs )
+{
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) * rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a subvector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the assigned subvector.
+//
+// \note A division by zero is only checked by an user assert.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_< IsNumeric<Other>, Subvector<VT,aligned,TF,true> >&
+ Subvector<VT,aligned,TF,true>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+ smpAssign( left, (*this) / rhs );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the current size/dimension of the dense subvector.
+//
+// \return The size of the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,aligned,TF,true>::size() const noexcept
+{
+ return size_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the dense subvector.
+//
+// \return The capacity of the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,aligned,TF,true>::capacity() const noexcept
+{
+ return vector_.capacity() - offset_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the subvector.
+//
+// \return The number of non-zero elements in the subvector.
+//
+// Note that the number of non-zero elements is always less than or equal to the current size
+// of the subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,aligned,TF,true>::nonZeros() const
+{
+ size_t nonzeros( 0 );
+
+ const size_t iend( offset_ + size_ );
+ for( size_t i=offset_; i<iend; ++i ) {
+ if( !isDefault( vector_[i] ) )
+ ++nonzeros;
+ }
+
+ return nonzeros;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline void Subvector<VT,aligned,TF,true>::reset()
+{
+ using blaze::clear;
+
+ const size_t iend( offset_ + size_ );
+ for( size_t i=offset_; i<iend; ++i )
+ clear( vector_[i] );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the dense subvector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the subvector scaling.
+// \return Reference to the dense subvector.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline Subvector<VT,aligned,TF,true>& Subvector<VT,aligned,TF,true>::scale( const Other& scalar )
+{
+ const size_t iend( offset_ + size_ );
+ for( size_t i=offset_; i<iend; ++i )
+ vector_[i] *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense subvector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense subvector, \a false if not.
+//
+// This function returns whether the given address can alias with the dense subvector.
+// In contrast to the isAliased() function this function is allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool Subvector<VT,aligned,TF,true>::canAlias( const Other* alias ) const noexcept
+{
+ return vector_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense subvector can alias with the given dense subvector \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense subvector, \a false if not.
+//
+// This function returns whether the given address can alias with the dense subvector.
+// In contrast to the isAliased() function this function is allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 // Data type of the foreign dense subvector
+ , bool AF2 // Alignment flag of the foreign dense subvector
+ , bool TF2 > // Transpose flag of the foreign dense subvector
+inline bool Subvector<VT,aligned,TF,true>::canAlias( const Subvector<VT2,AF2,TF2,true>* alias ) const noexcept
+{
+ return ( vector_.isAliased( &alias->vector_ ) &&
+ ( offset_ + size_ > alias->offset_ ) && ( offset_ < alias->offset_ + alias->size_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense subvector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense subvector, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense subvector.
+// In contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool Subvector<VT,aligned,TF,true>::isAliased( const Other* alias ) const noexcept
+{
+ return vector_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the dense subvector is aliased with the given dense subvector \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this dense subvector, \a false if not.
+//
+// This function returns whether the given address is aliased with the dense subvector.
+// In contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 // Data type of the foreign dense subvector
+ , bool AF2 // Alignment flag of the foreign dense subvector
+ , bool TF2 > // Transpose flag of the foreign dense subvector
+inline bool Subvector<VT,aligned,TF,true>::isAliased( const Subvector<VT2,AF2,TF2,true>* alias ) const noexcept
+{
+ return ( vector_.isAliased( &alias->vector_ ) &&
+ ( offset_ + size_ > alias->offset_ ) && ( offset_ < alias->offset_ + alias->size_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the subvector is properly aligned in memory.
+//
+// \return \a true in case the subvector is aligned, \a false if not.
+//
+// This function returns whether the subvector is guaranteed to be properly aligned in memory,
+// i.e. whether the beginning and the end of the subvector are guaranteed to conform to the
+// alignment restrictions of the underlying element type.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline bool Subvector<VT,aligned,TF,true>::isAligned() const noexcept
+{
+ return true;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the subvector can be used in SMP assignments.
+//
+// \return \a true in case the subvector can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the subvector can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current size of the
+// subvector).
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+inline bool Subvector<VT,aligned,TF,true>::canSMPAssign() const noexcept
+{
+ return ( size() > SMP_DVECASSIGN_THRESHOLD );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Load of a SIMD element of the dense subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return The loaded SIMD element.
+//
+// This function performs a load of a specific SIMD element of the dense subvector. The index
+// must be smaller than the number of subvector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename Subvector<VT,aligned,TF,true>::SIMDType
+ Subvector<VT,aligned,TF,true>::load( size_t index ) const noexcept
+{
+ return loada( index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned load of a SIMD element of the dense subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an aligned load of a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename Subvector<VT,aligned,TF,true>::SIMDType
+ Subvector<VT,aligned,TF,true>::loada( size_t index ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ return vector_.loada( offset_+index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned load of a SIMD element of the dense subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return The loaded SIMD element.
+//
+// This function performs an unaligned load of a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE typename Subvector<VT,aligned,TF,true>::SIMDType
+ Subvector<VT,aligned,TF,true>::loadu( size_t index ) const noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ return vector_.loadu( offset_+index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Store of a SIMD element of the subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs a store a specific SIMD element of the dense subvector. The index
+// must be smaller than the number of subvector elements and it must be a multiple of the
+// number of values inside the SIMD element. This function must \b NOT be called explicitly!
+// It is used internally for the performance optimized evaluation of expression templates.
+// Calling this function explicitly might result in erroneous results and/or in compilation
+// errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ Subvector<VT,aligned,TF,true>::store( size_t index, const SIMDType& value ) noexcept
+{
+ storea( index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned store of a SIMD element of the subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned store a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ Subvector<VT,aligned,TF,true>::storea( size_t index, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ vector_.storea( offset_+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Unaligned store of a SIMD element of the subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an unaligned store a specific SIMD element of the dense subvector.
+// The index must be smaller than the number of subvector elements and it must be a multiple
+// of the number of values inside the SIMD element. This function must \b NOT be called
+// explicitly! It is used internally for the performance optimized evaluation of expression
+// templates. Calling this function explicitly might result in erroneous results and/or in
+// compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ Subvector<VT,aligned,TF,true>::storeu( size_t index, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ vector_.storeu( offset_+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Aligned, non-temporal store of a SIMD element of the subvector.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \param value The SIMD element to be stored.
+// \return void
+//
+// This function performs an aligned, non-temporal store a specific SIMD element of the
+// dense subvector. The index must be smaller than the number of subvector elements and it
+// must be a multiple of the number of values inside the SIMD element. This function
+// must \b NOT be called explicitly! It is used internally for the performance optimized
+// evaluation of expression templates. Calling this function explicitly might result in
+// erroneous results and/or in compilation errors.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+BLAZE_ALWAYS_INLINE void
+ Subvector<VT,aligned,TF,true>::stream( size_t index, const SIMDType& value ) noexcept
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( index < size() , "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size(), "Invalid subvector access index" );
+ BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL , "Invalid subvector access index" );
+
+ vector_.stream( offset_+index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::assign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] = (~rhs)[i ];
+ vector_[offset_+i+1UL] = (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] = (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::assign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ if( useStreaming && size_ > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( &vector_ ) )
+ {
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+ else
+ {
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left = *right; ++left; ++right;
+ }
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,aligned,TF,true>::assign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ vector_[offset_+element->index()] = element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedAddAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::addAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] += (~rhs)[i ];
+ vector_[offset_+i+1UL] += (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] += (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedAddAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::addAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left += *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,aligned,TF,true>::addAssign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ vector_[offset_+element->index()] += element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedSubAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::subAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] -= (~rhs)[i ];
+ vector_[offset_+i+1UL] -= (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] -= (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedSubAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::subAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left -= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,aligned,TF,true>::subAssign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ vector_[offset_+element->index()] -= element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedMultAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::multAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] *= (~rhs)[i ];
+ vector_[offset_+i+1UL] *= (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] *= (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedMultAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::multAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left *= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the multiplication assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be multiplied.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,aligned,TF,true>::multAssign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const ResultType tmp( serial( *this ) );
+
+ reset();
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element )
+ vector_[offset_+element->index()] = tmp[element->index()] * element->value();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline DisableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedDivAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::divAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size() & size_t(-2) );
+ for( size_t i=0UL; i<ipos; i+=2UL ) {
+ vector_[offset_+i ] /= (~rhs)[i ];
+ vector_[offset_+i+1UL] /= (~rhs)[i+1UL];
+ }
+ if( ipos < size() ) {
+ vector_[offset_+ipos] /= (~rhs)[ipos];
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief SIMD optimized implementation of the division assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the dense vector
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline EnableIf_< typename Subvector<VT,aligned,TF,true>::BLAZE_TEMPLATE VectorizedDivAssign<VT2> >
+ Subvector<VT,aligned,TF,true>::divAssign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const size_t ipos( size_ & size_t(-SIMDSIZE) );
+ BLAZE_INTERNAL_ASSERT( ( size_ - ( size_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
+
+ size_t i( 0UL );
+ Iterator left( begin() );
+ ConstIterator_<VT2> right( (~rhs).begin() );
+
+ for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<ipos; i+=SIMDSIZE ) {
+ left.store( left.load() / right.load() ); left += SIMDSIZE; right += SIMDSIZE;
+ }
+ for( ; i<size_; ++i ) {
+ *left /= *right; ++left; ++right;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DVECDVECCROSSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Subvector for dense vector/dense vector cross products.
+// \ingroup subvector
+//
+// This specialization of Subvector adapts the class template to the special case of dense
+// vector/dense vector cross products.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class Subvector< DVecDVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >
+ : public DenseVector< Subvector< DVecDVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >, TF >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef DVecDVecCrossExpr<VT1,VT2,TF> CPE; //!< Type of the cross product expression.
+ typedef ResultType_<CPE> RT; //!< Result type of the cross product expression.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Subvector<CPE,unaligned,TF,true> This; //!< Type of this Subvector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this Subvector instance.
+ typedef SubvectorTrait_<RT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<CPE> ElementType; //!< Type of the subvector elements.
+ typedef ReturnType_<CPE> ReturnType; //!< Return type for expression template evaluations
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Subvector specialization class.
+ //
+ // \param vector The dense vector/dense vector cross product expression.
+ // \param index The first index of the subvector in the given expression.
+ // \param n The size of the subvector.
+ */
+ explicit inline Subvector( const CPE& vector, size_t index, size_t n ) noexcept
+ : vector_( vector ) // The dense vector/dense vector cross product expression
+ , offset_( index ) // The offset of the subvector within the cross product expression
+ , size_ ( n ) // The size of the subvector
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < size(), "Invalid vector access index" );
+ return vector_[offset_+index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return size_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ CPE vector_; //!< The dense vector/dense vector cross product expression.
+ const size_t offset_; //!< The offset of the subvector within the cross product expression.
+ const size_t size_; //!< The size of the subvector.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< bool AF1, typename VT, bool AF2, bool TF2, bool DF2 >
+ friend const Subvector<VT,AF1,TF2,DF2>
+ subvector( const Subvector<VT,AF2,TF2,DF2>& sv, size_t index, size_t size );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isIntact( const Subvector<VT3,AF,TF2,DF2>& sv ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT3,AF,TF2,DF2>& a, const Vector<VT3,TF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Vector<VT3,TF2>& a, const Subvector<VT3,AF,TF2,DF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT3,AF,TF2,DF2>& a, const Subvector<VT3,AF,TF2,DF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryAssign( const Subvector<VT3,AF,TF2,DF2>& lhs, const Vector<VT4,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryAddAssign( const Subvector<VT2,AF,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool trySubAssign( const Subvector<VT2,AF,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryMultAssign( const Subvector<VT3,AF,TF2,DF2>& lhs, const Vector<VT4,TF2>& rhs, size_t index );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR DVECSVECCROSSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Subvector for dense vector/sparse vector cross products.
+// \ingroup subvector
+//
+// This specialization of Subvector adapts the class template to the special case of dense
+// vector/sparse vector cross products.
+*/
+template< typename VT1 // Type of the left-hand side dense vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class Subvector< DVecSVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >
+ : public DenseVector< Subvector< DVecSVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >, TF >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef DVecSVecCrossExpr<VT1,VT2,TF> CPE; //!< Type of the cross product expression.
+ typedef ResultType_<CPE> RT; //!< Result type of the cross product expression.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Subvector<CPE,unaligned,TF,true> This; //!< Type of this Subvector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this Subvector instance.
+ typedef SubvectorTrait_<RT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<CPE> ElementType; //!< Type of the subvector elements.
+ typedef ReturnType_<CPE> ReturnType; //!< Return type for expression template evaluations
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Subvector specialization class.
+ //
+ // \param vector The dense vector/sparse vector cross product expression.
+ // \param index The first index of the subvector in the given expression.
+ // \param n The size of the subvector.
+ */
+ explicit inline Subvector( const CPE& vector, size_t index, size_t n ) noexcept
+ : vector_( vector ) // The dense vector/sparse vector cross product expression
+ , offset_( index ) // The offset of the subvector within the cross product expression
+ , size_ ( n ) // The size of the subvector
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < size(), "Invalid vector access index" );
+ return vector_[offset_+index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return size_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ CPE vector_; //!< The dense vector/sparse vector cross product expression.
+ const size_t offset_; //!< The offset of the subvector within the cross product expression.
+ const size_t size_; //!< The size of the subvector.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< bool AF1, typename VT, bool AF2, bool TF2, bool DF2 >
+ friend const Subvector<VT,AF1,TF2,DF2>
+ subvector( const Subvector<VT,AF2,TF2,DF2>& sv, size_t index, size_t size );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isIntact( const Subvector<VT3,AF,TF2,DF2>& sv ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT3,AF,TF2,DF2>& a, const Vector<VT3,TF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Vector<VT3,TF2>& a, const Subvector<VT3,AF,TF2,DF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT3,AF,TF2,DF2>& a, const Subvector<VT3,AF,TF2,DF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryAssign( const Subvector<VT3,AF,TF2,DF2>& lhs, const Vector<VT4,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryAddAssign( const Subvector<VT2,AF,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool trySubAssign( const Subvector<VT2,AF,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryMultAssign( const Subvector<VT3,AF,TF2,DF2>& lhs, const Vector<VT4,TF2>& rhs, size_t index );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SVECDVECCROSSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Subvector for sparse vector/dense vector cross products.
+// \ingroup subvector
+//
+// This specialization of Subvector adapts the class template to the special case of sparse
+// vector/dense vector cross products.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side dense vector
+ , bool TF > // Transpose flag
+class Subvector< SVecDVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >
+ : public DenseVector< Subvector< SVecDVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >, TF >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef SVecDVecCrossExpr<VT1,VT2,TF> CPE; //!< Type of the cross product expression.
+ typedef ResultType_<CPE> RT; //!< Result type of the cross product expression.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Subvector<CPE,unaligned,TF,true> This; //!< Type of this Subvector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this Subvector instance.
+ typedef SubvectorTrait_<RT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<CPE> ElementType; //!< Type of the subvector elements.
+ typedef ReturnType_<CPE> ReturnType; //!< Return type for expression template evaluations
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Subvector specialization class.
+ //
+ // \param vector The sparse vector/dense vector cross product expression.
+ // \param index The first index of the subvector in the given expression.
+ // \param n The size of the subvector.
+ */
+ explicit inline Subvector( const CPE& vector, size_t index, size_t n ) noexcept
+ : vector_( vector ) // The sparse vector/dense vector cross product expression
+ , offset_( index ) // The offset of the subvector within the cross product expression
+ , size_ ( n ) // The size of the subvector
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < size(), "Invalid vector access index" );
+ return vector_[offset_+index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return size_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const noexcept {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ CPE vector_; //!< The sparse vector/dense vector cross product expression.
+ const size_t offset_; //!< The offset of the subvector within the cross product expression.
+ const size_t size_; //!< The size of the subvector.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< bool AF1, typename VT, bool AF2, bool TF2, bool DF2 >
+ friend const Subvector<VT,AF1,TF2,DF2>
+ subvector( const Subvector<VT,AF2,TF2,DF2>& sv, size_t index, size_t size );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isIntact( const Subvector<VT3,AF,TF2,DF2>& sv ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT3,AF,TF2,DF2>& a, const Vector<VT3,TF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Vector<VT3,TF2>& a, const Subvector<VT3,AF,TF2,DF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT3,AF,TF2,DF2>& a, const Subvector<VT3,AF,TF2,DF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryAssign( const Subvector<VT3,AF,TF2,DF2>& lhs, const Vector<VT4,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryAddAssign( const Subvector<VT2,AF,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool trySubAssign( const Subvector<VT2,AF,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryMultAssign( const Subvector<VT3,AF,TF2,DF2>& lhs, const Vector<VT4,TF2>& rhs, size_t index );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SVECSVECCROSSEXPR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Subvector for sparse vector/sparse vector cross products.
+// \ingroup subvector
+//
+// This specialization of Subvector adapts the class template to the special case of sparse
+// vector/sparse vector cross products.
+*/
+template< typename VT1 // Type of the left-hand side sparse vector
+ , typename VT2 // Type of the right-hand side sparse vector
+ , bool TF > // Transpose flag
+class Subvector< SVecSVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >
+ : public DenseVector< Subvector< SVecSVecCrossExpr<VT1,VT2,TF>, unaligned, TF, true >, TF >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef SVecSVecCrossExpr<VT1,VT2,TF> CPE; //!< Type of the cross product expression.
+ typedef ResultType_<CPE> RT; //!< Result type of the cross product expression.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Subvector<CPE,unaligned,TF,true> This; //!< Type of this Subvector instance.
+ typedef DenseVector<This,TF> BaseType; //!< Base type of this Subvector instance.
+ typedef SubvectorTrait_<RT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<CPE> ElementType; //!< Type of the subvector elements.
+ typedef ReturnType_<CPE> ReturnType; //!< Return type for expression template evaluations
+ typedef const ResultType CompositeType; //!< Data type for composite expression templates.
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template evaluation strategy.
+ enum : bool { simdEnabled = false };
+
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = false };
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Subvector specialization class.
+ //
+ // \param vector The sparse vector/sparse vector cross product expression.
+ // \param index The first index of the subvector in the given expression.
+ // \param n The size of the subvector.
+ */
+ explicit inline Subvector( const CPE& vector, size_t index, size_t n ) noexcept
+ : vector_( vector ) // The sparse vector/sparse vector cross product expression
+ , offset_( index ) // The offset of the subvector within the cross product expression
+ , size_ ( n ) // The size of the subvector
+ {}
+ //**********************************************************************************************
+
+ //**Subscript operator**************************************************************************
+ /*!\brief Subscript operator for the direct access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ */
+ inline ReturnType operator[]( size_t index ) const {
+ BLAZE_INTERNAL_ASSERT( index < size(), "Invalid vector access index" );
+ return vector_[offset_+index];
+ }
+ //**********************************************************************************************
+
+ //**At function*********************************************************************************
+ /*!\brief Checked access to the vector elements.
+ //
+ // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+ // \return The resulting value.
+ // \exception std::out_of_range Invalid vector access index.
+ */
+ inline ReturnType at( size_t index ) const {
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
+ }
+ return (*this)[index];
+ }
+ //**********************************************************************************************
+
+ //**Size function*******************************************************************************
+ /*!\brief Returns the current size/dimension of the vector.
+ //
+ // \return The size of the vector.
+ */
+ inline size_t size() const noexcept {
+ return size_;
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression can alias with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case the expression can alias, \a false otherwise.
+ */
+ template< typename T >
+ inline bool canAlias( const T* alias ) const noexcept {
+ return vector_.canAlias( alias );
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Returns whether the expression is aliased with the given address \a alias.
+ //
+ // \param alias The alias to be checked.
+ // \return \a true in case an alias effect is detected, \a false otherwise.
+ */
+ template< typename T >
+ inline bool isAliased( const T* alias ) const {
+ return vector_.isAliased( alias );
+ }
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ CPE vector_; //!< The sparse vector/sparse vector cross product expression.
+ const size_t offset_; //!< The offset of the subvector within the cross product expression.
+ const size_t size_; //!< The size of the subvector.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< bool AF1, typename VT, bool AF2, bool TF2, bool DF2 >
+ friend const Subvector<VT,AF1,TF2,DF2>
+ subvector( const Subvector<VT,AF2,TF2,DF2>& sv, size_t index, size_t size );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isIntact( const Subvector<VT3,AF,TF2,DF2>& sv ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT3,AF,TF2,DF2>& a, const Vector<VT3,TF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Vector<VT3,TF2>& a, const Subvector<VT3,AF,TF2,DF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT3,AF,TF2,DF2>& a, const Subvector<VT3,AF,TF2,DF2>& b ) noexcept;
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryAssign( const Subvector<VT3,AF,TF2,DF2>& lhs, const Vector<VT4,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryAddAssign( const Subvector<VT2,AF,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool trySubAssign( const Subvector<VT2,AF,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 >
+ friend bool tryMultAssign( const Subvector<VT3,AF,TF2,DF2>& lhs, const Vector<VT4,TF2>& rhs, size_t index );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/math/views/subvector/Sparse.h b/src/cpu/blaze/math/views/subvector/Sparse.h
new file mode 100644
index 00000000..1de6be35
--- /dev/null
+++ b/src/cpu/blaze/math/views/subvector/Sparse.h
@@ -0,0 +1,2004 @@
+//=================================================================================================
+/*!
+// \file blaze/math/views/subvector/Sparse.h
+// \brief Subvector specialization for sparse vectors
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_MATH_VIEWS_SUBVECTOR_SPARSE_H_
+#define _BLAZE_MATH_VIEWS_SUBVECTOR_SPARSE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/math/Aliases.h>
+#include <blaze/math/AlignmentFlag.h>
+#include <blaze/math/constraints/Computation.h>
+#include <blaze/math/constraints/DenseVector.h>
+#include <blaze/math/constraints/RequiresEvaluation.h>
+#include <blaze/math/constraints/SparseVector.h>
+#include <blaze/math/constraints/Subvector.h>
+#include <blaze/math/constraints/TransExpr.h>
+#include <blaze/math/constraints/TransposeFlag.h>
+#include <blaze/math/Exception.h>
+#include <blaze/math/expressions/SparseVector.h>
+#include <blaze/math/expressions/View.h>
+#include <blaze/math/shims/IsDefault.h>
+#include <blaze/math/shims/Serial.h>
+#include <blaze/math/sparse/SparseElement.h>
+#include <blaze/math/traits/AddTrait.h>
+#include <blaze/math/traits/DerestrictTrait.h>
+#include <blaze/math/traits/DivTrait.h>
+#include <blaze/math/traits/MultTrait.h>
+#include <blaze/math/traits/SubTrait.h>
+#include <blaze/math/traits/SubvectorTrait.h>
+#include <blaze/math/typetraits/IsExpression.h>
+#include <blaze/math/typetraits/IsRestricted.h>
+#include <blaze/math/views/subvector/BaseTemplate.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE SPECIALIZATION FOR SPARSE SUBVECTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of Subvector for sparse subvectors.
+// \ingroup views
+//
+// This specialization of Subvector adapts the class template to the requirements of sparse
+// subvectors.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+class Subvector<VT,AF,TF,false>
+ : public SparseVector< Subvector<VT,AF,TF,false>, TF >
+ , private View
+{
+ private:
+ //**Type definitions****************************************************************************
+ //! Composite data type of the sparse vector expression.
+ typedef If_< IsExpression<VT>, VT, VT& > Operand;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Subvector<VT,AF,TF,false> This; //!< Type of this Subvector instance.
+ typedef SparseVector<This,TF> BaseType; //!< Base type of this Subvector instance.
+ typedef SubvectorTrait_<VT> ResultType; //!< Result type for expression template evaluations.
+ typedef TransposeType_<ResultType> TransposeType; //!< Transpose type for expression template evaluations.
+ typedef ElementType_<VT> ElementType; //!< Type of the subvector elements.
+ typedef ReturnType_<VT> ReturnType; //!< Return type for expression template evaluations
+ typedef const Subvector& CompositeType; //!< Data type for composite expression templates.
+
+ //! Reference to a constant subvector value.
+ typedef ConstReference_<VT> ConstReference;
+
+ //! Reference to a non-constant subvector value.
+ typedef If_< IsConst<VT>, ConstReference, Reference_<VT> > Reference;
+ //**********************************************************************************************
+
+ //**SubvectorElement class definition***********************************************************
+ /*!\brief Access proxy for a specific element of the sparse subvector.
+ */
+ template< typename VectorType // Type of the sparse vector
+ , typename IteratorType > // Type of the sparse vector iterator
+ class SubvectorElement : private SparseElement
+ {
+ private:
+ //*******************************************************************************************
+ //! Compilation switch for the return type of the value member function.
+ /*! The \a returnConst compile time constant expression represents a compilation switch for
+ the return type of the value member function. In case the given vector type \a VectorType
+ is const qualified, \a returnConst will be set to 1 and the value member function will
+ return a reference to const. Otherwise \a returnConst will be set to 0 and the value
+ member function will offer write access to the sparse vector elements. */
+ enum : bool { returnConst = IsConst<VectorType>::value };
+ //*******************************************************************************************
+
+ //**Type definitions*************************************************************************
+ //! Type of the underlying sparse elements.
+ typedef typename std::iterator_traits<IteratorType>::value_type SET;
+
+ typedef Reference_<SET> RT; //!< Reference type of the underlying sparse element.
+ typedef ConstReference_<SET> CRT; //!< Reference-to-const type of the underlying sparse element.
+ //*******************************************************************************************
+
+ public:
+ //**Type definitions*************************************************************************
+ typedef ValueType_<SET> ValueType; //!< The value type of the row element.
+ typedef size_t IndexType; //!< The index type of the row element.
+ typedef IfTrue_<returnConst,CRT,RT> Reference; //!< Reference return type
+ typedef CRT ConstReference; //!< Reference-to-const return type.
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SubvectorElement class.
+ //
+ // \param pos Iterator to the current position within the sparse subvector.
+ // \param offset The offset within the according sparse vector.
+ */
+ inline SubvectorElement( IteratorType pos, size_t offset )
+ : pos_ ( pos ) // Iterator to the current position within the sparse subvector
+ , offset_( offset ) // Offset within the according sparse vector
+ {}
+ //*******************************************************************************************
+
+ //**Assignment operator**********************************************************************
+ /*!\brief Assignment to the accessed sparse subvector element.
+ //
+ // \param v The new value of the sparse subvector element.
+ // \return Reference to the sparse subvector element.
+ */
+ template< typename T > inline SubvectorElement& operator=( const T& v ) {
+ *pos_ = v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Addition assignment operator*************************************************************
+ /*!\brief Addition assignment to the accessed sparse subvector element.
+ //
+ // \param v The right-hand side value for the addition.
+ // \return Reference to the sparse subvector element.
+ */
+ template< typename T > inline SubvectorElement& operator+=( const T& v ) {
+ *pos_ += v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Subtraction assignment operator**********************************************************
+ /*!\brief Subtraction assignment to the accessed sparse subvector element.
+ //
+ // \param v The right-hand side value for the subtraction.
+ // \return Reference to the sparse subvector element.
+ */
+ template< typename T > inline SubvectorElement& operator-=( const T& v ) {
+ *pos_ -= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Multiplication assignment operator*******************************************************
+ /*!\brief Multiplication assignment to the accessed sparse subvector element.
+ //
+ // \param v The right-hand side value for the multiplication.
+ // \return Reference to the sparse subvector element.
+ */
+ template< typename T > inline SubvectorElement& operator*=( const T& v ) {
+ *pos_ *= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Division assignment operator*************************************************************
+ /*!\brief Division assignment to the accessed sparse subvector element.
+ //
+ // \param v The right-hand side value for the division.
+ // \return Reference to the sparse subvector element.
+ */
+ template< typename T > inline SubvectorElement& operator/=( const T& v ) {
+ *pos_ /= v;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the sparse subvector element at the current iterator position.
+ //
+ // \return Reference to the sparse subvector element at the current iterator position.
+ */
+ inline const SubvectorElement* operator->() const {
+ return this;
+ }
+ //*******************************************************************************************
+
+ //**Value function***************************************************************************
+ /*!\brief Access to the current value of the sparse subvector element.
+ //
+ // \return The current value of the sparse subvector element.
+ */
+ inline Reference value() const {
+ return pos_->value();
+ }
+ //*******************************************************************************************
+
+ //**Index function***************************************************************************
+ /*!\brief Access to the current index of the sparse element.
+ //
+ // \return The current index of the sparse element.
+ */
+ inline IndexType index() const {
+ return pos_->index() - offset_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current position within the sparse subvector.
+ size_t offset_; //!< Offset within the according sparse vector.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**SubvectorIterator class definition**********************************************************
+ /*!\brief Iterator over the elements of the sparse subvector.
+ */
+ template< typename VectorType // Type of the sparse vector
+ , typename IteratorType > // Type of the sparse vector iterator
+ class SubvectorIterator
+ {
+ public:
+ //**Type definitions*************************************************************************
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef SubvectorElement<VectorType,IteratorType> ValueType; //!< Type of the underlying elements.
+ typedef ValueType PointerType; //!< Pointer return type.
+ typedef ValueType ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying elements.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //*******************************************************************************************
+
+ //**Default constructor**********************************************************************
+ /*!\brief Default constructor for the SubvectorIterator class.
+ */
+ inline SubvectorIterator()
+ : pos_ () // Iterator to the current sparse element
+ , offset_() // The offset of the subvector within the sparse vector
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Constructor for the SubvectorIterator class.
+ //
+ // \param iterator Iterator to the current sparse element.
+ // \param index The starting index of the subvector within the sparse vector.
+ */
+ inline SubvectorIterator( IteratorType iterator, size_t index )
+ : pos_ ( iterator ) // Iterator to the current sparse element
+ , offset_( index ) // The offset of the subvector within the sparse vector
+ {}
+ //*******************************************************************************************
+
+ //**Constructor******************************************************************************
+ /*!\brief Conversion constructor from different SubvectorIterator instances.
+ //
+ // \param it The subvector iterator to be copied.
+ */
+ template< typename VectorType2, typename IteratorType2 >
+ inline SubvectorIterator( const SubvectorIterator<VectorType2,IteratorType2>& it )
+ : pos_ ( it.base() ) // Iterator to the current sparse element.
+ , offset_( it.offset() ) // The offset of the subvector within the sparse vector
+ {}
+ //*******************************************************************************************
+
+ //**Prefix increment operator****************************************************************
+ /*!\brief Pre-increment operator.
+ //
+ // \return Reference to the incremented iterator.
+ */
+ inline SubvectorIterator& operator++() {
+ ++pos_;
+ return *this;
+ }
+ //*******************************************************************************************
+
+ //**Postfix increment operator***************************************************************
+ /*!\brief Post-increment operator.
+ //
+ // \return The previous position of the iterator.
+ */
+ inline const SubvectorIterator operator++( int ) {
+ const SubvectorIterator tmp( *this );
+ ++(*this);
+ return tmp;
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse subvector element.
+ //
+ // \return Reference to the sparse subvector element.
+ */
+ inline ReferenceType operator*() const {
+ return ReferenceType( pos_, offset_ );
+ }
+ //*******************************************************************************************
+
+ //**Element access operator******************************************************************
+ /*!\brief Direct access to the current sparse subvector element.
+ //
+ // \return Pointer to the sparse subvector element.
+ */
+ inline PointerType operator->() const {
+ return PointerType( pos_, offset_ );
+ }
+ //*******************************************************************************************
+
+ //**Equality operator************************************************************************
+ /*!\brief Equality comparison between two SubvectorIterator objects.
+ //
+ // \param rhs The right-hand side subvector iterator.
+ // \return \a true if the iterators refer to the same element, \a false if not.
+ */
+ template< typename VectorType2, typename IteratorType2 >
+ inline bool operator==( const SubvectorIterator<VectorType2,IteratorType2>& rhs ) const {
+ return base() == rhs.base();
+ }
+ //*******************************************************************************************
+
+ //**Inequality operator**********************************************************************
+ /*!\brief Inequality comparison between two SubvectorIterator objects.
+ //
+ // \param rhs The right-hand side subvector iterator.
+ // \return \a true if the iterators don't refer to the same element, \a false if they do.
+ */
+ template< typename VectorType2, typename IteratorType2 >
+ inline bool operator!=( const SubvectorIterator<VectorType2,IteratorType2>& rhs ) const {
+ return !( *this == rhs );
+ }
+ //*******************************************************************************************
+
+ //**Subtraction operator*********************************************************************
+ /*!\brief Calculating the number of elements between two subvector iterators.
+ //
+ // \param rhs The right-hand side subvector iterator.
+ // \return The number of elements between the two subvector iterators.
+ */
+ inline DifferenceType operator-( const SubvectorIterator& rhs ) const {
+ return pos_ - rhs.pos_;
+ }
+ //*******************************************************************************************
+
+ //**Base function****************************************************************************
+ /*!\brief Access to the current position of the subvector iterator.
+ //
+ // \return The current position of the subvector iterator.
+ */
+ inline IteratorType base() const {
+ return pos_;
+ }
+ //*******************************************************************************************
+
+ //**Offset function**************************************************************************
+ /*!\brief Access to the offset of the subvector iterator.
+ //
+ // \return The offset of the subvector iterator.
+ */
+ inline size_t offset() const noexcept {
+ return offset_;
+ }
+ //*******************************************************************************************
+
+ private:
+ //**Member variables*************************************************************************
+ IteratorType pos_; //!< Iterator to the current sparse element.
+ size_t offset_; //!< The offset of the subvector within the sparse vector.
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ //! Iterator over constant elements.
+ typedef SubvectorIterator< const VT, ConstIterator_<VT> > ConstIterator;
+
+ //! Iterator over non-constant elements.
+ typedef If_< IsConst<VT>, ConstIterator, SubvectorIterator< VT, Iterator_<VT> > > Iterator;
+ //**********************************************************************************************
+
+ //**Compilation flags***************************************************************************
+ //! Compilation switch for the expression template assignment strategy.
+ enum : bool { smpAssignable = VT::smpAssignable };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline Subvector( Operand vector, size_t index, size_t n );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index );
+ inline ConstReference operator[]( size_t index ) const;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Iterator begin ();
+ inline ConstIterator begin () const;
+ inline ConstIterator cbegin() const;
+ inline Iterator end ();
+ inline ConstIterator end () const;
+ inline ConstIterator cend () const;
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline Subvector& operator= ( const Subvector& rhs );
+ template< typename VT2 > inline Subvector& operator= ( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator+=( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator-=( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator*=( const Vector<VT2,TF>& rhs );
+ template< typename VT2 > inline Subvector& operator/=( const DenseVector<VT2,TF>& rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Subvector >& operator*=( Other rhs );
+
+ template< typename Other >
+ inline EnableIf_<IsNumeric<Other>, Subvector >& operator/=( Other rhs );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size() const noexcept;
+ inline size_t capacity() const noexcept;
+ inline size_t nonZeros() const;
+ inline void reset();
+ inline Iterator set ( size_t index, const ElementType& value );
+ inline Iterator insert ( size_t index, const ElementType& value );
+ inline void erase ( size_t index );
+ inline Iterator erase ( Iterator pos );
+ inline Iterator erase ( Iterator first, Iterator last );
+ inline void reserve( size_t n );
+ template< typename Other > inline Subvector& scale ( const Other& scalar );
+ //@}
+ //**********************************************************************************************
+
+ //**Lookup functions****************************************************************************
+ /*!\name Lookup functions */
+ //@{
+ inline Iterator find ( size_t index );
+ inline ConstIterator find ( size_t index ) const;
+ inline Iterator lowerBound( size_t index );
+ inline ConstIterator lowerBound( size_t index ) const;
+ inline Iterator upperBound( size_t index );
+ inline ConstIterator upperBound( size_t index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Low-level utility functions*****************************************************************
+ /*!\name Low-level utility functions */
+ //@{
+ inline void append( size_t index, const ElementType& value, bool check=false );
+ //@}
+ //**********************************************************************************************
+
+ //**Expression template evaluation functions****************************************************
+ /*!\name Expression template evaluation functions */
+ //@{
+ template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
+ template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
+
+ inline bool canSMPAssign() const noexcept;
+
+ template< typename VT2 > inline void assign ( const DenseVector <VT2,TF>& rhs );
+ template< typename VT2 > inline void assign ( const SparseVector<VT2,TF>& rhs );
+ template< typename VT2 > inline void addAssign( const DenseVector <VT2,TF>& rhs );
+ template< typename VT2 > inline void addAssign( const SparseVector<VT2,TF>& rhs );
+ template< typename VT2 > inline void subAssign( const DenseVector <VT2,TF>& rhs );
+ template< typename VT2 > inline void subAssign( const SparseVector<VT2,TF>& rhs );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Operand vector_; //!< The sparse vector containing the subvector.
+ const size_t offset_; //!< The offset of the subvector within the sparse vector.
+ const size_t size_; //!< The size of the subvector.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ template< bool AF1, typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend const Subvector<VT2,AF1,TF2,DF2>
+ subvector( const Subvector<VT2,AF2,TF2,DF2>& sv, size_t index, size_t size );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isIntact( const Subvector<VT2,AF2,TF2,DF2>& sv ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT2,AF2,TF2,DF2>& a, const Vector<VT2,TF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Vector<VT2,TF2>& a, const Subvector<VT2,AF2,TF2,DF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend bool isSame( const Subvector<VT2,AF2,TF2,DF2>& a, const Subvector<VT2,AF2,TF2,DF2>& b ) noexcept;
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryAddAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool trySubAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 >
+ friend bool tryMultAssign( const Subvector<VT2,AF2,TF2,DF2>& lhs, const Vector<VT3,TF2>& rhs, size_t index );
+
+ template< typename VT2, bool AF2, bool TF2, bool DF2 >
+ friend DerestrictTrait_< Subvector<VT2,AF2,TF2,DF2> > derestrict( Subvector<VT2,AF2,TF2,DF2>& sv );
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SUBVECTOR_TYPE ( VT );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief The constructor for Subvector.
+//
+// \param vector The sparse vector containing the subvector.
+// \param index The index of the first element of the subvector.
+// \param n The size of the subvector.
+// \exception std::invalid_argument Invalid subvector specification.
+//
+// In case the subvector is not properly specified (i.e. if the specified first index is larger
+// than the size of the given vector or the subvector is specified beyond the size of the vector)
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline Subvector<VT,AF,TF,false>::Subvector( Operand vector, size_t index, size_t n )
+ : vector_( vector ) // The sparse vector containing the subvector
+ , offset_( index ) // The offset of the subvector within the sparse vector
+ , size_ ( n ) // The size of the subvector
+{
+ if( index + n > vector.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid subvector specification" );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Reference
+ Subvector<VT,AF,TF,false>::operator[]( size_t index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" );
+ return vector_[offset_+index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subscript operator for the direct access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector elements.
+// \return Reference to the accessed value.
+//
+// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
+// the at() function is guaranteed to perform a check of the given access index.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstReference
+ Subvector<VT,AF,TF,false>::operator[]( size_t index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" );
+ return const_cast<const VT&>( vector_ )[offset_+index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid subvector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Reference
+ Subvector<VT,AF,TF,false>::at( size_t index )
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid subvector access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Checked access to the subvector elements.
+//
+// \param index Access index. The index must be smaller than the number of subvector columns.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid subvector access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstReference
+ Subvector<VT,AF,TF,false>::at( size_t index ) const
+{
+ if( index >= size() ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid subvector access index" );
+ }
+ return (*this)[index];
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator Subvector<VT,AF,TF,false>::begin()
+{
+ if( offset_ == 0UL )
+ return Iterator( vector_.begin(), offset_ );
+ else
+ return Iterator( vector_.lowerBound( offset_ ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstIterator Subvector<VT,AF,TF,false>::begin() const
+{
+ if( offset_ == 0UL )
+ return ConstIterator( vector_.cbegin(), offset_ );
+ else
+ return ConstIterator( vector_.lowerBound( offset_ ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first element of the subvector.
+//
+// \return Iterator to the first element of the subvector.
+//
+// This function returns an iterator to the first element of the subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstIterator Subvector<VT,AF,TF,false>::cbegin() const
+{
+ if( offset_ == 0UL )
+ return ConstIterator( vector_.cbegin(), offset_ );
+ else
+ return ConstIterator( vector_.lowerBound( offset_ ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator Subvector<VT,AF,TF,false>::end()
+{
+ if( offset_ + size_ == vector_.size() )
+ return Iterator( vector_.end(), offset_ );
+ else
+ return Iterator( vector_.lowerBound( offset_ + size_ ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstIterator Subvector<VT,AF,TF,false>::end() const
+{
+ if( offset_ + size_ == vector_.size() )
+ return ConstIterator( vector_.cend(), offset_ );
+ else
+ return ConstIterator( vector_.lowerBound( offset_ + size_ ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator just past the last element of the subvector.
+//
+// \return Iterator just past the last element of the subvector.
+//
+// This function returns an iterator just past the last element of the subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstIterator Subvector<VT,AF,TF,false>::cend() const
+{
+ if( offset_ + size_ == vector_.size() )
+ return ConstIterator( vector_.cend(), offset_ );
+ else
+ return ConstIterator( vector_.lowerBound( offset_ + size_ ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Copy assignment operator for Subvector.
+//
+// \param rhs Sparse subvector to be copied.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Subvector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two subvectors don't match, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline Subvector<VT,AF,TF,false>&
+ Subvector<VT,AF,TF,false>::operator=( const Subvector& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+
+ if( this == &rhs || ( &vector_ == &rhs.vector_ && offset_ == rhs.offset_ ) )
+ return *this;
+
+ if( size() != rhs.size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ if( !tryAssign( vector_, rhs, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( rhs.canAlias( &vector_ ) ) {
+ const ResultType tmp( rhs );
+ reset();
+ assign( left, tmp );
+ }
+ else {
+ reset();
+ assign( left, rhs );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Assignment operator for different vectors.
+//
+// \param rhs Dense vector to be assigned.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument
+// exception is thrown.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,AF,TF,false>&
+ Subvector<VT,AF,TF,false>::operator=( const Vector<VT2,TF>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_<VT2>, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ typedef If_< IsRestricted<VT>, CompositeType_<VT2>, const VT2& > Right;
+ Right right( ~rhs );
+
+ if( !tryAssign( vector_, right, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ if( IsReference<Right>::value || right.canAlias( &vector_ ) ) {
+ const ResultType_<VT2> tmp( right );
+ reset();
+ assign( left, tmp );
+ }
+ else {
+ reset();
+ assign( left, right );
+ }
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be added to the sparse subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,AF,TF,false>&
+ Subvector<VT,AF,TF,false>::operator+=( const Vector<VT2,TF>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ typedef AddTrait_< ResultType, ResultType_<VT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( AddType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const AddType tmp( *this + (~rhs) );
+
+ if( !tryAssign( vector_, tmp, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be subtracted from the sparse subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,AF,TF,false>&
+ Subvector<VT,AF,TF,false>::operator-=( const Vector<VT2,TF>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ typedef SubTrait_< ResultType, ResultType_<VT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( SubType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const SubType tmp( *this - (~rhs) );
+
+ if( !tryAssign( vector_, tmp, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication of a vector
+// (\f$ \vec{a}*=\vec{b} \f$).
+//
+// \param rhs The right-hand side vector to be multiplied with the sparse subvector.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side vector
+inline Subvector<VT,AF,TF,false>&
+ Subvector<VT,AF,TF,false>::operator*=( const Vector<VT2,TF>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ typedef MultTrait_< ResultType, ResultType_<VT2> > MultType;
+
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( MultType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const MultType tmp( *this * (~rhs) );
+
+ if( !tryAssign( vector_, tmp, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
+//
+// \param rhs The right-hand side dense vector divisor.
+// \return Reference to the assigned subvector.
+// \exception std::invalid_argument Vector sizes do not match.
+// \exception std::invalid_argument Invalid assignment to restricted vector.
+//
+// In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
+// is thrown.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline Subvector<VT,AF,TF,false>&
+ Subvector<VT,AF,TF,false>::operator/=( const DenseVector<VT2,TF>& rhs )
+{
+ using blaze::assign;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE ( ResultType );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE ( ResultType_<VT2> );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_<VT2> );
+
+ typedef DivTrait_< ResultType, ResultType_<VT2> > DivType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( DivType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( DivType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
+
+ if( size() != (~rhs).size() ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
+ }
+
+ const DivType tmp( *this / (~rhs) );
+
+ if( !tryAssign( vector_, tmp, offset_ ) ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" );
+ }
+
+ DerestrictTrait_<This> left( derestrict( *this ) );
+
+ left.reset();
+ assign( left, tmp );
+
+ BLAZE_INTERNAL_ASSERT( isIntact( vector_ ), "Invariant violation detected" );
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Multiplication assignment operator for the multiplication between a sparse subvector
+// and a scalar value (\f$ \vec{a}*=s \f$).
+//
+// \param rhs The right-hand side scalar value for the multiplication.
+// \return Reference to the assigned subvector.
+//
+// This operator can only be used for built-in data types. Additionally, the elements of
+// the sparse subvector must support the multiplication assignment operator for the given
+// scalar built-in data type.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Subvector<VT,AF,TF,false> >&
+ Subvector<VT,AF,TF,false>::operator*=( Other rhs )
+{
+ const Iterator last( end() );
+ for( Iterator element=begin(); element!=last; ++element )
+ element->value() *= rhs;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Division assignment operator for the division of a sparse subvector by a scalar value
+// (\f$ \vec{a}/=s \f$).
+//
+// \param rhs The right-hand side scalar value for the division.
+// \return Reference to the assigned subvector.
+//
+// This operator can only be used for built-in data types. Additionally, the elements of the
+// sparse subvector must either support the multiplication assignment operator for the given
+// floating point data type or the division assignment operator for the given integral data
+// type.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the right-hand side scalar
+inline EnableIf_<IsNumeric<Other>, Subvector<VT,AF,TF,false> >&
+ Subvector<VT,AF,TF,false>::operator/=( Other rhs )
+{
+ BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
+
+ typedef DivTrait_<ElementType,Other> DT;
+ typedef If_< IsNumeric<DT>, DT, Other > Tmp;
+
+ const Iterator last( end() );
+
+ // Depending on the two involved data types, an integer division is applied or a
+ // floating point division is selected.
+ if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
+ const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
+ for( Iterator element=begin(); element!=last; ++element )
+ element->value() *= tmp;
+ }
+ else {
+ for( Iterator element=begin(); element!=last; ++element )
+ element->value() /= rhs;
+ }
+
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the size/dimension of the sparse subvector.
+//
+// \return The size of the sparse subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,AF,TF,false>::size() const noexcept
+{
+ return size_;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the maximum capacity of the sparse subvector.
+//
+// \return The capacity of the sparse subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,AF,TF,false>::capacity() const noexcept
+{
+ return nonZeros() + vector_.capacity() - vector_.nonZeros();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns the number of non-zero elements in the subvector.
+//
+// \return The number of non-zero elements in the subvector.
+//
+// Note that the number of non-zero elements is always smaller than the size of the subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline size_t Subvector<VT,AF,TF,false>::nonZeros() const
+{
+ return end() - begin();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Reset to the default initial values.
+//
+// \return void
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void Subvector<VT,AF,TF,false>::reset()
+{
+ vector_.erase( vector_.lowerBound( offset_ ), vector_.lowerBound( offset_ + size_ ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting an element of the sparse subvector.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be set.
+// \return Reference to the set value.
+//
+// This function sets the value of an element of the sparse subvector. In case the sparse subvector
+// already contains an element with index \a index its value is modified, else a new element with
+// the given \a value is inserted.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator
+ Subvector<VT,AF,TF,false>::set( size_t index, const ElementType& value )
+{
+ return Iterator( vector_.set( offset_ + index, value ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting an element into the sparse subvector.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be inserted.
+// \return Reference to the inserted value.
+// \exception std::invalid_argument Invalid sparse subvector access index.
+//
+// This function inserts a new element into the sparse subvector. However, duplicate elements
+// are not allowed. In case the sparse subvector already contains an element at index \a index,
+// a \a std::invalid_argument exception is thrown.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator
+ Subvector<VT,AF,TF,false>::insert( size_t index, const ElementType& value )
+{
+ return Iterator( vector_.insert( offset_ + index, value ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse subvector.
+//
+// \param index The index of the element to be erased. The index has to be in the range \f$[0..N-1]\f$.
+// \return void
+//
+// This function erases an element from the sparse subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void Subvector<VT,AF,TF,false>::erase( size_t index )
+{
+ vector_.erase( offset_ + index );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing an element from the sparse subvector.
+//
+// \param pos Iterator to the element to be erased.
+// \return void
+//
+// This function erases an element from the sparse subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator Subvector<VT,AF,TF,false>::erase( Iterator pos )
+{
+ return Iterator( vector_.erase( pos.base() ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Erasing a range of elements from the sparse subvector.
+//
+// \param first Iterator to first element to be erased.
+// \param last Iterator just past the last element to be erased.
+// \return Iterator to the element after the erased element.
+//
+// This function erases a range of elements from the sparse subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator
+ Subvector<VT,AF,TF,false>::erase( Iterator first, Iterator last )
+{
+ return Iterator( vector_.erase( first.base(), last.base() ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Setting the minimum capacity of the sparse subvector.
+//
+// \param n The new minimum capacity of the sparse subvector.
+// \return void
+//
+// This function increases the capacity of the sparse subvector to at least \a n elements. The
+// current values of the subvector elements are preserved.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+void Subvector<VT,AF,TF,false>::reserve( size_t n )
+{
+ const size_t current( capacity() );
+
+ if( n > current ) {
+ vector_.reserve( vector_.capacity() + n - current );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Scaling of the sparse subvector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
+//
+// \param scalar The scalar value for the subvector scaling.
+// \return Reference to the sparse subvector.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the scalar value
+inline Subvector<VT,AF,TF,false>& Subvector<VT,AF,TF,false>::scale( const Other& scalar )
+{
+ for( Iterator element=begin(); element!=end(); ++element )
+ element->value() *= scalar;
+ return *this;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOOKUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific subvector element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// subvector. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse subvector (the end() iterator) is returned. Note that
+// the returned sparse subvector iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator
+ Subvector<VT,AF,TF,false>::find( size_t index )
+{
+ const Iterator_<VT> pos( vector_.find( offset_ + index ) );
+
+ if( pos != vector_.end() )
+ return Iterator( pos, offset_ );
+ else
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Searches for a specific subvector element.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the element in case the index is found, end() iterator otherwise.
+//
+// This function can be used to check whether a specific element is contained in the sparse
+// subvector. It specifically searches for the element with index \a index. In case the element
+// is found, the function returns an iterator to the element. Otherwise an iterator just past
+// the last non-zero element of the sparse subvector (the end() iterator) is returned. Note that
+// the returned sparse subvector iterator is subject to invalidation due to inserting operations
+// via the subscript operator or the insert() function!
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstIterator
+ Subvector<VT,AF,TF,false>::find( size_t index ) const
+{
+ const ConstIterator_<VT> pos( vector_.find( offset_ + index ) );
+
+ if( pos != vector_.end() )
+ return Iterator( pos, offset_ );
+ else
+ return end();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse subvector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator
+ Subvector<VT,AF,TF,false>::lowerBound( size_t index )
+{
+ return Iterator( vector_.lowerBound( offset_ + index ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index not less then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index not less then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index not less then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse subvector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstIterator
+ Subvector<VT,AF,TF,false>::lowerBound( size_t index ) const
+{
+ return ConstIterator( vector_.lowerBound( offset_ + index ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse subvector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::Iterator
+ Subvector<VT,AF,TF,false>::upperBound( size_t index )
+{
+ return Iterator( vector_.upperBound( offset_ + index ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns an iterator to the first index greater then the given index.
+//
+// \param index The index of the search element. The index has to be in the range \f$[0..N-1]\f$.
+// \return Iterator to the first index greater then the given index, end() iterator otherwise.
+//
+// This function returns an iterator to the first element with an index greater then the given
+// index. In combination with the upperBound() function this function can be used to create a
+// pair of iterators specifying a range of indices. Note that the returned sparse subvector
+// iterator is subject to invalidation due to inserting operations via the subscript operator
+// or the insert() function!
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline typename Subvector<VT,AF,TF,false>::ConstIterator
+ Subvector<VT,AF,TF,false>::upperBound( size_t index ) const
+{
+ return ConstIterator( vector_.upperBound( offset_ + index ), offset_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOW-LEVEL UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Appending an element to the sparse subvector.
+//
+// \param index The index of the new element. The index has to be in the range \f$[0..N-1]\f$.
+// \param value The value of the element to be appended.
+// \param check \a true if the new value should be checked for default values, \a false if not.
+// \return void
+//
+// This function provides a very efficient way to fill a sparse subvector with elements. It
+// appends a new element to the end of the sparse subvector without any memory allocation.
+// Therefore it is strictly necessary to keep the following preconditions in mind:
+//
+// - the index of the new element must be strictly larger than the largest index of non-zero
+// elements in the sparse subvector
+// - the current number of non-zero elements must be smaller than the capacity of the subvector
+//
+// Ignoring these preconditions might result in undefined behavior! The optional \a check
+// parameter specifies whether the new value should be tested for a default value. If the new
+// value is a default value (for instance 0 in case of an integral element type) the value is
+// not appended. Per default the values are not tested.
+//
+// \note Although append() does not allocate new memory, it still invalidates all iterators
+// returned by the end() functions!
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline void Subvector<VT,AF,TF,false>::append( size_t index, const ElementType& value, bool check )
+{
+ if( offset_ + size_ == vector_.size() )
+ vector_.append( offset_ + index, value, check );
+ else if( !check || !isDefault( value ) )
+ vector_.insert( offset_ + index, value );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// EXPRESSION TEMPLATE EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse subvector can alias with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse subvector, \a false if not.
+//
+// This function returns whether the given address can alias with the sparse subvector. In
+// contrast to the isAliased() function this function is allowed to use compile time expressions
+// to optimize the evaluation.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool Subvector<VT,AF,TF,false>::canAlias( const Other* alias ) const noexcept
+{
+ return vector_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the sparse subvector is aliased with the given address \a alias.
+//
+// \param alias The alias to be checked.
+// \return \a true in case the alias corresponds to this sparse subvector, \a false if not.
+//
+// This function returns whether the given address is aliased with the sparse subvector.
+// In contrast to the canAlias() function this function is not allowed to use compile time
+// expressions to optimize the evaluation.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename Other > // Data type of the foreign expression
+inline bool Subvector<VT,AF,TF,false>::isAliased( const Other* alias ) const noexcept
+{
+ return vector_.isAliased( alias );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Returns whether the subvector can be used in SMP assignments.
+//
+// \return \a true in case the subvector can be used in SMP assignments, \a false if not.
+//
+// This function returns whether the subvector can be used in SMP assignments. In contrast to the
+// \a smpAssignable member enumeration, which is based solely on compile time information, this
+// function additionally provides runtime information (as for instance the current size of the
+// vector).
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+inline bool Subvector<VT,AF,TF,false>::canSMPAssign() const noexcept
+{
+ return false;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline void Subvector<VT,AF,TF,false>::assign( const DenseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ reserve( (~rhs).size() );
+
+ for( size_t i=0UL; i<size(); ++i ) {
+ append( i, (~rhs)[i], true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be assigned.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,AF,TF,false>::assign( const SparseVector<VT2,TF>& rhs )
+{
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+ BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
+
+ reserve( (~rhs).nonZeros() );
+
+ for( ConstIterator_<VT2> element=(~rhs).begin(); element!=(~rhs).end(); ++element ) {
+ append( element->index(), element->value(), true );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline void Subvector<VT,AF,TF,false>::addAssign( const DenseVector<VT2,TF>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( AddType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the addition assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be added.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,AF,TF,false>::addAssign( const SparseVector<VT2,TF>& rhs )
+{
+ typedef AddTrait_< ResultType, ResultType_<VT2> > AddType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( AddType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( AddType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const AddType tmp( serial( *this + (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a dense vector.
+//
+// \param rhs The right-hand side dense vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side dense vector
+inline void Subvector<VT,AF,TF,false>::subAssign( const DenseVector<VT2,TF>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( SubType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Default implementation of the subtraction assignment of a sparse vector.
+//
+// \param rhs The right-hand side sparse vector to be subtracted.
+// \return void
+//
+// This function must \b NOT be called explicitly! It is used internally for the performance
+// optimized evaluation of expression templates. Calling this function explicitly might result
+// in erroneous results and/or in compilation errors. Instead of using this function use the
+// assignment operator.
+*/
+template< typename VT // Type of the sparse vector
+ , bool AF // Alignment flag
+ , bool TF > // Transpose flag
+template< typename VT2 > // Type of the right-hand side sparse vector
+inline void Subvector<VT,AF,TF,false>::subAssign( const SparseVector<VT2,TF>& rhs )
+{
+ typedef SubTrait_< ResultType, ResultType_<VT2> > SubType;
+
+ BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE( SubType );
+ BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( SubType, TF );
+ BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
+
+ BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" );
+
+ const SubType tmp( serial( *this - (~rhs) ) );
+ reset();
+ assign( tmp );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/system/Assertion.h b/src/cpu/blaze/system/Assertion.h
new file mode 100644
index 00000000..d513e0c5
--- /dev/null
+++ b/src/cpu/blaze/system/Assertion.h
@@ -0,0 +1,47 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Assertion.h
+// \brief Configuration of the run time assertion macros
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_ASSERTION_H_
+#define _BLAZE_SYSTEM_ASSERTION_H_
+
+
+//=================================================================================================
+//
+// ASSERTION SETTINGS
+//
+//=================================================================================================
+
+#include <blaze/config/Assertion.h>
+
+#endif
diff --git a/src/cpu/blaze/system/BLAS.h b/src/cpu/blaze/system/BLAS.h
new file mode 100644
index 00000000..e5f9f74e
--- /dev/null
+++ b/src/cpu/blaze/system/BLAS.h
@@ -0,0 +1,62 @@
+//=================================================================================================
+/*!
+// \file blaze/system/BLAS.h
+// \brief System settings for the BLAS mode
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_BLAS_H_
+#define _BLAZE_SYSTEM_BLAS_H_
+
+
+//=================================================================================================
+//
+// BLAS MODE CONFIGURATION
+//
+//=================================================================================================
+
+#include <blaze/config/BLAS.h>
+
+
+
+
+//=================================================================================================
+//
+// BLAS INCLUDE FILE CONFIGURATION
+//
+//=================================================================================================
+
+#if BLAZE_BLAS_MODE
+extern "C" {
+#include BLAZE_BLAS_INCLUDE_FILE
+}
+#endif
+
+#endif
diff --git a/src/cpu/blaze/system/Blocking.h b/src/cpu/blaze/system/Blocking.h
new file mode 100644
index 00000000..d7019089
--- /dev/null
+++ b/src/cpu/blaze/system/Blocking.h
@@ -0,0 +1,129 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Blocking.h
+// \brief Header file for kernel specific block sizes
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_BLOCKING_H_
+#define _BLAZE_SYSTEM_BLOCKING_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Debugging.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLOCKING SETTINGS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+constexpr size_t DEFAULT_BLOCK_SIZE = 16UL;
+
+constexpr size_t DMATDMATMULT_DEFAULT_IBLOCK_SIZE = 64UL;
+constexpr size_t DMATDMATMULT_DEFAULT_JBLOCK_SIZE = 128UL;
+constexpr size_t DMATDMATMULT_DEFAULT_KBLOCK_SIZE = 128UL;
+
+constexpr size_t TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE = 128UL;
+constexpr size_t TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE = 64UL;
+constexpr size_t TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE = 128UL;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+constexpr size_t DEBUG_BLOCK_SIZE = 8UL;
+
+constexpr size_t DMATDMATMULT_DEBUG_IBLOCK_SIZE = 8UL;
+constexpr size_t DMATDMATMULT_DEBUG_JBLOCK_SIZE = 64UL;
+constexpr size_t DMATDMATMULT_DEBUG_KBLOCK_SIZE = 8UL;
+
+constexpr size_t TDMATTDMATMULT_DEBUG_IBLOCK_SIZE = 64UL;
+constexpr size_t TDMATTDMATMULT_DEBUG_JBLOCK_SIZE = 8UL;
+constexpr size_t TDMATTDMATMULT_DEBUG_KBLOCK_SIZE = 8UL;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+constexpr size_t BLOCK_SIZE = ( BLAZE_DEBUG_MODE ? DEBUG_BLOCK_SIZE : DEFAULT_BLOCK_SIZE );
+
+constexpr size_t DMATDMATMULT_JBLOCK_SIZE = ( BLAZE_DEBUG_MODE ? DMATDMATMULT_DEBUG_JBLOCK_SIZE : DMATDMATMULT_DEFAULT_JBLOCK_SIZE );
+constexpr size_t DMATDMATMULT_IBLOCK_SIZE = ( BLAZE_DEBUG_MODE ? DMATDMATMULT_DEBUG_IBLOCK_SIZE : DMATDMATMULT_DEFAULT_IBLOCK_SIZE );
+constexpr size_t DMATDMATMULT_KBLOCK_SIZE = ( BLAZE_DEBUG_MODE ? DMATDMATMULT_DEBUG_KBLOCK_SIZE : DMATDMATMULT_DEFAULT_KBLOCK_SIZE );
+
+constexpr size_t TDMATTDMATMULT_IBLOCK_SIZE = ( BLAZE_DEBUG_MODE ? TDMATTDMATMULT_DEBUG_IBLOCK_SIZE : TDMATTDMATMULT_DEFAULT_IBLOCK_SIZE );
+constexpr size_t TDMATTDMATMULT_JBLOCK_SIZE = ( BLAZE_DEBUG_MODE ? TDMATTDMATMULT_DEBUG_JBLOCK_SIZE : TDMATTDMATMULT_DEFAULT_JBLOCK_SIZE );
+constexpr size_t TDMATTDMATMULT_KBLOCK_SIZE = ( BLAZE_DEBUG_MODE ? TDMATTDMATMULT_DEBUG_KBLOCK_SIZE : TDMATTDMATMULT_DEFAULT_KBLOCK_SIZE );
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( blaze::BLOCK_SIZE >= 4UL );
+
+BLAZE_STATIC_ASSERT( blaze::DMATDMATMULT_IBLOCK_SIZE >= 4UL );
+BLAZE_STATIC_ASSERT( blaze::DMATDMATMULT_JBLOCK_SIZE >= 64UL && blaze::DMATDMATMULT_JBLOCK_SIZE % 32UL == 0UL );
+BLAZE_STATIC_ASSERT( blaze::DMATDMATMULT_KBLOCK_SIZE >= 4UL );
+
+BLAZE_STATIC_ASSERT( blaze::TDMATTDMATMULT_IBLOCK_SIZE >= 64UL && blaze::TDMATTDMATMULT_IBLOCK_SIZE % 32UL == 0UL );
+BLAZE_STATIC_ASSERT( blaze::TDMATTDMATMULT_JBLOCK_SIZE >= 4UL );
+BLAZE_STATIC_ASSERT( blaze::TDMATTDMATMULT_KBLOCK_SIZE >= 4UL );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/CacheSize.h b/src/cpu/blaze/system/CacheSize.h
new file mode 100644
index 00000000..072a8d16
--- /dev/null
+++ b/src/cpu/blaze/system/CacheSize.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/system/CacheSize.h
+// \brief Header file for the cache size of the target architecture
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_CACHESIZE_H_
+#define _BLAZE_SYSTEM_CACHESIZE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+
+
+
+
+//=================================================================================================
+//
+// CACHE SIZE
+//
+//=================================================================================================
+
+#include <blaze/config/CacheSize.h>
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( blaze::cacheSize > 100000UL && blaze::cacheSize < 100000000UL );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/Debugging.h b/src/cpu/blaze/system/Debugging.h
new file mode 100644
index 00000000..b96d2023
--- /dev/null
+++ b/src/cpu/blaze/system/Debugging.h
@@ -0,0 +1,64 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Debugging.h
+// \brief System settings for the debugging policy of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_DEBUGGING_H_
+#define _BLAZE_SYSTEM_DEBUGGING_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/config/Debugging.h>
+
+
+
+
+//=================================================================================================
+//
+// OPENMP MODE CONFIGURATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#if BLAZE_USE_DEBUG_MODE && !defined(NDEBUG)
+#define BLAZE_DEBUG_MODE 1
+#else
+#define BLAZE_DEBUG_MODE 0
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/Deprecated.h b/src/cpu/blaze/system/Deprecated.h
new file mode 100644
index 00000000..1e99196e
--- /dev/null
+++ b/src/cpu/blaze/system/Deprecated.h
@@ -0,0 +1,68 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Deprecated.h
+// \brief System specific deprecated tags
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_DEPRECATED_H_
+#define _BLAZE_SYSTEM_DEPRECATED_H_
+
+
+//=================================================================================================
+//
+// DEPRECATED MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\def BLAZE_DEPRECATED(func)
+// \brief Platform dependent macro for marking a function as deprecated.
+// \ingroup system
+*/
+
+// GNU, Intel, PGI, and IBM C++ compiler
+#if (defined __GNUC__) || (defined __PGI) || (defined __IBMCPP__)
+# define BLAZE_DEPRECATED( func ) func __attribute__((deprecated))
+
+// Microsoft Visual C++ compiler
+#elif (defined _MSC_VER)
+# define BLAZE_DEPRECATED( func ) __declspec(deprecated) func
+
+// Default case for other compilers
+#else
+# error Compiler-specific deprecated tag undefined!
+#endif
+
+/*! \endcond */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/Inline.h b/src/cpu/blaze/system/Inline.h
new file mode 100644
index 00000000..6a980c94
--- /dev/null
+++ b/src/cpu/blaze/system/Inline.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Inline.h
+// \brief System settings for the inline keywords
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_INLINE_H_
+#define _BLAZE_SYSTEM_INLINE_H_
+
+
+//=================================================================================================
+//
+// INLINE SETTINGS
+//
+//=================================================================================================
+
+#include <blaze/config/Inline.h>
+
+
+
+
+//=================================================================================================
+//
+// BLAZE_STRONG_INLINE KEYWORD
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\def BLAZE_STRONG_INLINE
+// \brief Platform dependent setup of a strengthened inline keyword.
+// \ingroup system
+*/
+#if BLAZE_USE_STRONG_INLINE && ( defined(_MSC_VER) || defined(__INTEL_COMPILER) )
+# define BLAZE_STRONG_INLINE __forceinline
+#else
+# define BLAZE_STRONG_INLINE inline
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// BLAZE_ALWAYS_INLINE KEYWORD
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\def BLAZE_ALWAYS_INLINE
+// \brief Platform dependent setup of an enforced inline keyword.
+// \ingroup system
+*/
+#if BLAZE_USE_ALWAYS_INLINE && defined(__GNUC__)
+# define BLAZE_ALWAYS_INLINE __attribute__((always_inline)) inline
+#else
+# define BLAZE_ALWAYS_INLINE BLAZE_STRONG_INLINE
+#endif
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/Logging.h b/src/cpu/blaze/system/Logging.h
new file mode 100644
index 00000000..0f5a5948
--- /dev/null
+++ b/src/cpu/blaze/system/Logging.h
@@ -0,0 +1,56 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Logging.h
+// \brief System settings for the logging functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_LOGGING_H_
+#define _BLAZE_SYSTEM_LOGGING_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/logging/LogLevel.h>
+
+
+
+
+//=================================================================================================
+//
+// LOGGING CONFIGURATION
+//
+//=================================================================================================
+
+#include <blaze/config/Logging.h>
+
+#endif
diff --git a/src/cpu/blaze/system/MPI.h b/src/cpu/blaze/system/MPI.h
new file mode 100644
index 00000000..bdb9d551
--- /dev/null
+++ b/src/cpu/blaze/system/MPI.h
@@ -0,0 +1,47 @@
+//=================================================================================================
+/*!
+// \file blaze/system/MPI.h
+// \brief System settings for the MPI parallelization
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_MPI_H_
+#define _BLAZE_SYSTEM_MPI_H_
+
+
+//=================================================================================================
+//
+// MPI MODE CONFIGURATION
+//
+//=================================================================================================
+
+#include <blaze/config/MPI.h>
+
+#endif
diff --git a/src/cpu/blaze/system/Optimizations.h b/src/cpu/blaze/system/Optimizations.h
new file mode 100644
index 00000000..0f2fe9ee
--- /dev/null
+++ b/src/cpu/blaze/system/Optimizations.h
@@ -0,0 +1,47 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Optimizations.h
+// \brief System settings for performance optimizations
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_OPTIMIZATIONS_H_
+#define _BLAZE_SYSTEM_OPTIMIZATIONS_H_
+
+
+//=================================================================================================
+//
+// OPTIMIZATION SETTINGS
+//
+//=================================================================================================
+
+#include <blaze/config/Optimizations.h>
+
+#endif
diff --git a/src/cpu/blaze/system/Precision.h b/src/cpu/blaze/system/Precision.h
new file mode 100644
index 00000000..2334fd8e
--- /dev/null
+++ b/src/cpu/blaze/system/Precision.h
@@ -0,0 +1,75 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Precision.h
+// \brief Header file for the floating point precision of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_PRECISION_H_
+#define _BLAZE_SYSTEM_PRECISION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/constraints/FloatingPoint.h>
+
+
+
+
+//=================================================================================================
+//
+// NUMERICAL PRECISION
+//
+//=================================================================================================
+
+#include <blaze/config/Precision.h>
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( blaze::real_t );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/Random.h b/src/cpu/blaze/system/Random.h
new file mode 100644
index 00000000..abcf5488
--- /dev/null
+++ b/src/cpu/blaze/system/Random.h
@@ -0,0 +1,56 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Random.h
+// \brief Header file for the random number generator used in the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_RANDOM_H_
+#define _BLAZE_SYSTEM_RANDOM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <random>
+
+
+
+
+//=================================================================================================
+//
+// RANDOM NUMBER GENERATOR CONFIGURATION
+//
+//=================================================================================================
+
+#include <blaze/config/Random.h>
+
+#endif
diff --git a/src/cpu/blaze/system/Restrict.h b/src/cpu/blaze/system/Restrict.h
new file mode 100644
index 00000000..e19f0127
--- /dev/null
+++ b/src/cpu/blaze/system/Restrict.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Restrict.h
+// \brief System settings for the restrict keyword
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_RESTRICT_H_
+#define _BLAZE_SYSTEM_RESTRICT_H_
+
+
+//=================================================================================================
+//
+// RESTRICT SETTINGS
+//
+//=================================================================================================
+
+#include <blaze/config/Restrict.h>
+
+
+
+
+//=================================================================================================
+//
+// RESTRICT KEYWORD
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\def BLAZE_RESTRICT
+// \brief Platform dependent setup of the restrict keyword.
+// \ingroup system
+*/
+#if BLAZE_USE_RESTRICT
+
+// Intel compiler
+# if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)
+# define BLAZE_RESTRICT __restrict
+
+// GNU compiler
+# elif defined(__GNUC__)
+# define BLAZE_RESTRICT __restrict
+
+// Microsoft visual studio
+# elif defined(_MSC_VER)
+# define BLAZE_RESTRICT
+
+// All other compilers
+# else
+# define BLAZE_RESTRICT
+
+# endif
+#else
+# define BLAZE_RESTRICT
+#endif
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/SMP.h b/src/cpu/blaze/system/SMP.h
new file mode 100644
index 00000000..0faa8b03
--- /dev/null
+++ b/src/cpu/blaze/system/SMP.h
@@ -0,0 +1,126 @@
+//=================================================================================================
+/*!
+// \file blaze/system/SMP.h
+// \brief System settings for the shared-memory parallelization
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_SMP_H_
+#define _BLAZE_SYSTEM_SMP_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/config/SMP.h>
+
+
+
+
+//=================================================================================================
+//
+// OPENMP MODE CONFIGURATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the OpenMP parallelization.
+// \ingroup system
+//
+// This compilation switch enables/disables the OpenMP parallelization. In case OpenMP is enabled
+// during compilation the Blaze library attempts to parallelize all matrix and vector computations.
+// Note that the OpenMP-based parallelization has priority over the C++11 and Boost thread-based
+// parallelization and will be preferred in case several parallelizations are activated. In case
+// no parallelization is not enabled, all computations are performed on a single compute core.
+*/
+#if BLAZE_USE_SHARED_MEMORY_PARALLELIZATION && defined(_OPENMP)
+#define BLAZE_OPENMP_PARALLEL_MODE 1
+#else
+#define BLAZE_OPENMP_PARALLEL_MODE 0
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// C++11 THREAD PARALLEL MODE CONFIGURATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the C++11 parallelization.
+// \ingroup system
+//
+// This compilation switch enables/disables the parallelization based on C++11 threads. In case
+// the \c BLAZE_USE_CPP_THREADS command line argument is specified during compilation the Blaze
+// library attempts to parallelize all matrix and vector computations. Note however that the
+// OpenMP-based parallelization has priority over the C++11 thread parallelization and will
+// be preferred in case both parallelizations are activated. On the other hand, the C++11
+// thread parallelization has priority over the Boost thread-based parallelization. In case
+// no parallelization is enabled, all computations are performed on a single compute core.
+*/
+#if BLAZE_USE_SHARED_MEMORY_PARALLELIZATION && defined(BLAZE_USE_CPP_THREADS)
+#define BLAZE_CPP_THREADS_PARALLEL_MODE 1
+#else
+#define BLAZE_CPP_THREADS_PARALLEL_MODE 0
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// BOOST THREAD PARALLEL MODE CONFIGURATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the Boost parallelization.
+// \ingroup system
+//
+// This compilation switch enables/disables the parallelization based on Boost threads. In case
+// the \c BLAZE_USE_BOOST_THREADS command line argument is specified during compilation the Blaze
+// library attempts to parallelize all matrix and vector computations. Note however that the
+// OpenMP-based and the C++11 thread-based parallelizations have priority over the Boost thread
+// parallelization and will be preferred in case several parallelizations are activated. In case
+// no parallelization is enabled, all computations are performed on a single compute core.
+*/
+#if BLAZE_USE_SHARED_MEMORY_PARALLELIZATION && defined(BLAZE_USE_BOOST_THREADS)
+#define BLAZE_BOOST_THREADS_PARALLEL_MODE 1
+#else
+#define BLAZE_BOOST_THREADS_PARALLEL_MODE 0
+#endif
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/Signature.h b/src/cpu/blaze/system/Signature.h
new file mode 100644
index 00000000..38d723a8
--- /dev/null
+++ b/src/cpu/blaze/system/Signature.h
@@ -0,0 +1,72 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Signature.h
+// \brief Header file for a compiler independent type/function signature macro.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_SIGNATURE_H_
+#define _BLAZE_SYSTEM_SIGNATURE_H_
+
+
+//=================================================================================================
+//
+// SIGNATURE MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\def BLAZE_SIGNATURE
+// \brief Platform dependent setup of the type/function signature macro.
+// \ingroup system
+//
+// This macro contains the signature of the function the macro is used in. Note that the macro
+// must only be used inside a function!
+*/
+
+// Intel compiler
+#if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)
+# define BLAZE_SIGNATURE __PRETTY_FUNCTION__
+
+// GNU compiler
+#elif defined(__GNUC__)
+# define BLAZE_SIGNATURE __PRETTY_FUNCTION__
+
+// Microsoft visual studio
+#elif defined(_MSC_VER)
+# define BLAZE_SIGNATURE __FUNCSIG__
+
+// All other compilers
+#else
+# define BLAZE_SIGNATURE "Unknown function"
+#endif
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/StorageOrder.h b/src/cpu/blaze/system/StorageOrder.h
new file mode 100644
index 00000000..220ad3f8
--- /dev/null
+++ b/src/cpu/blaze/system/StorageOrder.h
@@ -0,0 +1,56 @@
+//=================================================================================================
+/*!
+// \file blaze/system/StorageOrder.h
+// \brief Header file for the default storage order for all vectors of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_STORAGEORDER_H_
+#define _BLAZE_SYSTEM_STORAGEORDER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/StorageOrder.h>
+
+
+
+
+//=================================================================================================
+//
+// STORAGE ORDER
+//
+//=================================================================================================
+
+#include <blaze/config/StorageOrder.h>
+
+#endif
diff --git a/src/cpu/blaze/system/System.h b/src/cpu/blaze/system/System.h
new file mode 100644
index 00000000..21344e7f
--- /dev/null
+++ b/src/cpu/blaze/system/System.h
@@ -0,0 +1,52 @@
+//=================================================================================================
+/*!
+// \file blaze/system/System.h
+// \brief System module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_SYSTEM_H_
+#define _BLAZE_SYSTEM_SYSTEM_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup system System settings
+//
+// The system module contains all system settings for the Blaze library.
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/Thresholds.h b/src/cpu/blaze/system/Thresholds.h
new file mode 100644
index 00000000..0364c65b
--- /dev/null
+++ b/src/cpu/blaze/system/Thresholds.h
@@ -0,0 +1,1034 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Thresholds.h
+// \brief Header file for the thresholds for matrix/vector and matrix/matrix multiplications
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_THRESHOLDS_H_
+#define _BLAZE_SYSTEM_THRESHOLDS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Debugging.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Types.h>
+
+
+
+
+//=================================================================================================
+//
+// THRESHOLDS
+//
+//=================================================================================================
+
+#include <blaze/config/Thresholds.h>
+
+
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BLAS THRESHOLDS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Row-major dense matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::DMATDVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies the threshold between the application of the custom Blaze
+// kernels and the BLAS kernels for the row-major dense matrix/dense vector multiplication. In
+// case the number of elements in the dense matrix is equal or higher than this value, the BLAS
+// kernels are preferred over the custom Blaze kernels. In case the number of elements in the
+// dense matrix is smaller, the Blaze kernels are used.
+*/
+constexpr size_t DMATDVECMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major dense matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::TDMATDVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies the threshold between the application of the custom Blaze
+// kernels and the BLAS kernels for the column-major dense matrix/dense vector multiplication.
+// In case the number of elements in the dense matrix is equal or higher than this value, the
+// BLAS kernels are preferred over the custom Blaze kernels. In case the number of elements in
+// the dense matrix is smaller, the Blaze kernels are used.
+*/
+constexpr size_t TDMATDVECMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Dense Vector/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::TDVECDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies the threshold between the application of the custom Blaze
+// kernels and the BLAS kernels for the dense vector/row-major dense matrix multiplication. In
+// case the number of elements in the dense matrix is equal or higher than this value, the BLAS
+// kernels are preferred over the custom Blaze kernels. In case the number of elements in the
+// dense matrix is smaller, the Blaze kernels are used.
+*/
+constexpr size_t TDVECDMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Dense Vector/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::TDVECTDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies the threshold between the application of the custom Blaze
+// kernels and the BLAS kernels for the dense vector/column-major dense matrix multiplication.
+// In case the number of elements in the dense matrix is equal or higher than this value, the
+// BLAS kernels are preferred over the custom Blaze kernels. In case the number of elements in
+// the dense matrix is smaller, the Blaze kernels are used.
+*/
+constexpr size_t TDVECTDMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Row-major dense matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::DMATDMATMULT_USER_THRESHOLD while the
+// Blaze debug mode is active. It specifies the threshold between the application of the custom
+// Blaze kernels and the BLAS kernels for the row-major dense matrix/row-major dense matrix
+// multiplication. In case the number of elements in the dense matrix is equal or higher than
+// this value, the BLAS kernels are preferred over the custom Blaze kernels. In case the number
+// of elements in the dense matrix is smaller, the Blaze kernels are used.
+*/
+constexpr size_t DMATDMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Row-major dense matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::DMATTDMATMULT_USER_THRESHOLD while the
+// Blaze debug mode is active. It specifies the threshold between the application of the custom
+// Blaze kernels and the BLAS kernels for the row-major dense matrix/column-major dense matrix
+// multiplication. In case the number of elements in the dense matrix is equal or higher than
+// this value, the BLAS kernels are preferred over the custom Blaze kernels. In case the number
+// of elements in the dense matrix is smaller, the Blaze kernels are used.
+*/
+constexpr size_t DMATTDMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major dense matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::TDMATDMATMULT_USER_THRESHOLD while the
+// Blaze debug mode is active. It specifies the threshold between the application of the custom
+// Blaze kernels and the BLAS kernels for the column-major dense matrix/row-major dense matrix
+// multiplication. In case the number of elements in the dense matrix is equal or higher than
+// this value, the BLAS kernels are preferred over the custom Blaze kernels. In case the number
+// of elements in the dense matrix is smaller, the Blaze kernels are used.
+*/
+constexpr size_t TDMATDMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major dense matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::TDMATTDMATMULT_USER_THRESHOLD while the
+// Blaze debug mode is active. It specifies the threshold between the application of the custom
+// Blaze kernels and the BLAS kernels for the column-major dense matrix/column-major dense matrix
+// multiplication. In case the number of elements in the dense matrix is equal or higher than
+// this value, the BLAS kernels are preferred over the custom Blaze kernels. In case the number
+// of elements in the dense matrix is smaller, the Blaze kernels are used.
+*/
+constexpr size_t TDMATTDMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Row-major dense matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::DMATSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies the threshold between the application of the Blaze kernels
+// for small and for large row-major dense matrix/row-major sparse matrix multiplications. In case
+// the number of elements of the target matrix is equal or higher than this value, the kernel for
+// large matrices is preferred over the kernel for small matrices. In case the number of elements
+// in the target matrix is smaller, the kernel for small matrices is used.
+*/
+constexpr size_t DMATSMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major dense matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::DMATSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies the threshold between the application of the Blaze kernels
+// for small and for large column-major dense matrix/row-major sparse matrix multiplications.
+// In case the number of elements of the target matrix is equal or higher than this value, the
+// kernel for large matrices is preferred over the kernel for small matrices. In case the number
+// of elements in the target matrix is smaller, the kernel for small matrices is used.
+*/
+constexpr size_t TDMATSMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major sparse matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::TSMATDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies the threshold between the application of the Blaze kernels
+// for small and for large column-major sparse matrix/row-major dense matrix multiplications.
+// In case the number of elements of the target matrix is equal or higher than this value, the
+// kernel for large matrices is preferred over the kernel for small matrices. In case the number
+// of elements in the target matrix is smaller, the kernel for small matrices is used.
+*/
+constexpr size_t TSMATDMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Column-major sparse matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::TSMATTDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies the threshold between the application of the Blaze kernels
+// for small and for large column-major sparse matrix/column-major dense matrix multiplications.
+// In case the number of elements of the target matrix is equal or higher than this value, the
+// kernel for large matrices is preferred over the kernel for small matrices. In case the number
+// of elements in the target matrix is smaller, the kernel for small matrices is used.
+*/
+constexpr size_t TSMATTDMATMULT_DEBUG_THRESHOLD = 256UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+constexpr size_t DMATDVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? DMATDVECMULT_DEBUG_THRESHOLD : DMATDVECMULT_USER_THRESHOLD );
+constexpr size_t TDMATDVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? TDMATDVECMULT_DEBUG_THRESHOLD : TDMATDVECMULT_USER_THRESHOLD );
+constexpr size_t TDVECDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? TDVECDMATMULT_DEBUG_THRESHOLD : TDVECDMATMULT_USER_THRESHOLD );
+constexpr size_t TDVECTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? TDVECTDMATMULT_DEBUG_THRESHOLD : TDVECTDMATMULT_USER_THRESHOLD );
+constexpr size_t DMATDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? DMATDMATMULT_DEBUG_THRESHOLD : DMATDMATMULT_USER_THRESHOLD );
+constexpr size_t DMATTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? DMATTDMATMULT_DEBUG_THRESHOLD : DMATTDMATMULT_USER_THRESHOLD );
+constexpr size_t TDMATDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? TDMATDMATMULT_DEBUG_THRESHOLD : TDMATDMATMULT_USER_THRESHOLD );
+constexpr size_t TDMATTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? TDMATTDMATMULT_DEBUG_THRESHOLD : TDMATTDMATMULT_USER_THRESHOLD );
+constexpr size_t DMATSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? DMATSMATMULT_DEBUG_THRESHOLD : DMATSMATMULT_USER_THRESHOLD );
+constexpr size_t TDMATSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? TDMATSMATMULT_DEBUG_THRESHOLD : TDMATSMATMULT_USER_THRESHOLD );
+constexpr size_t TSMATDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? TSMATDMATMULT_DEBUG_THRESHOLD : TSMATDMATMULT_USER_THRESHOLD );
+constexpr size_t TSMATTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? TSMATTDMATMULT_DEBUG_THRESHOLD : TSMATTDMATMULT_USER_THRESHOLD );
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMP THRESHOLDS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief SMP dense vector assignment threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DVECASSIGN_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when an assignment of a simple dense vector can be executed
+// in parallel. In case the number of elements of the target vector is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of elements is below this
+// threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DVECASSIGN_DEBUG_THRESHOLD = 32UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector addition threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DVECDVECADD_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense vector/dense vector addition can be executed
+// in parallel. In case the number of elements of the target vector is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of elements is below this
+// threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DVECDVECADD_DEBUG_THRESHOLD = 32UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector subtraction threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DVECDVECSUB_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense vector/dense vector subtraction can be executed
+// in parallel. In case the number of elements of the target vector is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of elements is below this
+// threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DVECDVECSUB_DEBUG_THRESHOLD = 32UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DVECDVECMULT_USER_THRESHOLD while the
+// Blaze debug mode is active. It specifies when a dense vector/dense vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger
+// or equal to this threshold, the operation is executed in parallel. If the number of elements
+// is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DVECDVECMULT_DEBUG_THRESHOLD = 32UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector division threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DVECDVECDIV_USER_THRESHOLD while the
+// Blaze debug mode is active. It specifies when a dense vector/dense vector division can be
+// executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements
+// is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DVECDVECDIV_DEBUG_THRESHOLD = 32UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/scalar multiplication/division threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DVECSCALARMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense vector/scalar multiplication/division can be
+// executed in parallel. In case the number of elements of the target vector is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of elements is below
+// this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DVECSCALARMULT_DEBUG_THRESHOLD = 32UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATDVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/dense vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATDVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDMATDVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major dense matrix/dense vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDMATDVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDVECDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense vector/row-major dense matrix multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDVECDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDVECTDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense vector/column-major dense matrix multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDVECTDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/sparse vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATSVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/sparse vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATSVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/sparse vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDMATSVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major dense matrix/sparse vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDMATSVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP sparse vector/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSVECDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a sparse vector/row-major dense matrix multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSVECDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP sparse vector/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSVECTDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a sparse vector/column-major dense matrix multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSVECTDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_SMATDVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major sparse matrix/dense vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_SMATDVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/dense vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSMATDVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major sparse matrix/dense vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSMATDVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDVECSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense vector/row-major sparse matrix multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDVECSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDVECTSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense vector/column-major sparse matrix multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDVECTSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/sparse vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_SMATSVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major sparse matrix/sparse vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_SMATSVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/sparse vector multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSMATSVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major sparse matrix/sparse vector multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSMATSVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP sparse vector/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSVECSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a sparse vector/row-major sparse matrix multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSVECSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP sparse vector/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSVECTSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a sparse vector/column-major sparse matrix multiplication
+// can be executed in parallel. In case the number of elements of the target vector is larger or
+// equal to this threshold, the operation is executed in parallel. If the number of elements is
+// below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSVECTSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense matrix assignment threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATASSIGN_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when an assignment with a simple dense matrix can be executed
+// in parallel. In case the number of rows/columns of the target matrix is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of rows/columns is below this
+// threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATASSIGN_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/row-major dense matrix addition threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATDMATADD_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/row-major dense matrix addition
+// can be executed in parallel. This threshold affects both additions between two row-major matrices
+// or two column-major dense matrices. In case the number of rows/columns of the target matrix is
+// larger or equal to this threshold, the operation is executed in parallel. If the number of
+// rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATDMATADD_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/column-major dense matrix addition threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATTDMATADD_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/column-major dense matrix
+// addition can be executed in parallel. This threshold affects both additions between a row-major
+// matrix and a column-major matrix and a column-major matrix and a row-major matrix. In case the
+// number of rows/columns of the target matrix is larger or equal to this threshold, the operation
+// is executed in parallel. If the number of rows/columns is below this threshold the operation is
+// executed single-threaded.
+*/
+constexpr size_t SMP_DMATTDMATADD_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/row-major dense matrix subtraction threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATDMATSUB_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/row-major dense matrix
+// subtraction can be executed in parallel. This threshold affects both subtractions between two
+// row-major matrices or two column-major dense matrices. In case the number of rows/columns of
+// the target matrix is larger or equal to this threshold, the operation is executed in parallel.
+// If the number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATDMATSUB_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/column-major dense matrix subtraction threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATTDMATSUB_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/column-major dense matrix
+// subtraction can be executed in parallel. This threshold affects both subtractions between a
+// row-major matrix and a column-major matrix and a column-major matrix and a row-major matrix.
+// In case the number of rows/columns of the target matrix is larger or equal to this threshold,
+// the operation is executed in parallel. If the number of rows/columns is below this threshold
+// the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATTDMATSUB_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense matrix/scalar multiplication/division threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATSCALARMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense matrix/scalar multiplication or division can be
+// executed in parallel. In case the number of rows/columns of the target matrix is larger or equal
+// to this threshold, the operation is executed in parallel. If the number of rows/columns is below
+// this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATSCALARMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATDMATMULT_USER_THRESHOLD while the
+// Blaze debug mode is active. It specifies when a row-major dense matrix/row-major dense matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATTDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/column-major dense matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATTDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDMATDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major dense matrix/row-major dense matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDMATDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDMATTDMATMULT_USER_THRESHOLD while the
+// Blaze debug mode is active. It specifies when a column-major dense matrix/column-major dense
+// matrix multiplication can be executed in parallel. In case the number of rows/columns of the
+// target matrix is larger or equal to this threshold, the operation is executed in parallel. If
+// the number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDMATTDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/row-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major dense matrix/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DMATTSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major dense matrix/column-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DMATTSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDMATSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major dense matrix/row-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDMATSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major dense matrix/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TDMATTSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major dense matrix/column-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TDMATTSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_SMATDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major sparse matrix/row-major dense matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_SMATDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_SMATTDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major sparse matrix/column-major dense matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_SMATTDMATMULT_DEBUG_THRESHOLD = 72UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/row-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSMATDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major sparse matrix/row-major dense matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSMATDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/column-major dense matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSMATTDMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major sparse matrix/column-major dense matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSMATTDMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_SMATSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major sparse matrix/row-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_SMATSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP row-major sparse matrix/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_SMATTSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a row-major sparse matrix/column-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_SMATTSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/row-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSMATSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major sparse matrix/row-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSMATSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP column-major sparse matrix/column-major sparse matrix multiplication threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_TSMATTSMATMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a column-major sparse matrix/column-major sparse matrix
+// multiplication can be executed in parallel. In case the number of rows/columns of the target
+// matrix is larger or equal to this threshold, the operation is executed in parallel. If the
+// number of rows/columns is below this threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_TSMATTSMATMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief SMP dense vector/dense vector outer product threshold.
+// \ingroup config
+//
+// This debug value is used instead of the blaze::SMP_DVECTDVECMULT_USER_THRESHOLD while the Blaze
+// debug mode is active. It specifies when a dense vector/dense vector outer product can be executed
+// in parallel. In case the number of rows/columns of the target matrix is larger or equal to this
+// threshold, the operation is executed in parallel. If the number of rows/columns is below this
+// threshold the operation is executed single-threaded.
+*/
+constexpr size_t SMP_DVECTDVECMULT_DEBUG_THRESHOLD = 16UL;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+constexpr size_t SMP_DVECASSIGN_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DVECASSIGN_DEBUG_THRESHOLD : SMP_DVECASSIGN_USER_THRESHOLD );
+constexpr size_t SMP_DVECDVECADD_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DVECDVECADD_DEBUG_THRESHOLD : SMP_DVECDVECADD_USER_THRESHOLD );
+constexpr size_t SMP_DVECDVECSUB_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DVECDVECSUB_DEBUG_THRESHOLD : SMP_DVECDVECSUB_USER_THRESHOLD );
+constexpr size_t SMP_DVECDVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DVECDVECMULT_DEBUG_THRESHOLD : SMP_DVECDVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_DVECDVECDIV_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DVECDVECDIV_DEBUG_THRESHOLD : SMP_DVECDVECDIV_USER_THRESHOLD );
+constexpr size_t SMP_DVECSCALARMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DVECSCALARMULT_DEBUG_THRESHOLD : SMP_DVECSCALARMULT_USER_THRESHOLD );
+constexpr size_t SMP_DMATDVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATDVECMULT_DEBUG_THRESHOLD : SMP_DMATDVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDMATDVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDMATDVECMULT_DEBUG_THRESHOLD : SMP_TDMATDVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDVECDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDVECDMATMULT_DEBUG_THRESHOLD : SMP_TDVECDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDVECTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDVECTDMATMULT_DEBUG_THRESHOLD : SMP_TDVECTDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_DMATSVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATSVECMULT_DEBUG_THRESHOLD : SMP_DMATSVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDMATSVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDMATSVECMULT_DEBUG_THRESHOLD : SMP_TDMATSVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSVECDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSVECDMATMULT_DEBUG_THRESHOLD : SMP_TSVECDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSVECTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSVECTDMATMULT_DEBUG_THRESHOLD : SMP_TSVECTDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_SMATDVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_SMATDVECMULT_DEBUG_THRESHOLD : SMP_SMATDVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSMATDVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSMATDVECMULT_DEBUG_THRESHOLD : SMP_TSMATDVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDVECSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDVECSMATMULT_DEBUG_THRESHOLD : SMP_TDVECSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDVECTSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDVECTSMATMULT_DEBUG_THRESHOLD : SMP_TDVECTSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_SMATSVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_SMATSVECMULT_DEBUG_THRESHOLD : SMP_SMATSVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSMATSVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSMATSVECMULT_DEBUG_THRESHOLD : SMP_TSMATSVECMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSVECSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSVECSMATMULT_DEBUG_THRESHOLD : SMP_TSVECSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSVECTSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSVECTSMATMULT_DEBUG_THRESHOLD : SMP_TSVECTSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_DMATASSIGN_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATASSIGN_DEBUG_THRESHOLD : SMP_DMATASSIGN_USER_THRESHOLD );
+constexpr size_t SMP_DMATDMATADD_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATDMATADD_DEBUG_THRESHOLD : SMP_DMATDMATADD_USER_THRESHOLD );
+constexpr size_t SMP_DMATTDMATADD_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATTDMATADD_DEBUG_THRESHOLD : SMP_DMATTDMATADD_USER_THRESHOLD );
+constexpr size_t SMP_DMATDMATSUB_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATDMATSUB_DEBUG_THRESHOLD : SMP_DMATDMATSUB_USER_THRESHOLD );
+constexpr size_t SMP_DMATTDMATSUB_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATTDMATSUB_DEBUG_THRESHOLD : SMP_DMATTDMATSUB_USER_THRESHOLD );
+constexpr size_t SMP_DMATSCALARMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATSCALARMULT_DEBUG_THRESHOLD : SMP_DMATSCALARMULT_USER_THRESHOLD );
+constexpr size_t SMP_DMATDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATDMATMULT_DEBUG_THRESHOLD : SMP_DMATDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_DMATTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATTDMATMULT_DEBUG_THRESHOLD : SMP_DMATTDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDMATDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDMATDMATMULT_DEBUG_THRESHOLD : SMP_TDMATDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDMATTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDMATTDMATMULT_DEBUG_THRESHOLD : SMP_TDMATTDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_DMATSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATSMATMULT_DEBUG_THRESHOLD : SMP_DMATSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_DMATTSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DMATTSMATMULT_DEBUG_THRESHOLD : SMP_DMATTSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDMATSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDMATSMATMULT_DEBUG_THRESHOLD : SMP_TDMATSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TDMATTSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TDMATTSMATMULT_DEBUG_THRESHOLD : SMP_TDMATTSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_SMATDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_SMATDMATMULT_DEBUG_THRESHOLD : SMP_SMATDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_SMATTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_SMATTDMATMULT_DEBUG_THRESHOLD : SMP_SMATTDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSMATDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSMATDMATMULT_DEBUG_THRESHOLD : SMP_TSMATDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSMATTDMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSMATTDMATMULT_DEBUG_THRESHOLD : SMP_TSMATTDMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_SMATSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_SMATSMATMULT_DEBUG_THRESHOLD : SMP_SMATSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_SMATTSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_SMATTSMATMULT_DEBUG_THRESHOLD : SMP_SMATTSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSMATSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSMATSMATMULT_DEBUG_THRESHOLD : SMP_TSMATSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_TSMATTSMATMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_TSMATTSMATMULT_DEBUG_THRESHOLD : SMP_TSMATTSMATMULT_USER_THRESHOLD );
+constexpr size_t SMP_DVECTDVECMULT_THRESHOLD = ( BLAZE_DEBUG_MODE ? SMP_DVECTDVECMULT_DEBUG_THRESHOLD : SMP_DVECTDVECMULT_USER_THRESHOLD );
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( blaze::DMATDVECMULT_THRESHOLD > 0UL );
+BLAZE_STATIC_ASSERT( blaze::TDMATDVECMULT_THRESHOLD > 0UL );
+BLAZE_STATIC_ASSERT( blaze::TDVECDMATMULT_THRESHOLD > 0UL );
+BLAZE_STATIC_ASSERT( blaze::TDVECTDMATMULT_THRESHOLD > 0UL );
+BLAZE_STATIC_ASSERT( blaze::DMATDMATMULT_THRESHOLD > 0UL );
+BLAZE_STATIC_ASSERT( blaze::DMATTDMATMULT_THRESHOLD > 0UL );
+BLAZE_STATIC_ASSERT( blaze::TDMATDMATMULT_THRESHOLD > 0UL );
+BLAZE_STATIC_ASSERT( blaze::TDMATTDMATMULT_THRESHOLD > 0UL );
+
+BLAZE_STATIC_ASSERT( blaze::SMP_DVECASSIGN_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DVECDVECADD_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DVECDVECSUB_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DVECDVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DVECSCALARMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATDVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDMATDVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDVECDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDVECTDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATSVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDMATSVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSVECDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSVECTDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_SMATDVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSMATDVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDVECSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDVECTSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_SMATSVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSMATSVECMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSVECSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSVECTSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATASSIGN_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATDMATADD_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATTDMATADD_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATDMATSUB_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATTDMATSUB_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATSCALARMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATTDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDMATDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDMATTDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DMATTSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDMATSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TDMATTSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_SMATDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_SMATTDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSMATDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSMATTDMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_SMATSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_SMATTSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSMATSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_TSMATTSMATMULT_THRESHOLD >= 0UL );
+BLAZE_STATIC_ASSERT( blaze::SMP_DVECTDVECMULT_THRESHOLD >= 0UL );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/TransposeFlag.h b/src/cpu/blaze/system/TransposeFlag.h
new file mode 100644
index 00000000..4b01b672
--- /dev/null
+++ b/src/cpu/blaze/system/TransposeFlag.h
@@ -0,0 +1,56 @@
+//=================================================================================================
+/*!
+// \file blaze/system/TransposeFlag.h
+// \brief Header file for the default transpose flag for all vectors of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_TRANSPOSEFLAG_H_
+#define _BLAZE_SYSTEM_TRANSPOSEFLAG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/TransposeFlag.h>
+
+
+
+
+//=================================================================================================
+//
+// TRANSPOSE FLAG
+//
+//=================================================================================================
+
+#include <blaze/config/TransposeFlag.h>
+
+#endif
diff --git a/src/cpu/blaze/system/Vectorization.h b/src/cpu/blaze/system/Vectorization.h
new file mode 100644
index 00000000..dfeb9723
--- /dev/null
+++ b/src/cpu/blaze/system/Vectorization.h
@@ -0,0 +1,349 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Vectorization.h
+// \brief System settings for the SSE mode
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_VECTORIZATION_H_
+#define _BLAZE_SYSTEM_VECTORIZATION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/config/Vectorization.h>
+#include <blaze/util/StaticAssert.h>
+
+
+
+
+//=================================================================================================
+//
+// AVX2 ENFORCEMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#ifdef BLAZE_ENFORCE_AVX2
+# ifndef BLAZE_ENFORCE_AVX
+# define BLAZE_ENFORCE_AVX
+# endif
+# ifndef __AVX2__
+# define __AVX2__
+# endif
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// AVX ENFORCEMENT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+#ifdef BLAZE_ENFORCE_AVX
+# ifndef __MMX__
+# define __MMX__
+# endif
+# ifndef __SSE__
+# define __SSE__
+# endif
+# ifndef __SSE2__
+# define __SSE2__
+# endif
+# ifndef __SSE3__
+# define __SSE3__
+# endif
+# ifndef __SSSE3__
+# define __SSSE3__
+# endif
+# ifndef __SSE4_1__
+# define __SSE4_1__
+# endif
+# ifndef __SSE4_2__
+# define __SSE4_2__
+# endif
+# ifndef __AVX__
+# define __AVX__
+# endif
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SSE/AVX/MIC MODE CONFIGURATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the SSE mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the SSE mode. In case the SSE mode is enabled
+// (i.e. in case SSE functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by SSE intrinsics. In case the SSE mode is disabled, the
+// Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && ( defined(__SSE__) || ( _M_IX86_FP > 0 ) )
+# define BLAZE_SSE_MODE 1
+#else
+# define BLAZE_SSE_MODE 0
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the SSE2 mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the SSE2 mode. In case the SSE2 mode is enabled
+// (i.e. in case SSE2 functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by SSE2 intrinsics. In case the SSE2 mode is disabled, the
+// Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && ( defined(__SSE2__) || ( _M_IX86_FP > 1 ) )
+# define BLAZE_SSE2_MODE 1
+#else
+# define BLAZE_SSE2_MODE 0
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the SSE3 mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the SSE3 mode. In case the SSE3 mode is enabled
+// (i.e. in case SSE3 functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by SSE3 intrinsics. In case the SSE3 mode is disabled, the
+// Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && defined(__SSE3__)
+# define BLAZE_SSE3_MODE 1
+#else
+# define BLAZE_SSE3_MODE 0
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the SSSE3 mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the SSSE3 mode. In case the SSSE3 mode is enabled
+// (i.e. in case SSSE3 functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by SSSE3 intrinsics. In case the SSSE3 mode is disabled, the
+// Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && defined(__SSSE3__)
+# define BLAZE_SSSE3_MODE 1
+#else
+# define BLAZE_SSSE3_MODE 0
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the SSE4 mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the SSE4 mode. In case the SSE4 mode is enabled
+// (i.e. in case SSE4 functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by SSE4 intrinsics. In case the SSE4 mode is disabled,
+// the Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && ( defined(__SSE4_2__) || defined(__SSE4_1__) )
+# define BLAZE_SSE4_MODE 1
+#else
+# define BLAZE_SSE4_MODE 0
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the AVX mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the AVX mode. In case the AVX mode is enabled
+// (i.e. in case AVX functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by AVX intrinsics. In case the AVX mode is disabled,
+// the Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && defined(__AVX__)
+# define BLAZE_AVX_MODE 1
+#else
+# define BLAZE_AVX_MODE 0
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the AVX2 mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the AVX2 mode. In case the AVX2 mode is enabled
+// (i.e. in case AVX2 functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by AVX2 intrinsics. In case the AVX2 mode is disabled,
+// the Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && defined(__AVX2__)
+# define BLAZE_AVX2_MODE 1
+#else
+# define BLAZE_AVX2_MODE 0
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the MIC mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the MIC mode. In case the MIC mode is enabled
+// (i.e. in case MIC functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by MIC intrinsics. In case the MIC mode is disabled,
+// the Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && defined(__MIC__)
+# define BLAZE_MIC_MODE 1
+#else
+# define BLAZE_MIC_MODE 0
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// FMA MODE CONFIGURATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the FMA mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the FMA mode. In case the FMA mode is enabled
+// (i.e. in case FMA functionality is available) the Blaze library attempts to vectorize
+// the linear algebra operations by FMA intrinsics. In case the FMA mode is disabled,
+// the Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && defined(__FMA__)
+# define BLAZE_FMA_MODE 1
+#else
+# define BLAZE_FMA_MODE 0
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SVML MODE CONFIGURATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compilation switch for the SVML mode.
+// \ingroup system
+//
+// This compilation switch enables/disables the SVML mode. In case the SVML mode is enabled
+// (i.e. in case an Intel compiler is used) the Blaze library attempts to vectorize several
+// linear algebra operations by SVML intrinsics. In case the SVML mode is disabled, the
+// Blaze library chooses default, non-vectorized functionality for the operations.
+*/
+#if BLAZE_USE_VECTORIZATION && ( defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) )
+# define BLAZE_SVML_MODE 1
+#else
+# define BLAZE_SVML_MODE 0
+#endif
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// COMPILE TIME CONSTRAINTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+namespace {
+
+BLAZE_STATIC_ASSERT( !BLAZE_SSE2_MODE || BLAZE_SSE_MODE );
+BLAZE_STATIC_ASSERT( !BLAZE_SSE3_MODE || BLAZE_SSE2_MODE );
+BLAZE_STATIC_ASSERT( !BLAZE_SSSE3_MODE || BLAZE_SSE3_MODE );
+BLAZE_STATIC_ASSERT( !BLAZE_SSE4_MODE || BLAZE_SSSE3_MODE );
+BLAZE_STATIC_ASSERT( !BLAZE_AVX_MODE || BLAZE_SSE4_MODE );
+BLAZE_STATIC_ASSERT( !BLAZE_AVX2_MODE || BLAZE_AVX_MODE );
+
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SSE/AVX/MIC INCLUDE FILE CONFIGURATION
+//
+//=================================================================================================
+
+#if BLAZE_MIC_MODE || BLAZE_AVX_MODE || BLAZE_AVX2_MODE
+# include <immintrin.h>
+#elif BLAZE_SSE4_MODE
+# include <smmintrin.h>
+#elif BLAZE_SSSE3_MODE
+# include <tmmintrin.h>
+#elif BLAZE_SSE3_MODE
+# include <pmmintrin.h>
+#elif BLAZE_SSE2_MODE
+# include <emmintrin.h>
+#elif BLAZE_SSE_MODE
+# include <xmmintrin.h>
+#endif
+
+#endif
diff --git a/src/cpu/blaze/system/Version.h b/src/cpu/blaze/system/Version.h
new file mode 100644
index 00000000..db9b1f79
--- /dev/null
+++ b/src/cpu/blaze/system/Version.h
@@ -0,0 +1,66 @@
+//=================================================================================================
+/*!
+// \file blaze/system/Version.h
+// \brief Header file for the current version of the Blaze library
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_VERSION_H_
+#define _BLAZE_SYSTEM_VERSION_H_
+
+
+//=================================================================================================
+//
+// BLAZE VERSION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Major version of the Blaze library.
+// \ingroup system
+//
+// This value corresponds to the major version of the Blaze library. For instance, for Blaze
+// version 2.6, the BLAZE_MAJOR_VERSION corresponds to 2.
+*/
+#define BLAZE_MAJOR_VERSION 2
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Minor version of the Blaze library.
+// \ingroup system
+//
+// This value corresponds to the minor version of the Blaze library. For instance, for Blaze
+// version 2.6, the BLAZE_MINOR_VERSION corresponds to 6.
+*/
+#define BLAZE_MINOR_VERSION 6
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/system/WarningDisable.h b/src/cpu/blaze/system/WarningDisable.h
new file mode 100644
index 00000000..63ce709d
--- /dev/null
+++ b/src/cpu/blaze/system/WarningDisable.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/system/WarningDisable.h
+// \brief Deactivation of compiler specific warnings
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_SYSTEM_WARNINGDISABLE_H_
+#define _BLAZE_SYSTEM_WARNINGDISABLE_H_
+
+
+//=================================================================================================
+//
+// MICROSOFT VISUAL STUDIO WARNINGS
+//
+//=================================================================================================
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+
+ // Disables a 'deprecated' warning for some standard library functions. This warning
+ // is emitted when you use some perfectly conforming library functions in a perfectly
+ // correct way, and also by some of Microsoft's own standard library code. For more
+ // information about this particular warning, see
+ // http://msdn.microsoft.com/en-us/library/ttcz0bys(VS.80).aspx
+# pragma warning(disable:4996)
+
+ // Disables a warning for a this pointer that is passed to a base class in the constructor
+ // initializer list.
+# pragma warning(disable:4355)
+
+ // Disables the warning for ignored C++ exception specifications.
+# pragma warning(disable:4290)
+
+#endif
+
+
+
+
+//=================================================================================================
+//
+// INTEL WARNINGS
+//
+//=================================================================================================
+
+#if defined(__INTEL_COMPILER) || defined(__ICL)
+
+ // Disables a 'deprecated' warning for some standard library functions.
+# pragma warning(disable:1786)
+
+#endif
+
+#endif
diff --git a/src/cpu/blaze/util/Algorithm.h b/src/cpu/blaze/util/Algorithm.h
new file mode 100644
index 00000000..ca1538e8
--- /dev/null
+++ b/src/cpu/blaze/util/Algorithm.h
@@ -0,0 +1,150 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Algorithm.h
+// \brief Headerfile for generic algorithms
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_ALGORITHM_H_
+#define _BLAZE_UTIL_ALGORITHM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+#include <blaze/util/constraints/DerivedFrom.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsAssignable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// TRANSFER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Transfers the elements from the given source range to the destination range.
+//
+// \param first Iterator to the first element of the source range.
+// \param last Iterator to the element one past the last element of the source range.
+// \param dest Iterator to the first element of the destination range.
+// \return Output iterator to the element one past the last copied element.
+//
+// This function transfers the elements in the range \f$ [first,last) \f$ to the specified
+// destination range. In case the elements provide a no-throw move assignment, the transfer
+// operation is handled via move. Else the elements are copied.
+*/
+template< typename InputIterator
+ , typename OutputIterator >
+OutputIterator transfer( InputIterator first, InputIterator last, OutputIterator dest )
+{
+ using ValueType = typename std::iterator_traits<InputIterator>::value_type;
+
+ if( IsNothrowMoveAssignable<ValueType>::value ) {
+ return std::move( first, last, dest );
+ }
+ else {
+ return std::copy( first, last, dest );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// POLYMORPHIC COUNT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Counts the pointer to objects with dynamic type \a D.
+//
+// \param first Iterator to the first pointer of the pointer range.
+// \param last Iterator to the pointer one past the last pointer of the pointer range.
+// \return The number of objects with dynamic type \a D.
+//
+// This function traverses the range \f$ [first,last) \f$ of pointers to objects with static
+// type \a S and counts all polymorphic pointers to objects of dynamic type \a D. Note that
+// in case \a D is not a type derived from \a S, a compile time error is created!
+*/
+template< typename D // Dynamic type of the objects
+ , typename S > // Static type of the objects
+inline size_t polymorphicCount( S *const * first, S *const * last )
+{
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_DERIVED_FROM( D, S );
+
+ size_t count( 0 );
+ for( S *const * it=first; it!=last; ++it )
+ if( dynamic_cast<D*>( *it ) ) ++count;
+ return count;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// POLYMORPHIC FIND
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Finds the next pointer to an object with dynamic type \a D.
+//
+// \param first Iterator to the first pointer of the pointer range.
+// \param last Iterator to the pointer one past the last pointer of the pointer range.
+// \return The next pointer to an object with dynamic type \a D.
+//
+// This function traverses the range \f$ [first,last) \f$ of pointers to objects with static
+// type \a S until it finds the next polymorphic pointer to an object of dynamic type \a D.
+// Note that in case \a D is not a type derived from \a S, a compile time error is created!
+*/
+template< typename D // Dynamic type of the objects
+ , typename S > // Static type of the objects
+inline S *const * polymorphicFind( S *const * first, S *const * last )
+{
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_DERIVED_FROM( D, S );
+
+ while( first != last && !dynamic_cast<D*>( *first ) ) ++first;
+ return first;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/AlignedAllocator.h b/src/cpu/blaze/util/AlignedAllocator.h
new file mode 100644
index 00000000..f203736f
--- /dev/null
+++ b/src/cpu/blaze/util/AlignedAllocator.h
@@ -0,0 +1,387 @@
+//=================================================================================================
+/*!
+// \file blaze/util/AlignedAllocator.h
+// \brief Header file for the AlignedAllocator implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_ALIGNEDALLOCATOR_H_
+#define _BLAZE_UTIL_ALIGNEDALLOCATOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Memory.h>
+#include <blaze/util/typetraits/AlignmentOf.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Allocator for type-specific aligned memory.
+// \ingroup util
+//
+// The AlignedAllocator class template represents an implementation of the allocator concept of
+// the standard library for the allocation of type-specific, aligned, uninitialized memory. The
+// allocator performs its allocation via the blaze::allocate() and blaze::deallocate() functions
+// to guarantee properly aligned memory based on the alignment restrictions of the specified type
+// \a Type. For instance, in case the given type is a fundamental, built-in data type and in case
+// SSE vectorization is possible, the returned memory is guaranteed to be at least 16-byte aligned.
+// In case AVX is active, the memory is even guaranteed to be at least 32-byte aligned.
+*/
+template< typename Type >
+class AlignedAllocator
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef Type ValueType; //!< Type of the allocated values.
+ typedef Type* Pointer; //!< Type of a pointer to the allocated values.
+ typedef const Type* ConstPointer; //!< Type of a pointer-to-const to the allocated values.
+ typedef Type& Reference; //!< Type of a reference to the allocated values.
+ typedef const Type& ConstReference; //!< Type of a reference-to-const to the allocated values.
+ typedef std::size_t SizeType; //!< Size type of the aligned allocator.
+ typedef std::ptrdiff_t DifferenceType; //!< Difference type of the aligned allocator.
+
+ // STL allocator requirements
+ typedef ValueType value_type; //!< Type of the allocated values.
+ typedef Pointer pointer; //!< Type of a pointer to the allocated values.
+ typedef ConstPointer const_pointer; //!< Type of a pointer-to-const to the allocated values.
+ typedef Reference reference; //!< Type of a reference to the allocated values.
+ typedef ConstReference const_reference; //!< Type of a reference-to-const to the allocated values.
+ typedef SizeType size_type; //!< Size type of the aligned allocator.
+ typedef DifferenceType difference_type; //!< Difference type of the aligned allocator.
+ //**********************************************************************************************
+
+ //**rebind class definition*********************************************************************
+ /*!\brief Implementation of the AlignedAllocator rebind mechanism.
+ */
+ template< typename Type2 >
+ struct rebind
+ {
+ typedef AlignedAllocator<Type2> other; //!< Type of the other allocator.
+ };
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline AlignedAllocator();
+
+ template< typename Type2 >
+ inline AlignedAllocator( const AlignedAllocator<Type2>& );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline constexpr size_t max_size() const noexcept;
+ inline Pointer address( Reference x ) const noexcept;
+ inline ConstPointer address( ConstReference x ) const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Allocation functions************************************************************************
+ /*!\name Allocation functions */
+ //@{
+ inline Pointer allocate ( size_t numObjects, const void* localityHint = nullptr );
+ inline void deallocate( Pointer ptr, size_t numObjects );
+ //@}
+ //**********************************************************************************************
+
+ //**Construction functions**********************************************************************
+ /*!\name Construction functions */
+ //@{
+ inline void construct( Pointer ptr, const Type& value );
+ inline void destroy ( Pointer ptr ) noexcept;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for AlignedAllocator.
+*/
+template< typename Type >
+inline AlignedAllocator<Type>::AlignedAllocator()
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different AlignedAllocator instances.
+//
+// \param allocator The foreign aligned allocator to be copied.
+*/
+template< typename Type >
+template< typename Type2 >
+inline AlignedAllocator<Type>::AlignedAllocator( const AlignedAllocator<Type2>& allocator )
+{
+ UNUSED_PARAMETER( allocator );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the maximum possible number of elements that can be allocated together.
+//
+// \return The maximum number of elements that can be allocated together.
+*/
+template< typename Type >
+inline constexpr size_t AlignedAllocator<Type>::max_size() const noexcept
+{
+ return size_t(-1) / sizeof( Type );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the address of the given element.
+//
+// \return The address of the given element.
+*/
+template< typename Type >
+inline typename AlignedAllocator<Type>::Pointer
+ AlignedAllocator<Type>::address( Reference x ) const noexcept
+{
+ return &x;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the address of the given element.
+//
+// \return The address of the given element.
+*/
+template< typename Type >
+inline typename AlignedAllocator<Type>::ConstPointer
+ AlignedAllocator<Type>::address( ConstReference x ) const noexcept
+{
+ return &x;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ALLOCATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Allocates aligned memory for the specified number of objects.
+//
+// \param numObjects The number of objects to be allocated.
+// \param localityHint Hint for improved locality.
+// \return Pointer to the newly allocated memory.
+//
+// This function allocates a junk of memory for the specified number of objects of type \a Type.
+// The returned pointer is guaranteed to be aligned according to the alignment restrictions of
+// the data type \a Type. For instance, in case the type is a fundamental, built-in data type
+// and in case SSE vectorization is possible, the returned memory is guaranteed to be at least
+// 16-byte aligned. In case AVX is active, the memory is even guaranteed to be 32-byte aligned.
+*/
+template< typename Type >
+inline typename AlignedAllocator<Type>::Pointer
+ AlignedAllocator<Type>::allocate( size_t numObjects, const void* localityHint )
+{
+ UNUSED_PARAMETER( localityHint );
+
+ const size_t alignment( AlignmentOf<Type>::value );
+
+ if( alignment >= 8UL ) {
+ return reinterpret_cast<Type*>( allocate_backend( numObjects*sizeof(Type), alignment ) );
+ }
+ else {
+ return static_cast<Pointer>( operator new[]( numObjects * sizeof( Type ) ) );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deallocation of memory.
+//
+// \param ptr The address of the first element of the array to be deallocated.
+// \param numObjects The number of objects to be deallocated.
+// \return void
+//
+// This function deallocates a junk of memory that was previously allocated via the allocate()
+// function. Note that the argument \a numObjects must be equal ot the first argument of the call
+// to allocate() that origianlly produced \a ptr.
+*/
+template< typename Type >
+inline void AlignedAllocator<Type>::deallocate( Pointer ptr, size_t numObjects )
+{
+ UNUSED_PARAMETER( numObjects );
+
+ if( ptr == nullptr )
+ return;
+
+ const size_t alignment( AlignmentOf<Type>::value );
+
+ if( alignment >= 8UL ) {
+ deallocate_backend( ptr );
+ }
+ else {
+ operator delete[]( ptr );
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructs an object of type \a Type at the specified memory location.
+//
+// \param ptr Pointer to the allocated, uninitialized storage.
+// \param value The initialization value.
+// \return void
+//
+// This function constructs an object of type \a Type in the allocated, uninitialized storage
+// pointed to by \a ptr. This construction is performed via placement-new.
+*/
+template< typename Type >
+inline void AlignedAllocator<Type>::construct( Pointer ptr, ConstReference value )
+{
+ ::new( ptr ) Type( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Destroys the object of type \a Type at the specified memory location.
+//
+// \param ptr Pointer to the object to be destroyed.
+// \return void
+//
+// This function destroys the object at the specified memory location via a direct call to its
+// destructor.
+*/
+template< typename Type >
+inline void AlignedAllocator<Type>::destroy( Pointer ptr ) noexcept
+{
+ ptr->~Type();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name AlignedAllocator operators */
+//@{
+template< typename T1, typename T2 >
+inline bool operator==( const AlignedAllocator<T1>& lhs, const AlignedAllocator<T2>& rhs ) noexcept;
+
+template< typename T1, typename T2 >
+inline bool operator!=( const AlignedAllocator<T1>& lhs, const AlignedAllocator<T2>& rhs ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two AlignedAllocator objects.
+//
+// \param lhs The left-hand side aligned allocator.
+// \param rhs The right-hand side aligned allocator.
+// \return \a true.
+*/
+template< typename T1 // Type of the left-hand side aligned allocator
+ , typename T2 > // Type of the right-hand side aligned allocator
+inline bool operator==( const AlignedAllocator<T1>& lhs, const AlignedAllocator<T2>& rhs ) noexcept
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return true;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two AlignedAllocator objects.
+//
+// \param lhs The left-hand side aligned allocator.
+// \param rhs The right-hand side aligned allocator.
+// \return \a false.
+*/
+template< typename T1 // Type of the left-hand side aligned allocator
+ , typename T2 > // Type of the right-hand side aligned allocator
+inline bool operator!=( const AlignedAllocator<T1>& lhs, const AlignedAllocator<T2>& rhs ) noexcept
+{
+ UNUSED_PARAMETER( lhs, rhs );
+ return false;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/AlignedArray.h b/src/cpu/blaze/util/AlignedArray.h
new file mode 100644
index 00000000..83845563
--- /dev/null
+++ b/src/cpu/blaze/util/AlignedArray.h
@@ -0,0 +1,501 @@
+//=================================================================================================
+/*!
+// \file blaze/util/AlignedArray.h
+// \brief Header file for the AlignedArray implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_ALIGNEDARRAY_H_
+#define _BLAZE_UTIL_ALIGNEDARRAY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Volatile.h>
+#include <blaze/util/Exception.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/typetraits/AlignmentOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of a static array with a fixed alignment.
+// \ingroup util
+//
+// The AlignedArray class template represents a static array with a guaranteed, fixed alignment.
+// The type of the array elements, the number of elements and the alignment of the array can be
+// specified via the three template parameters:
+
+ \code
+ template< typename Type, size_t N, size_t Alignment >
+ class AlignedArray;
+ \endcode
+
+// The alignment of the array, which must be a power of two (i.e. 1, 2, 4, 8, ...), can either be
+// specified explicitly via the template parameter \a Alignment or it is evaluated automatically
+// based on the alignment requirements of the given data type \a Type. In the latter case, if
+// \a T is a built-in, vectorizable data type, AlignedArray enforces an alignment of 16 or 32
+// bytes, depending on the active SSE/AVX level. In all other cases, no specific alignment is
+// enforced.
+//
+// AlignedArray can be used exactly like any built-in static array. It is possible to access the
+// individual element via the subscript operator and the array can be used wherever a pointer is
+// expected:
+
+ \code
+ void func( const int* );
+
+ blaze::AlignedArray<int,100UL> array;
+
+ array[10] = 2; // Accessing and assigning the 10th array element
+ func( array ); // Passing the aligned array to a function expecting a pointer
+
+ blaze::AlignedArray<int,3UL> array2{ 1, 2, 3 }; // Directly initialized array
+ blaze::AlignedArray<int,3UL> array3( 1, 2, 3 ); // Same effect as above
+ \endcode
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment = AlignmentOf<Type>::value > // Array alignment
+class AlignedArray
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef Type ElementType; //!< Type of the array elements.
+ typedef Type* Pointer; //!< Pointer to a non-constant array element.
+ typedef const Type* ConstPointer; //!< Pointer to a constant array element.
+ typedef Type& Reference; //!< Reference to a non-constant array element.
+ typedef const Type& ConstReference; //!< Reference to a constant array element.
+ typedef Type* Iterator; //!< Iterator over non-constant elements.
+ typedef const Type* ConstIterator; //!< Iterator over constant elements.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline AlignedArray();
+
+ template< typename... Ts >
+ explicit inline constexpr AlignedArray( const Ts&... args );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Conversion operators************************************************************************
+ /*!\name Conversion operators */
+ //@{
+ inline operator Pointer () noexcept;
+ inline constexpr operator ConstPointer() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Data access functions***********************************************************************
+ /*!\name Data access functions */
+ //@{
+ inline Reference operator[]( size_t index ) noexcept;
+ inline constexpr ConstReference operator[]( size_t index ) const noexcept;
+ inline Reference at( size_t index );
+ inline ConstReference at( size_t index ) const;
+ inline Pointer data() noexcept;
+ inline constexpr ConstPointer data() const noexcept;
+ inline Iterator begin () noexcept;
+ inline constexpr ConstIterator begin () const noexcept;
+ inline constexpr ConstIterator cbegin() const noexcept;
+ inline Iterator end () noexcept;
+ inline constexpr ConstIterator end () const noexcept;
+ inline constexpr ConstIterator cend () const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline constexpr size_t size() const noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ /*!\name Member variables */
+ //@{
+ alignas( Alignment ) Type v_[N]; //!< The aligned array of size N.
+ //@}
+ /*! \endcond */
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
+ BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE( Type );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for AlignedArray.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline AlignedArray<Type,N,Alignment>::AlignedArray()
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Initialization constructor for AlignedArray.
+//
+// \param args Pack of initialization values.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+template< typename... Ts > // Types of the array initializers
+inline constexpr AlignedArray<Type,N,Alignment>::AlignedArray( const Ts&... args )
+ : v_{ args... }
+{
+ BLAZE_STATIC_ASSERT( sizeof...( Ts ) == N );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to a pointer.
+//
+// \return The raw pointer of the aligned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline AlignedArray<Type,N,Alignment>::operator Pointer() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion operator to a pointer-to-const.
+//
+// \return The raw pointer of the aligned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline constexpr AlignedArray<Type,N,Alignment>::operator ConstPointer() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DATA ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the array elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+//
+// \note This operator does not perform any kind of index check!
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline typename AlignedArray<Type,N,Alignment>::Reference
+ AlignedArray<Type,N,Alignment>::operator[]( size_t index ) noexcept
+{
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the array elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference-to-const to the accessed value.
+//
+// \note This operator does not perform any kind of index check!
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline constexpr typename AlignedArray<Type,N,Alignment>::ConstReference
+ AlignedArray<Type,N,Alignment>::operator[]( size_t index ) const noexcept
+{
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the array elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid array access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline typename AlignedArray<Type,N,Alignment>::Reference
+ AlignedArray<Type,N,Alignment>::at( size_t index )
+{
+ if( index >= N ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" );
+ }
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checked access to the array elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
+// \return Reference to the accessed value.
+// \exception std::out_of_range Invalid array access index.
+//
+// In contrast to the subscript operator this function always performs a check of the given
+// access index.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline typename AlignedArray<Type,N,Alignment>::ConstReference
+ AlignedArray<Type,N,Alignment>::at( size_t index ) const
+{
+ if( index >= N ) {
+ BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" );
+ }
+ return v_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the array elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the aligned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline typename AlignedArray<Type,N,Alignment>::Pointer
+ AlignedArray<Type,N,Alignment>::data() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Low-level data access to the array elements.
+//
+// \return Pointer to the internal element storage.
+//
+// This function returns a pointer to the internal storage of the aligned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline constexpr typename AlignedArray<Type,N,Alignment>::ConstPointer
+ AlignedArray<Type,N,Alignment>::data() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the aligned array.
+//
+// \return Iterator to the first element of the aigned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline typename AlignedArray<Type,N,Alignment>::Iterator
+ AlignedArray<Type,N,Alignment>::begin() noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the aligned array.
+//
+// \return Iterator to the first element of the aigned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline constexpr typename AlignedArray<Type,N,Alignment>::ConstIterator
+ AlignedArray<Type,N,Alignment>::begin() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of the aligned array.
+//
+// \return Iterator to the first element of the aigned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline constexpr typename AlignedArray<Type,N,Alignment>::ConstIterator
+ AlignedArray<Type,N,Alignment>::cbegin() const noexcept
+{
+ return v_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the aligned array.
+//
+// \return Iterator just past the last element of the aligned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline typename AlignedArray<Type,N,Alignment>::Iterator
+ AlignedArray<Type,N,Alignment>::end() noexcept
+{
+ return v_ + N;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the aligned array.
+//
+// \return Iterator just past the last element of the aligned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline constexpr typename AlignedArray<Type,N,Alignment>::ConstIterator
+ AlignedArray<Type,N,Alignment>::end() const noexcept
+{
+ return v_ + N;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the aligned array.
+//
+// \return Iterator just past the last element of the aligned array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline constexpr typename AlignedArray<Type,N,Alignment>::ConstIterator
+ AlignedArray<Type,N,Alignment>::cend() const noexcept
+{
+ return v_ + N;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current size/dimension of the aligned array.
+//
+// \return The size of the array.
+*/
+template< typename Type // Data type of the elements
+ , size_t N // Number of elements
+ , size_t Alignment > // Array alignment
+inline constexpr size_t AlignedArray<Type,N,Alignment>::size() const noexcept
+{
+ return N;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/AlignmentCheck.h b/src/cpu/blaze/util/AlignmentCheck.h
new file mode 100644
index 00000000..2bfba710
--- /dev/null
+++ b/src/cpu/blaze/util/AlignmentCheck.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/util/AlignmentCheck.h
+// \brief Header file for the alignment check function
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_ALIGNMENTCHECK_H_
+#define _BLAZE_UTIL_ALIGNMENTCHECK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+#include <blaze/util/Misalignment.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SIZETRAIT CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Checks the alignment of the given address.
+// \ingroup util
+//
+// \param address The address to be checked.
+// \return \a true in case the address is properly aligned, \a false if it is not.
+//
+// This function performs an alignment check on the given address. For instance, for fundamental
+// data types that can be vectorized via SSE or AVX instructions, the proper alignment is 16 or
+// 32 bytes, respectively. In case the given address is properly aligned, the function returns
+// \a true, otherwise it returns \a false.
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE bool checkAlignment( const T* address )
+{
+ return ( misalignment( address ) == 0UL );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Assert.h b/src/cpu/blaze/util/Assert.h
new file mode 100644
index 00000000..598c6a91
--- /dev/null
+++ b/src/cpu/blaze/util/Assert.h
@@ -0,0 +1,123 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Assert.h
+// \brief Header file for run time assertion macros
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_ASSERT_H_
+#define _BLAZE_UTIL_ASSERT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cassert>
+#include <blaze/system/Assertion.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// RUN TIME ASSERTION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup assert Assertions
+// \ingroup util
+*/
+/*!\defgroup runtime_assert Run time assertions
+// \ingroup assert
+*/
+/*!\brief Assertion helper function.
+// \ingroup runtime_assert
+//
+// The ASSERT_MESSAGE function is a small helper function to assist in printing an informative
+// message in case an assert fires. This function builds on the ideas of Matthew Wilson, who
+// directly combines a C-string error message with the run time expression (Imperfect C++,
+// ISBN: 0321228774):
+
+ \code
+ assert( ... && "Error message" );
+ assert( ... || !"Error message" );
+ \endcode
+
+// However, both approaches fail to compile without warning on certain compilers. Therefore
+// this inline function is used instead of the direct approaches, which circumvents all compiler
+// warnings:
+
+ \code
+ assert( ... || ASSERT_MESSAGE( "Error message" ) );
+ \endcode
+*/
+inline bool ASSERT_MESSAGE( const char* /*msg*/ )
+{
+ return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Run time assertion macro for internal checks.
+// \ingroup runtime_assert
+//
+// In case of an invalid run time expression, the program execution is terminated.\n
+// The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the \a BLAZE_USER_ASSERTION
+// flag to zero or by defining \a NDEBUG during the compilation.
+*/
+#if BLAZE_INTERNAL_ASSERTION
+# define BLAZE_INTERNAL_ASSERT(expr,msg) assert( ( expr ) || blaze::ASSERT_MESSAGE( msg ) )
+#else
+# define BLAZE_INTERNAL_ASSERT(expr,msg)
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Run time assertion macro for user checks.
+// \ingroup runtime_assert
+//
+// In case of an invalid run time expression, the program execution is terminated.\n
+// The BLAZE_USER_ASSERT macro can be disabled by setting the \a BLAZE_USER_ASSERT flag
+// to zero or by defining \a NDEBUG during the compilation.
+*/
+#if BLAZE_USER_ASSERTION
+# define BLAZE_USER_ASSERT(expr,msg) assert( ( expr ) || blaze::ASSERT_MESSAGE( msg ) )
+#else
+# define BLAZE_USER_ASSERT(expr,msg)
+#endif
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/ColorMacros.h b/src/cpu/blaze/util/ColorMacros.h
new file mode 100644
index 00000000..f39fee50
--- /dev/null
+++ b/src/cpu/blaze/util/ColorMacros.h
@@ -0,0 +1,166 @@
+//=================================================================================================
+/*!
+// \file blaze/util/ColorMacros.h
+// \brief Header file for color macros
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_COLORMACROS_H_
+#define _BLAZE_UTIL_COLORMACROS_H_
+
+
+//=================================================================================================
+//
+// COLOR MACRO SWITCH
+//
+//=================================================================================================
+
+//! pe color output mode.
+/*! This mode triggers the color output macros. */
+#define BLAZE_COLOR_OUTPUT 0
+
+
+
+
+//=================================================================================================
+//
+// COLOR MACRO DEFINITIONS
+//
+//=================================================================================================
+
+#if BLAZE_COLOR_OUTPUT
+
+//! Switches the text color to black in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_BLACK "\033[0;30m"
+
+//! Switches the text color to red in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_RED "\033[0;31m"
+
+//! Switches the text color to green in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_GREEN "\033[0;32m"
+
+//! Switches the text color to brown in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_BROWN "\033[0;33m"
+
+//! Switches the text color to blue in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_BLUE "\033[0;34m"
+
+//! Switches the text color to magenta in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_MAGENTA "\033[0;35m"
+
+//! Switches the text color to cyan in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_CYAN "\033[0;36m"
+
+//! Switches the text color to white in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_WHITE "\033[0;37m"
+
+//! Switches the text color to a light black in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTBLACK "\033[1;30m"
+
+//! Switches the text color to a light red in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTRED "\033[1;31m"
+
+//! Switches the text color to a light green in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTGREEN "\033[1;32m"
+
+//! Switches the text color to yellow in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_YELLOW "\033[1;33m"
+
+//! Switches the text color to a light blue in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTBLUE "\033[1;34m"
+
+//! Switches the text color to a light magenta in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTMAGENTA "\033[1;35m"
+
+//! Switches the text color to a light cyan in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTCYAN "\033[1;36m"
+
+//! Switches the text color to a light white in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTWHITE "\033[1;37m"
+
+//! Switches the text color back to the default color.
+#define BLAZE_OLDCOLOR "\033[0m"
+
+#else
+
+//! Switches the text color to black in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_BLACK ""
+
+//! Switches the text color to red in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_RED ""
+
+//! Switches the text color to green in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_GREEN ""
+
+//! Switches the text color to brown in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_BROWN ""
+
+//! Switches the text color to blue in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_BLUE ""
+
+//! Switches the text color to magenta in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_MAGENTA ""
+
+//! Switches the text color to cyan in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_CYAN ""
+
+//! Switches the text color to white in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_WHITE ""
+
+//! Switches the text color to a light black in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTBLACK ""
+
+//! Switches the text color to a light red in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTRED ""
+
+//! Switches the text color to a light green in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTGREEN ""
+
+//! Switches the text color to yellow in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_YELLOW ""
+
+//! Switches the text color to a light blue in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTBLUE ""
+
+//! Switches the text color to a light magenta in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTMAGENTA ""
+
+//! Switches the text color to a light cyan in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTCYAN ""
+
+//! Switches the text color to a light white in case the BLAZE_COLOR_OUTPUT macro is set.
+#define BLAZE_LIGHTWHITE ""
+
+//! Switches the text color back to the default color.
+#define BLAZE_OLDCOLOR ""
+
+#endif
+
+#endif
diff --git a/src/cpu/blaze/util/Complex.h b/src/cpu/blaze/util/Complex.h
new file mode 100644
index 00000000..a836c3f7
--- /dev/null
+++ b/src/cpu/blaze/util/Complex.h
@@ -0,0 +1,64 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Complex.h
+// \brief Header file for the complex data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_COMPLEX_H_
+#define _BLAZE_UTIL_COMPLEX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <complex>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// TYPE DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::complex
+// \brief Complex data type of the Blaze library.
+// \ingroup util
+*/
+using std::complex;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Constraints.h b/src/cpu/blaze/util/Constraints.h
new file mode 100644
index 00000000..7cc7228a
--- /dev/null
+++ b/src/cpu/blaze/util/Constraints.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Constraints.h
+// \brief Header file for compile time constraints
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_H_
+#define _BLAZE_UTIL_CONSTRAINTS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/constraints/Arithmetic.h>
+#include <blaze/util/constraints/Array.h>
+#include <blaze/util/constraints/Assignable.h>
+#include <blaze/util/constraints/BaseOf.h>
+#include <blaze/util/constraints/Boolean.h>
+#include <blaze/util/constraints/Builtin.h>
+#include <blaze/util/constraints/Class.h>
+#include <blaze/util/constraints/Comparable.h>
+#include <blaze/util/constraints/Complex.h>
+#include <blaze/util/constraints/ComplexDouble.h>
+#include <blaze/util/constraints/ComplexFloat.h>
+#include <blaze/util/constraints/Const.h>
+#include <blaze/util/constraints/Constructible.h>
+#include <blaze/util/constraints/Convertible.h>
+#include <blaze/util/constraints/DerivedFrom.h>
+#include <blaze/util/constraints/Destructible.h>
+#include <blaze/util/constraints/Double.h>
+#include <blaze/util/constraints/Empty.h>
+#include <blaze/util/constraints/Float.h>
+#include <blaze/util/constraints/FloatingPoint.h>
+#include <blaze/util/constraints/Integer.h>
+#include <blaze/util/constraints/Integral.h>
+#include <blaze/util/constraints/LongDouble.h>
+#include <blaze/util/constraints/Numeric.h>
+#include <blaze/util/constraints/Object.h>
+#include <blaze/util/constraints/Pod.h>
+#include <blaze/util/constraints/Pointer.h>
+#include <blaze/util/constraints/Rank.h>
+#include <blaze/util/constraints/Reference.h>
+#include <blaze/util/constraints/SameSize.h>
+#include <blaze/util/constraints/SameType.h>
+#include <blaze/util/constraints/Signed.h>
+#include <blaze/util/constraints/Size.h>
+#include <blaze/util/constraints/Subscriptable.h>
+#include <blaze/util/constraints/TypeRestriction.h>
+#include <blaze/util/constraints/Union.h>
+#include <blaze/util/constraints/Unsigned.h>
+#include <blaze/util/constraints/Valid.h>
+#include <blaze/util/constraints/Vectorizable.h>
+#include <blaze/util/constraints/Void.h>
+#include <blaze/util/constraints/Volatile.h>
+
+#endif
diff --git a/src/cpu/blaze/util/Convert.h b/src/cpu/blaze/util/Convert.h
new file mode 100644
index 00000000..db38fc2a
--- /dev/null
+++ b/src/cpu/blaze/util/Convert.h
@@ -0,0 +1,654 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Convert.h
+// \brief Conversion functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONVERT_H_
+#define _BLAZE_UTIL_CONVERT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cstdlib>
+#include <sstream>
+#include <string>
+#include <typeinfo>
+#include <blaze/util/Exception.h>
+#include <blaze/util/NonCreatable.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TEMPLATE CASTCONVERTER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Base class for the CastConverter specializations.
+// \ingroup util
+*/
+template< typename To, typename From, int IsBase >
+struct CastConverter
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+
+//=================================================================================================
+//
+// PARTIAL TEMPLATE SPECIALIZATION OF CASTCONVERTER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Dynamic cast converter between pointers of type \a From and \a To.
+// \ingroup util
+*/
+template< typename To, typename From >
+struct CastConverter<To*,From*,0> : private NonCreatable
+{
+ public:
+ //**Conversion functions************************************************************************
+ /*!\name Conversion functions */
+ //@{
+ static inline To* convert( From* from );
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Dynamic cast between pointers of type \a From and type \a To.
+//
+// \param from The pointer of type \a From to be converted.
+// \return The converted pointer of type \a To.
+*/
+template< typename To, typename From >
+inline To* CastConverter<To*,From*,0>::convert( From* from )
+{
+ return dynamic_cast<To*>( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// PARTIAL TEMPLATE SPECIALIZATION OF CASTCONVERTER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Static cast converter between pointers of type \a From and \a To.
+// \ingroup util
+*/
+template< typename To, typename From >
+struct CastConverter<To*,From*,1> : private NonCreatable
+{
+ public:
+ //**Conversion functions************************************************************************
+ /*!\name Conversion functions */
+ //@{
+ static inline To* convert( From* from );
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Static cast between pointers of type \a From and type \a To.
+//
+// \param from The pointer of type \a From to be converted.
+// \return The converted pointer of type \a To.
+*/
+template< typename To, typename From >
+inline To* CastConverter<To*,From*,1>::convert( From* from )
+{
+ return static_cast<To*>( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS TEMPLATE CONVERTER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Converter class between type \a From and type \a To.
+// \ingroup util
+*/
+template< typename To, typename From >
+struct Converter : private NonCreatable
+{
+ public:
+ //**Conversion functions************************************************************************
+ /*!\name Conversion functions */
+ //@{
+ static inline To convert( const From& from );
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from type \a From to type \a To.
+//
+// \param from The data value to be converted.
+// \return The converted data value.
+*/
+template< typename To, typename From >
+inline To Converter<To,From>::convert( const From& from )
+{
+ return static_cast<To>( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TOTAL TEMPLATE SPECIALIZATION OF CONVERTER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Converter class between pointers of type \a From and type \a To.
+// \ingroup util
+*/
+template< typename To, typename From >
+struct Converter<To*,From*> : private NonCreatable
+{
+ public:
+ //**Conversion functions************************************************************************
+ /*!\name Conversion functions */
+ //@{
+ static inline To* convert( From* from );
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion between pointers of type \a From and type \a To.
+//
+// \param from The pointer of type \a From to be converted.
+// \return The converted pointer of type \a To.
+*/
+template< typename To, typename From >
+inline To* Converter<To*,From*>::convert( From* from )
+{
+ return CastConverter<To*,From*,blaze::IsBaseOf<To,From>::yes>::convert( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// PARTIAL TEMPLATE SPECIALIZATION OF CONVERTER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Converter class between type \a std::string and type \a To.
+// \ingroup util
+*/
+template< typename To >
+struct Converter<To,std::string> : private NonCreatable
+{
+ public:
+ //**Conversion functions************************************************************************
+ /*!\name Conversion functions */
+ //@{
+ static inline To convert( const std::string& from );
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from type \a std::string to type \a To.
+//
+// \param from The \a std::string value to be converted.
+// \return The converted data value.
+*/
+template< typename To >
+inline To Converter<To,std::string>::convert( const std::string& from )
+{
+ To to;
+ std::istringstream iss( from );
+ if( !(iss >> to) ) {
+ std::ostringstream error;
+ error << "Invalid cast from std::string to " << typeid(to).name() << "\n";
+ BLAZE_THROW_RUNTIME_ERROR( error.str() );
+ }
+ return to;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// PARTIAL TEMPLATE SPECIALIZATION OF CONVERTER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Converter class between type \a From and type \a std::string.
+// \ingroup util
+*/
+template< typename From >
+struct Converter<std::string,From> : private NonCreatable
+{
+ public:
+ //**Conversion functions************************************************************************
+ /*!\name Conversion functions */
+ //@{
+ static inline std::string convert( const From& from );
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from type \a From to type \a std::string.
+//
+// \param from The data value to be converted.
+// \return The converted data value.
+*/
+template< typename From >
+inline std::string Converter<std::string,From>::convert( const From& from )
+{
+ std::ostringstream oss;
+ if( !(oss << from) ) {
+ std::ostringstream error;
+ error << "Invalid cast from " << typeid(from).name() << " to std::string\n";
+ BLAZE_THROW_RUNTIME_ERROR( error.str() );
+ }
+ return oss.str();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TOTAL TEMPLATE SPECIALIZATION OF CONVERTER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Resolution of the ambiguity for the conversion \a std::string to \a std::string
+// \ingroup util
+//
+// This converter resolves the ambiguity for the instantiation of Converter<std::string,std::string>.
+*/
+template<>
+struct Converter<std::string,std::string> : private NonCreatable
+{
+ public:
+ //**Conversion functions************************************************************************
+ /*!\name Conversion functions */
+ //@{
+ static inline std::string convert( const std::string& from );
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from \a std::string to \a std::string.
+//
+// \param from The string to be converted.
+// \return The converted string.
+*/
+inline std::string Converter<std::string,std::string>::convert( const std::string& from )
+{
+ return from;
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion from type \a From to type \a To.
+//
+// \param from The data value to be converted.
+// \return The converted data value.
+//
+// The \a convert function transforms the data value \a from of type \a From to the data type
+// \a To. The syntax for this operation is similar to the C++ cast operators. For example, in
+// order to convert a built-in integer value \p integer to a \a std::string, use
+//
+// \code convert<std::string>( integer ) \endcode
+//
+// The \a convert function supports any possible type conversion in the most efficient way.
+*/
+template< typename To, typename From >
+inline To convert( const From& from )
+{
+ return Converter<To,From>::convert( from );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a \a std::string to an integer value.
+//
+// \param from The string to be converted.
+// \return The converted integer value.
+*/
+template<>
+inline int convert<int,std::string>( const std::string& from )
+{
+ return std::atoi( from.c_str() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a \a std::string to an unsigned integer value.
+//
+// \param from The string to be converted.
+// \return The converted unsigned integer value.
+*/
+template<>
+inline unsigned int convert<unsigned int,std::string>( const std::string& from )
+{
+ return static_cast<unsigned int>( std::atoi( from.c_str() ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a \a std::string to a float value.
+//
+// \param from The string to be converted.
+// \return The converted float value.
+*/
+template<>
+inline float convert<float,std::string>( const std::string& from )
+{
+ return static_cast<float>( std::atof( from.c_str() ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a \a std::string to a double value.
+//
+// \param from The string to be converted.
+// \return The converted double value.
+*/
+template<>
+inline double convert<double,std::string>( const std::string& from )
+{
+ return std::atof( from.c_str() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a constant character array to type \a To.
+//
+// \param from The constant character array to be converted.
+// \return The converted data value.
+*/
+template< typename To >
+inline To convert( const char* const from )
+{
+ return Converter<To,std::string>::convert( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a constant character array to an integer value.
+//
+// \param from The constant character array to be converted.
+// \return The converted integer value.
+*/
+template<>
+inline int convert<int>( const char* const from )
+{
+ return std::atoi( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a constant character array to an unsigned integer value.
+//
+// \param from The constant character array to be converted.
+// \return The converted unsigned integer value.
+*/
+template<>
+inline unsigned int convert<unsigned int>( const char* const from )
+{
+ return static_cast<unsigned int>( std::atof( from ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a constant character array to a \a float value.
+//
+// \param from The constant character array to be converted.
+// \return The converted float value.
+*/
+template<>
+inline float convert<float>( const char* const from )
+{
+ return static_cast<float>( std::atof( from ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a constant character array to a \a double value.
+//
+// \param from The constant character array to be converted.
+// \return The converted double value.
+*/
+template<>
+inline double convert<double>( const char* const from )
+{
+ return std::atof( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a non-constant character array to type \a To.
+//
+// \param from The non-constant character array to be converted.
+// \return The converted data value.
+*/
+template< typename To >
+inline To convert( char* const from )
+{
+ return Converter<To,std::string>::convert( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a non-constant character array to an integer value.
+//
+// \param from The non-constant character array to be converted.
+// \return The converted integer value.
+*/
+template<>
+inline int convert<int>( char* const from )
+{
+ return std::atoi( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a non-constant character array to an unsigned integer value.
+//
+// \param from The non-constant character array to be converted.
+// \return The converted unsigned integer value.
+*/
+template<>
+inline unsigned int convert<unsigned int>( char* const from )
+{
+ return static_cast<unsigned int>( std::atoi( from ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a non-constant character array to a \a float value.
+//
+// \param from The non-constant character array to be converted.
+// \return The converted float value.
+*/
+template<>
+inline float convert<float>( char* const from )
+{
+ return static_cast<float>( std::atof( from ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Conversion from a non-constant character array to a \a double value.
+//
+// \param from The non-constant character array to be converted.
+// \return The converted double value.
+*/
+template<>
+inline double convert<double>( char* const from )
+{
+ return std::atof( from );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/DimensionOf.h b/src/cpu/blaze/util/DimensionOf.h
new file mode 100644
index 00000000..d0332b16
--- /dev/null
+++ b/src/cpu/blaze/util/DimensionOf.h
@@ -0,0 +1,101 @@
+//=================================================================================================
+/*!
+// \file blaze/util/DimensionOf.h
+// \brief Compile time evaluation of array sizes
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_DIMENSIONOF_H_
+#define _BLAZE_UTIL_DIMENSIONOF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Types.h>
+#include <blaze/util/Unused.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DIMENSIONOF FUNCTIONALITY
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper class for the dimensionof function.
+// \ingroup util
+//
+// The Array class is a helper class for the dimensionof function. It provides a public array
+// member of exactly N bytes.
+*/
+template< unsigned int N >
+struct Array {
+ byte_t array[N];
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Static evaluation of array dimensions.
+// \ingroup util
+//
+// \param a Reference to a static array of type T and size N.
+// \return Dimension of the static array.
+//
+// The dimensionof function is a safe way to evaluate the size of an array. The function only
+// works for array arguments and fails for pointers and user-defined class types.
+
+ \code
+ int ai[ 42 ];
+ int* pi( ai );
+ std::vector<int> vi( 42 );
+
+ dimensionof( ai ); // Returns the size of the integer array (42)
+ dimensionof( pi ); // Fails to compile!
+ dimensionof( vi ); // Fails to compile!
+ \endcode
+*/
+template< typename T, unsigned int N >
+inline size_t dimensionof( T(&a)[N] )
+{
+ UNUSED_PARAMETER( a );
+ return sizeof( Array<N> );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/DisableIf.h b/src/cpu/blaze/util/DisableIf.h
new file mode 100644
index 00000000..6cb09c76
--- /dev/null
+++ b/src/cpu/blaze/util/DisableIf.h
@@ -0,0 +1,228 @@
+//=================================================================================================
+/*!
+// \file blaze/util/DisableIf.h
+// \brief Header file for the DisableIf class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_DISABLEIF_H_
+#define _BLAZE_UTIL_DISABLEIF_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Substitution Failure Is Not An Error (SFINAE) class.
+// \ingroup util
+//
+// The DisableIfTrue class template is an auxiliary tool for an intentional application of the
+// Substitution Failure Is Not An Error (SFINAE) principle. It allows a function template or a
+// class template specialization to include or exclude itself from a set of matching functions
+// or specializations based on properties of its template arguments. For instance, it can be
+// used to restrict the selection of a function template to specific data types. The following
+// example illustrates this in more detail.
+
+ \code
+ template< typename Type >
+ void process( Type t ) { ... }
+ \endcode
+
+// Due to the general formulation of this function, it will always be a possible candidate for
+// every possible argument. However, with the DisableIfTrue class it is for example possible
+// to prohibit built-in, numeric data types as argument types:
+
+ \code
+ template< typename Type >
+ typename DisableIfTrue< IsNumeric<Type>::value >::Type process( Type t ) { ... }
+ \endcode
+
+// In case the given data type is a built-in, numeric data type, the access to the nested type
+// definition \a Type of the DisableIfTrue class template will fail. However, due to the SFINAE
+// principle, this will only result in a compilation error in case the compiler cannot find
+// another valid function.\n
+// Note that in this application of the DisableIfTrue template the default for the nested type
+// definition \a Type is used, which corresponds to \a void. Via the second template argument
+// it is possible to explicitly specify the type of \a Type:
+
+ \code
+ // Explicity specifying the default
+ typename DisableIfTrue< IsNumeric<Type>::value, void >::Type
+
+ // In case the given data type is not a boolean data type, the nested type definition
+ // 'Type' is set to float
+ typename DisableIfTrue< IsBoolean<Type>::value, float >::Type
+ \endcode
+
+// For more information on the DisableIfTrue/DisableIf functionality, see the Boost library
+// documentation of the enable_if family at:
+//
+// \a http://www.boost.org/doc/libs/1_60_0/libs/utility/enable_if.html.
+*/
+template< bool Condition // Compile time condition
+ , typename T=void > // The type to be instantiated
+struct DisableIfTrue
+{
+ //**********************************************************************************************
+ typedef T Type; //!< The instantiated type.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief DisableIfTrue specialization for failed constraints.
+// \ingroup util
+//
+// This specialization of the DisableIfTrue template is selected if the first template parameter
+// (the compile time condition) evaluates to \a true. This specialization does not contains a
+// nested type definition \a Type and therefore always results in a compilation error in case
+// \a Type is accessed. However, due to the SFINAE principle the compilation process is not
+// necessarily stopped if another, valid instantiation is found by the compiler.
+*/
+template< typename T > // The type to be instantiated
+struct DisableIfTrue<true,T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary type for the DisableIfTrue class template.
+// \ingroup util
+//
+// The DisableIfTrue_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the DisableIfTrue class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DisableIfTrue< IsBuiltin<T>::value >::Type;
+ using Type2 = DisableIfTrue_< IsBuiltin<T>::value >;
+ \endcode
+*/
+template< bool Condition // Compile time condition
+ , typename T=void > // The type to be instantiated
+using DisableIfTrue_ = typename DisableIfTrue<Condition,T>::Type;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Substitution Failure Is Not An Error (SFINAE) class.
+// \ingroup util
+//
+// The DisableIf class template is an auxiliary tool for an intentional application of the
+// Substitution Failure Is Not An Error (SFINAE) principle. It allows a function template
+// or a class template specialization to include or exclude itself from a set of matching
+// functions or specializations based on properties of its template arguments. For instance,
+// it can be used to restrict the selection of a function template to specific data types.
+// The following example illustrates this in more detail.
+
+ \code
+ template< typename Type >
+ void process( Type t ) { ... }
+ \endcode
+
+// Due to the general formulation of this function, it will always be a possible candidate
+// for every possible argument. However, with the DisableIf class it is for example possible
+// to prohibit built-in, numeric data types as argument types:
+
+ \code
+ template< typename Type >
+ typename DisableIf< IsNumeric<Type> >::Type process( Type t ) { ... }
+ \endcode
+
+// In case the given data type is a built-in, numeric data type, the access to the nested
+// type definition \a Type of the DisableIf class template will fail. However, due to the
+// SFINAE principle, this will only result in a compilation error in case the compiler cannot
+// find another valid function.\n
+// Note that in this application of the DisableIf template the default for the nested type
+// definition \a Type is used, which corresponds to \a void. Via the second template argument
+// it is possible to explicitly specify the type of \a Type:
+
+ \code
+ // Explicity specifying the default
+ typename DisableIf< IsNumeric<Type>, void >::Type
+
+ // In case the given data type is not a boolean data type, the nested type definition
+ // 'Type' is set to float
+ typename DisableIf< IsBoolean<Type>, float >::Type
+ \endcode
+
+// Note that in contrast to the DisableIfTrue template, the DisableIf template expects a
+// type as first template argument that has a nested type definition \a value. Therefore
+// the DisableIf template is the more convenient choice for all kinds of type traits.
+//
+// For more information on the DisableIfTrue/DisableIf functionality, see the Boost library
+// documentation of the enable_if family at:
+//
+// \a http://www.boost.org/doc/libs/1_60_0/libs/utility/enable_if.html.
+*/
+template< typename Condition // Compile time condition
+ , typename T=void > // The type to be instantiated
+struct DisableIf : public DisableIfTrue<Condition::value,T>
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary type for the DisableIf class template.
+// \ingroup util
+//
+// The DisableIf_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the DisableIf class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename DisableIf< IsBuiltin<T> >::Type;
+ using Type2 = DisableIf_< IsBuiltin<T> >;
+ \endcode
+*/
+template< typename Condition // Compile time condition
+ , typename T=void > // The type to be instantiated
+using DisableIf_ = typename DisableIf<Condition,T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/EmptyType.h b/src/cpu/blaze/util/EmptyType.h
new file mode 100644
index 00000000..659f7e54
--- /dev/null
+++ b/src/cpu/blaze/util/EmptyType.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/util/EmptyType.h
+// \brief Header file for the empty type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_EMPTYTYPE_H_
+#define _BLAZE_UTIL_EMPTYTYPE_H_
+
+
+namespace blaze {
+
+//*************************************************************************************************
+/*!\brief Empty data type for utility purposes.
+// \ingroup util
+*/
+struct EmptyType
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/EnableIf.h b/src/cpu/blaze/util/EnableIf.h
new file mode 100644
index 00000000..f7d65a76
--- /dev/null
+++ b/src/cpu/blaze/util/EnableIf.h
@@ -0,0 +1,228 @@
+//=================================================================================================
+/*!
+// \file blaze/util/EnableIf.h
+// \brief Header file for the EnableIf class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_ENABLEIF_H_
+#define _BLAZE_UTIL_ENABLEIF_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Substitution Failure Is Not An Error (SFINAE) class.
+// \ingroup util
+//
+// The EnableIfTrue class template is an auxiliary tool for an intentional application of the
+// Substitution Failure Is Not An Error (SFINAE) principle. It allows a function template or a
+// class template specialization to include or exclude itself from a set of matching functions
+// or specializations based on properties of its template arguments. For instance, it can be
+// used to restrict the selection of a function template to specific data types. The following
+// example illustrates this in more detail.
+
+ \code
+ template< typename Type >
+ void process( Type t ) { ... }
+ \endcode
+
+// Due to the general formulation of this function, it will always be a possible candidate for
+// every possible argument. However, with the EnableIfTrue class it is for example possible to
+// restrict the valid argument types to built-in, numeric data types.
+
+ \code
+ template< typename Type >
+ typename EnableIfTrue< IsNumeric<Type>::value >::Type process( Type t ) { ... }
+ \endcode
+
+// In case the given data type is not a built-in, numeric data type, the access to the nested
+// type defintion \a Type of the EnableIfTrue template will fail. However, due to the SFINAE
+// principle, this will only result in a compilation error in case the compiler cannot find
+// another valid function.\n
+// Note that in this application of the EnableIfTrue template the default for the nested type
+// definition \a Type is used, which corresponds to \a void. Via the second template argument
+// it is possible to explicitly specify the type of \a Type:
+
+ \code
+ // Explicity specifying the default
+ typename EnableIfTrue< IsNumeric<Type>::value, void >::Type
+
+ // In case the given data type is a boolean data type, the nested type definition
+ // 'Type' is set to float
+ typename EnableIfTrue< IsBoolean<Type>::value, float >::Type
+ \endcode
+
+// For more information on the EnableIfTrue/EnableIf functionality, see the Boost library
+// documentation of the enable_if family at:
+//
+// \a http://www.boost.org/doc/libs/1_60_0/libs/utility/enable_if.html.
+*/
+template< bool Condition // Compile time condition
+ , typename T=void > // The type to be instantiated
+struct EnableIfTrue
+{
+ //**********************************************************************************************
+ typedef T Type; //!< The instantiated type.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief EnableIfTrue specialization for failed constraints.
+// \ingroup util
+//
+// This specialization of the EnableIfTrue template is selected if the first template parameter
+// (the compile time condition) evaluates to \a false. This specialization does not contains a
+// nested type definition \a Type and therefore always results in a compilation error in case
+// \a Type is accessed. However, due to the SFINAE principle the compilation process is not
+// necessarily stopped if another, valid instantiation is found by the compiler.
+*/
+template< typename T > // The type to be instantiated
+struct EnableIfTrue<false,T>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary type for the EnableIfTrue class template.
+// \ingroup util
+//
+// The EnableIfTrue_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the EnableIfTrue class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename EnableIfTrue< IsBuiltin<T>::value >::Type;
+ using Type2 = EnableIfTrue_< IsBuiltin<T>::value >;
+ \endcode
+*/
+template< bool Condition // Compile time condition
+ , typename T=void > // The type to be instantiated
+using EnableIfTrue_ = typename EnableIfTrue<Condition,T>::Type;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Substitution Failure Is Not An Error (SFINAE) class.
+// \ingroup util
+//
+// The EnableIf class template is an auxiliary tool for an intentional application of the
+// Substitution Failure Is Not An Error (SFINAE) principle. It allows a function template
+// or a class template specialization to include or exclude itself from a set of matching
+// functions or specializations based on properties of its template arguments. For instance,
+// it can be used to restrict the selection of a function template to specific data types.
+// The following example illustrates this in more detail.
+
+ \code
+ template< typename Type >
+ void process( Type t ) { ... }
+ \endcode
+
+// Due to the general formulation of this function, it will always be a possible candidate
+// for every possible argument. However, with the EnableIf class it is for example possible
+// to restrict the valid argument types to built-in, numeric data types.
+
+ \code
+ template< typename Type >
+ typename EnableIf< IsNumeric<Type> >::Type process( Type t ) { ... }
+ \endcode
+
+// In case the given data type is not a built-in, numeric data type, the access to the nested
+// type defintion \a Type of the EnableIf template will fail. However, due to the SFINAE
+// principle, this will only result in a compilation error in case the compiler cannot find
+// another valid function.\n
+// Note that in this application of the EnableIf template the default for the nested type
+// definition \a Type is used, which corresponds to \a void. Via the second template argument
+// it is possible to explicitly specify the type of \a Type:
+
+ \code
+ // Explicity specifying the default
+ typename EnableIf< IsNumeric<Type>, void >::Type
+
+ // In case the given data type is a boolean data type, the nested type definition
+ // 'Type' is set to float
+ typename EnableIf< IsBoolean<Type>, float >::Type
+ \endcode
+
+// Note that in contrast to the EnableIfTrue template, the EnableIf template expects a type as
+// first template argument that has a nested type definition \a value. Therefore the EnableIf
+// template is the more convenient choice for all kinds of type traits.
+//
+// For more information on the EnableIfTrue/EnableIf functionality, see the Boost library
+// documentation of the enable_if family at:
+//
+// \a http://www.boost.org/doc/libs/1_60_0/libs/utility/enable_if.html.
+*/
+template< typename Condition // Compile time condition
+ , typename T=void > // The type to be instantiated
+struct EnableIf : public EnableIfTrue<Condition::value,T>
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the EnableIf class template.
+// \ingroup util
+//
+// The EnableIf_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the EnableIf class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename EnableIf< IsBuiltin<T> >::Type;
+ using Type2 = EnableIf_< IsBuiltin<T> >;
+ \endcode
+*/
+template< typename Condition // Compile time condition
+ , typename T=void > // The type to be instantiated
+using EnableIf_ = typename EnableIf<Condition,T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Exception.h b/src/cpu/blaze/util/Exception.h
new file mode 100644
index 00000000..e9a8ed04
--- /dev/null
+++ b/src/cpu/blaze/util/Exception.h
@@ -0,0 +1,383 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Exception.h
+// \brief Header file for exception macros
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_EXCEPTION_H_
+#define _BLAZE_UTIL_EXCEPTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <stdexcept>
+
+
+
+
+//=================================================================================================
+//
+// EXCEPTION MACROS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW
+// \brief Macro for the error reporting mechanism of the \b Blaze library.
+// \ingroup util
+//
+// This macro encapsulates the default, general way of the \b Blaze library to report errors of
+// any kind by throwing an exception. Also, since under certain conditions and environments it
+// may be desirable to replace exceptions by a different error reporting mechanism this macro
+// provides an opportunity to customize the error reporting approach.
+//
+// The macro excepts a single argument, which specifies the exception to be thrown:
+
+ \code
+ #define BLAZE_THROW( EXCEPTION ) \
+ throw EXCEPTION
+ \endcode
+
+// In order to customize the error reporing mechanism all that needs to be done is to define
+// the macro prior to including any \a Blaze header file. This will cause the \b Blaze specific
+// mechanism to be overridden. The following example demonstrates this by replacing exceptions
+// by a call to a \a log() function and a direct call to abort:
+
+ \code
+ #define BLAZE_THROW( EXCEPTION ) \
+ log( "..." ); \
+ abort()
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is possible to execute several statements instead of executing a single statement to
+// throw an exception. Also note that it is recommended to define the macro such that a subsequent
+// semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the error reporting mechanism via
+// this macro can have a significant effect on the library. Thus be advised to use the macro
+// with due care!
+*/
+#ifndef BLAZE_THROW
+# define BLAZE_THROW( EXCEPTION ) throw EXCEPTION
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW_BAD_ALLOC
+// \brief Macro for the emission of a \a std::bad_alloc exception.
+// \ingroup util
+//
+// This macro encapsulates the default way of \b Blaze to throw a \a std::bad_alloc exception.
+// Also, since it may be desirable to replace the type of exception by a custom exception type
+// this macro provides an opportunity to customize the behavior.
+
+ \code
+ #define BLAZE_THROW_BAD_ALLOC \
+ BLAZE_THROW( std::bad_alloc() )
+ \endcode
+
+// In order to customize the type of exception all that needs to be done is to define the macro
+// prior to including any \a Blaze header file. This will override the \b Blaze default behavior.
+// The following example demonstrates this by replacing \a std::bad_alloc by a custom exception
+// type:
+
+ \code
+ class BadAlloc
+ {
+ public:
+ BadAlloc();
+ // ...
+ };
+
+ #define BLAZE_THROW_BAD_ALLOC \
+ throw BadAlloc()
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is recommended to define the macro such that a subsequent semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the type of exception via this
+// macro may have an effect on the library. Thus be advised to use the macro with due care!
+*/
+#ifndef BLAZE_THROW_BAD_ALLOC
+# define BLAZE_THROW_BAD_ALLOC BLAZE_THROW( std::bad_alloc() )
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW_LOGIC_ERROR
+// \brief Macro for the emission of a \a std::logic_error exception.
+// \ingroup util
+//
+// This macro encapsulates the default way of \b Blaze to throw a \a std::logic_error exception.
+// Also, since it may be desirable to replace the type of exception by a custom exception type
+// this macro provides an opportunity to customize the behavior.
+//
+// The macro excepts a single argument, which specifies the message of the exception:
+
+ \code
+ #define BLAZE_THROW_LOGIC_ERROR( MESSAGE ) \
+ BLAZE_THROW( std::logic_error( MESSAGE ) )
+ \endcode
+
+// In order to customize the type of exception all that needs to be done is to define the macro
+// prior to including any \a Blaze header file. This will override the \b Blaze default behavior.
+// The following example demonstrates this by replacing \a std::logic_error by a custom exception
+// type:
+
+ \code
+ class LogicError
+ {
+ public:
+ LogicError();
+ explicit LogicError( const std::string& message );
+ // ...
+ };
+
+ #define BLAZE_THROW_LOGIC_ERROR( MESSAGE ) \
+ throw LogicError( MESSAGE )
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is recommended to define the macro such that a subsequent semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the type of exception via this
+// macro may have an effect on the library. Thus be advised to use the macro with due care!
+*/
+#ifndef BLAZE_THROW_LOGIC_ERROR
+# define BLAZE_THROW_LOGIC_ERROR( MESSAGE ) BLAZE_THROW( std::logic_error( MESSAGE ) )
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW_INVALID_ARGUMENT
+// \brief Macro for the emission of a \a std::invalid_argument exception.
+// \ingroup util
+//
+// This macro encapsulates the default way of \b Blaze to throw a \a std::invalid_argument
+// exception. Also, since it may be desirable to replace the type of exception by a custom
+// exception type this macro provides an opportunity to customize the behavior.
+//
+// The macro excepts a single argument, which specifies the message of the exception:
+
+ \code
+ #define BLAZE_THROW_INVALID_ARGUMENT( MESSAGE ) \
+ BLAZE_THROW( std::invalid_argument( MESSAGE ) )
+ \endcode
+
+// In order to customize the type of exception all that needs to be done is to define the macro
+// prior to including any \a Blaze header file. This will override the \b Blaze default behavior.
+// The following example demonstrates this by replacing \a std::invalid_argument by a custom
+// exception type:
+
+ \code
+ class InvalidArgument
+ {
+ public:
+ InvalidArgument();
+ explicit InvalidArgument( const std::string& message );
+ // ...
+ };
+
+ #define BLAZE_THROW_INVALID_ARGUMENT( MESSAGE ) \
+ throw InvalidArgument( MESSAGE )
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is recommended to define the macro such that a subsequent semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the type of exception via this
+// macro may have an effect on the library. Thus be advised to use the macro with due care!
+*/
+#ifndef BLAZE_THROW_INVALID_ARGUMENT
+# define BLAZE_THROW_INVALID_ARGUMENT( MESSAGE ) BLAZE_THROW( std::invalid_argument( MESSAGE ) )
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW_LENGTH_ERROR
+// \brief Macro for the emission of a \a std::length_error exception.
+// \ingroup util
+//
+// This macro encapsulates the default way of \b Blaze to throw a \a std::length_error exception.
+// Also, since it may be desirable to replace the type of exception by a custom exception type
+// this macro provides an opportunity to customize the behavior.
+//
+// The macro excepts a single argument, which specifies the message of the exception:
+
+ \code
+ #define BLAZE_THROW_LENGTH_ERROR( MESSAGE ) \
+ BLAZE_THROW( std::length_error( MESSAGE ) )
+ \endcode
+
+// In order to customize the type of exception all that needs to be done is to define the macro
+// prior to including any \a Blaze header file. This will override the \b Blaze default behavior.
+// The following example demonstrates this by replacing \a std::length_error by a custom
+// exception type:
+
+ \code
+ class LengthError
+ {
+ public:
+ LengthError();
+ explicit LengthError( const std::string& message );
+ // ...
+ };
+
+ #define BLAZE_THROW_LENGTH_ERROR( MESSAGE ) \
+ throw LengthError( MESSAGE )
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is recommended to define the macro such that a subsequent semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the type of exception via this
+// macro may have an effect on the library. Thus be advised to use the macro with due care!
+*/
+#ifndef BLAZE_THROW_LENGTH_ERROR
+# define BLAZE_THROW_LENGTH_ERROR( MESSAGE ) BLAZE_THROW( std::length_error( MESSAGE ) )
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW_OUT_OF_RANGE
+// \brief Macro for the emission of a \a std::out_of_range exception.
+// \ingroup util
+//
+// This macro encapsulates the default way of \b Blaze to throw a \a std::out_of_range exception.
+// Also, since it may be desirable to replace the type of exception by a custom exception type
+// this macro provides an opportunity to customize the behavior.
+//
+// The macro excepts a single argument, which specifies the message of the exception:
+
+ \code
+ #define BLAZE_THROW_OUT_OF_RANGE( MESSAGE ) \
+ BLAZE_THROW( std::out_of_range( MESSAGE ) )
+ \endcode
+
+// In order to customize the type of exception all that needs to be done is to define the macro
+// prior to including any \a Blaze header file. This will override the \b Blaze default behavior.
+// The following example demonstrates this by replacing \a std::out_of_range by a custom exception
+// type:
+
+ \code
+ class OutOfRange
+ {
+ public:
+ OutOfRange();
+ explicit OutOfRange( const std::string& message );
+ // ...
+ };
+
+ #define BLAZE_THROW_OUT_OF_RANGE( MESSAGE ) \
+ throw OutOfRange( MESSAGE )
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is recommended to define the macro such that a subsequent semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the type of exception via this
+// macro may have an effect on the library. Thus be advised to use the macro with due care!
+*/
+#ifndef BLAZE_THROW_OUT_OF_RANGE
+# define BLAZE_THROW_OUT_OF_RANGE( MESSAGE ) BLAZE_THROW( std::out_of_range( MESSAGE ) )
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\def BLAZE_THROW_RUNTIME_ERROR
+// \brief Macro for the emission of a \a std::runtime_error exception.
+// \ingroup util
+//
+// This macro encapsulates the default way of \b Blaze to throw a \a std::runtime_error exception.
+// Also, since it may be desirable to replace the type of exception by a custom exception type
+// this macro provides an opportunity to customize the behavior.
+//
+// The macro excepts a single argument, which specifies the message of the exception:
+
+ \code
+ #define BLAZE_THROW_RUNTIME_ERROR( MESSAGE ) \
+ BLAZE_THROW( std::runtime_error( MESSAGE ) )
+ \endcode
+
+// In order to customize the type of exception all that needs to be done is to define the macro
+// prior to including any \a Blaze header file. This will override the \b Blaze default behavior.
+// The following example demonstrates this by replacing \a std::runtime_error by a custom
+// exception type:
+
+ \code
+ class RuntimeError
+ {
+ public:
+ RuntimeError();
+ explicit RuntimeError( const std::string& message );
+ // ...
+ };
+
+ #define BLAZE_THROW_RUNTIME_ERROR( MESSAGE ) \
+ throw RuntimeError( MESSAGE )
+
+ #include <blaze/Blaze.h>
+ \endcode
+
+// \note It is recommended to define the macro such that a subsequent semicolon is required!
+//
+// \warning This macro is provided with the intention to assist in adapting \b Blaze to special
+// conditions and environments. However, the customization of the type of exception via this
+// macro may have an effect on the library. Thus be advised to use the macro with due care!
+*/
+#ifndef BLAZE_THROW_RUNTIME_ERROR
+# define BLAZE_THROW_RUNTIME_ERROR( MESSAGE ) BLAZE_THROW( std::runtime_error( MESSAGE ) )
+#endif
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/FalseType.h b/src/cpu/blaze/util/FalseType.h
new file mode 100644
index 00000000..3f35d41a
--- /dev/null
+++ b/src/cpu/blaze/util/FalseType.h
@@ -0,0 +1,66 @@
+//=================================================================================================
+/*!
+// \file blaze/util/FalseType.h
+// \brief Header file for the FalseType type/value trait base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_FALSETYPE_H_
+#define _BLAZE_UTIL_FALSETYPE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ALIAS DECLARATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Type/value traits base class.
+// \ingroup util
+//
+// The FalseType class is used as base class for type traits and value traits that evaluate to
+// \a false.
+*/
+using FalseType = BoolConstant<false>;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Indices.h b/src/cpu/blaze/util/Indices.h
new file mode 100644
index 00000000..b7166cfd
--- /dev/null
+++ b/src/cpu/blaze/util/Indices.h
@@ -0,0 +1,220 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Indices.h
+// \brief Header file for the Indices class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_INDICES_H_
+#define _BLAZE_UTIL_INDICES_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <stdexcept>
+#include <vector>
+#include <blaze/util/Exception.h>
+#include <blaze/util/Random.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Auxiliary class for the generation of random indices.
+//
+// This auxiliary class can be used to generate a set of random indices.
+*/
+class Indices
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef std::vector<size_t>::const_iterator ConstIterator; //!< Iterator over the generated indices.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline Indices( size_t min, size_t max, size_t number );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t size () const;
+ inline ConstIterator begin() const;
+ inline ConstIterator end () const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::vector<size_t> indices_; //!< The generated indices.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The constructor for the Indices class.
+//
+// \param min The lower limit of the random indices.
+// \param max The upper limit of the random indices.
+// \param number The number of random indices to generate.
+// \exception std::invalid_argument Invalid index range.
+// \exception std::invalid_argument Invalid number of indices.
+//
+// This constructor initializes an Indices object by generating \a number random, unique indices
+// in the range \a min to \a max. In case \a number is larger than the possible number of incides
+// in the specified range, a \a std::invalid_argument exception is thrown.
+*/
+inline Indices::Indices( size_t min, size_t max, size_t number )
+ : indices_() // The generated indices
+{
+ if( max < min ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range" );
+ }
+
+ const size_t maxNumber( max + 1UL - min );
+
+ if( number > maxNumber ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of indices" );
+ }
+
+ if( number == 0UL ) {
+ return;
+ }
+
+ if( number <= size_t( maxNumber * 0.5 ) )
+ {
+ indices_.reserve( number );
+
+ while( indices_.size() < number )
+ {
+ const size_t value = rand<size_t>(min,max);
+ BLAZE_INTERNAL_ASSERT( min <= value && value <= max, "Invalid index detected" );
+ const auto pos = std::lower_bound( indices_.begin(), indices_.end(), value );
+
+ if( pos == indices_.end() || *pos != value ) {
+ indices_.insert( pos, value );
+ }
+ }
+ }
+ else
+ {
+ indices_.resize( maxNumber );
+ std::iota( indices_.begin(), indices_.end(), min );
+
+ while( indices_.size() > number )
+ {
+ const size_t value = rand<size_t>(min,max);
+ BLAZE_INTERNAL_ASSERT( min <= value && value <= max, "Invalid index detected" );
+ const auto pos = std::lower_bound( indices_.begin(), indices_.end(), value );
+
+ if( pos != indices_.end() && *pos == value ) {
+ indices_.erase( pos );
+ }
+ }
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the total number of random indices.
+//
+// \return The total number of random indices.
+*/
+inline size_t Indices::size() const
+{
+ return indices_.size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the beginning of the vector.
+//
+// \return Iterator to the beginning of the vector.
+*/
+inline Indices::ConstIterator Indices::begin() const
+{
+ return indices_.begin();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the vector.
+//
+// \return Iterator just past the last element of the vector.
+*/
+inline Indices::ConstIterator Indices::end() const
+{
+ return indices_.end();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/InputString.h b/src/cpu/blaze/util/InputString.h
new file mode 100644
index 00000000..61681efe
--- /dev/null
+++ b/src/cpu/blaze/util/InputString.h
@@ -0,0 +1,434 @@
+//=================================================================================================
+/*!
+// \file blaze/util/InputString.h
+// \brief String implementation for the extraction of input strings
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_INPUTSTRING_H_
+#define _BLAZE_UTIL_INPUTSTRING_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cctype>
+#include <iostream>
+#include <string>
+#include <blaze/util/Assert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of a string wrapper.
+// \ingroup util
+//
+// The InputString class is a wrapper class for the purpose to read input strings delimited by
+// quotations from streams, like for instance "example input". All characters between the
+// leading and the trailing quotation are extracted unchanged from the input stream, including
+// whitespaces. The input string has to be in one single line. In case of input errors, the
+// \a std::istream::failbit of the input stream is set.
+*/
+class InputString
+{
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend std::istream& operator>>( std::istream& is, InputString& str );
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef std::string::size_type SizeType; //!< Size type of the InputString.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline InputString( const char* string="" );
+ explicit inline InputString( const std::string& string );
+ inline InputString( const InputString& s );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ inline InputString& operator=( const char* string );
+ inline InputString& operator=( const std::string& string );
+ // No explicitly declared copy assignment operator.
+ //@}
+ //**********************************************************************************************
+
+ //**Access functions****************************************************************************
+ /*!\name Access functions */
+ //@{
+ inline char& operator[]( SizeType index );
+ inline const char& operator[]( SizeType index ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions
+ // \brief The utility functions are named in the style of \a std::string.
+ */
+ //@{
+ inline const char* c_str() const;
+ inline const std::string& str() const;
+ inline SizeType size() const;
+ inline SizeType capacity() const;
+ inline bool empty() const;
+ inline void reserve( SizeType newSize );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member varibales****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::string buffer_; //!< The character buffer.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for InputString.
+//
+// \param string The initial value for the string.
+*/
+inline InputString::InputString( const char* string )
+ : buffer_( string ) // Character buffer
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Constructor for the direct initialization with a \a std::string.
+//
+// \param string The initial value for the string.
+*/
+inline InputString::InputString( const std::string& string )
+ : buffer_( string ) // Character buffer
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The copy constructor for InputString.
+//
+// \param s The string object to be copied.
+*/
+inline InputString::InputString( const InputString& s )
+ : buffer_( s.buffer_ ) // Character buffer
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Assignment operator for C-style character strings.
+//
+// \param string The C-style string to be copied.
+// \return Reference to the assigned string.
+*/
+inline InputString& InputString::operator=( const char* string )
+{
+ buffer_ = string;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for STL strings.
+//
+// \param string The STL string to be copied.
+// \return Reference to the assigned string.
+*/
+inline InputString& InputString::operator=( const std::string& string )
+{
+ buffer_ = string;
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the characters of the string.
+//
+// \param index Access index. The index has to be in the range \f$[0..size-1]\f$.
+// \return A reference to the indexed character.
+*/
+inline char& InputString::operator[]( SizeType index )
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid access index" );
+ return buffer_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the characters of the string.
+//
+// \param index Access index. The index has to be in the range \f$[0..size-1]\f$.
+// \return A reference to the indexed character.
+*/
+inline const char& InputString::operator[]( SizeType index ) const
+{
+ BLAZE_USER_ASSERT( index < size(), "Invalid access index" );
+ return buffer_[index];
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to a constant character array.
+//
+// \return The converted constant character array.
+*/
+inline const char* InputString::c_str() const
+{
+ return buffer_.c_str();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion to a \a std::string.
+//
+// \return The converted \a std::string.
+*/
+inline const std::string& InputString::str() const
+{
+ return buffer_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the size of the string.
+//
+// \return The size of the string.
+*/
+inline InputString::SizeType InputString::size() const
+{
+ return buffer_.size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximum capacity of the string.
+//
+// \return The capacity of the string.
+*/
+inline InputString::SizeType InputString::capacity() const
+{
+ return buffer_.capacity();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns if the string is empty.
+//
+// \return \a true if the string is empty, \a false if it is not.
+*/
+inline bool InputString::empty() const
+{
+ return buffer_.empty();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reserves at least \a size characters within the string.
+//
+// \param newSize The minimum size of the string.
+// \return void
+*/
+inline void InputString::reserve( SizeType newSize )
+{
+ buffer_.reserve( newSize );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name InputString operators */
+//@{
+inline bool IsFileName( const InputString& s );
+inline std::ostream& operator<<( std::ostream& os, const InputString& str );
+inline std::istream& operator>>( std::istream& is, InputString& str );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Tests for a valid file name.
+// \ingroup util
+//
+// \param s The file name string.
+// \return \a true if the string is a file name, \a false if it is not.
+//
+// In order to be a file name, the first character can only be an alphanumerical character,
+// '.', '/' or '_'.
+*/
+inline bool IsFileName( const InputString& s )
+{
+ if( s.empty() ) return false;
+ else if( isalnum(s[0]) || s[0] == '.' || s[0] == '/' || s[0] == '_' ) return true;
+ else return false;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Global output operator for the InputString class.
+// \ingroup util
+//
+// \param os Reference to the output stream.
+// \param str Reference to a string object.
+// \return The output stream.
+*/
+inline std::ostream& operator<<( std::ostream& os, const InputString& str )
+{
+ return os << str.str();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Global input operator for the InputString class.
+// \ingroup util
+//
+// \param is Reference to the input stream.
+// \param str Reference to a string object.
+// \return The input stream.
+//
+// The input operator guarantees that the string object is not changed in the case of an input
+// error.
+*/
+inline std::istream& operator>>( std::istream& is, InputString& str )
+{
+ if( !is ) return is;
+
+ char c;
+ std::string buffer;
+ std::istream::pos_type pos( is.tellg() );
+
+ buffer.reserve( 20 );
+
+ // Extracting the leading quotation
+ is >> std::ws;
+ if( !is.get( c ) || c != '"' ) {
+ is.clear();
+ is.seekg( pos );
+ is.setstate( std::istream::failbit );
+ return is;
+ }
+
+ // Extracting the input string
+ while( true )
+ {
+ if( !is.get( c ) || c == '\n' ) {
+ is.clear();
+ is.seekg( pos );
+ is.setstate( std::istream::failbit );
+ return is;
+ }
+ else if( c == '"' ) break;
+
+ buffer.push_back( c );
+ }
+
+ // Replacing the old string
+ swap( str.buffer_, buffer );
+
+ return is;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/IntegralConstant.h b/src/cpu/blaze/util/IntegralConstant.h
new file mode 100644
index 00000000..24fe735a
--- /dev/null
+++ b/src/cpu/blaze/util/IntegralConstant.h
@@ -0,0 +1,105 @@
+//=================================================================================================
+/*!
+// \file blaze/util/IntegralConstant.h
+// \brief Header file for the IntegralConstant class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_INTEGRALCONSTANT_H_
+#define _BLAZE_UTIL_INTEGRALCONSTANT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for a compile time constant integral value.
+// \ingroup util
+//
+// The IntegralConstant class template represents a generic wrapper for a compile time constant
+// integral value. The value of an IntegralConstant can be accessed via the nested \a value (which
+// is guaranteed to be of type \a T), the type can be accessed via the nested type definition
+// \a ValueType.
+
+ \code
+ using namespace blaze;
+
+ IntegralConstant<int,3>::value // Evaluates to 3
+ IntegralConstant<long,5L>::ValueType // Results in long
+ \endcode
+*/
+template< typename T, T N >
+struct IntegralConstant : public std::integral_constant<T,N>
+{
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ using ValueType = T;
+ using Type = IntegralConstant<T,N>;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Generic wrapper for a compile time constant boolean value.
+// \ingroup util
+//
+// The BoolConstant class template represents a generic wrapper for a compile time constant
+// boolean value. The value of a BoolConstant can be accessed via the nested \a value (which
+// is guaranteed to be of type \c bool), the type can be accessed via the nested type definition
+// \a ValueType.
+
+ \code
+ using namespace blaze;
+
+ BoolConstant<true>::value // Evaluates to true
+ BoolConstant<false>::ValueType // Results in bool
+ \endcode
+*/
+template< bool B >
+using BoolConstant = IntegralConstant<bool,B>;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/InvalidType.h b/src/cpu/blaze/util/InvalidType.h
new file mode 100644
index 00000000..27141670
--- /dev/null
+++ b/src/cpu/blaze/util/InvalidType.h
@@ -0,0 +1,59 @@
+//=================================================================================================
+/*!
+// \file blaze/util/InvalidType.h
+// \brief Utility type for generic codes
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_INVALIDTYPE_H_
+#define _BLAZE_UTIL_INVALIDTYPE_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Utility type for generic codes.
+// \ingroup util
+//
+// The INVALID_TYPE class represents an invalid data type. It is left undefined to terminate
+// the compilation process in case of the attempt to instantiate it.
+*/
+class INVALID_TYPE;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Limits.h b/src/cpu/blaze/util/Limits.h
new file mode 100644
index 00000000..62cf52e0
--- /dev/null
+++ b/src/cpu/blaze/util/Limits.h
@@ -0,0 +1,440 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Limits.h
+// \brief Numerical limits of built-in data types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LIMITS_H_
+#define _BLAZE_UTIL_LIMITS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <limits>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Numerical limits of built-in data types.
+// \ingroup util
+//
+// The Limits class provides numerical limits for the following built-in data types:
+//
+// <ul>
+// <li>Integral data types</li>
+// <ul>
+// <li>unsigned char, signed char, char, wchar_t</li>
+// <li>unsigned short, short</li>
+// <li>unsigned int, int</li>
+// <li>unsigned long, long</li>
+// <li>size_t, ptrdiff_t (for certain 64-bit compilers)</li>
+// </ul>
+// <li>Floating point data types</li>
+// <ul>
+// <li>float</li>
+// <li>double</li>
+// <li>long double</li>
+// </ul>
+// </ul>
+//
+// Depending on the data type, the following limits can be used:
+//
+// - \b inf: The \a inf function is defined for all built-in data types. It returns the largest
+// possible positive value of the according data type.
+// - \b ninf: The \a ninf function is defined for all signed integral and all floating point
+// data types. It returns the largest possible negative value of the according data type.
+// - \b epsilon: The \a epsilon function is defined for all floating point data types and
+// returns the smallest possible difference between two values of the according data type.
+// - \b accuracy: The \a accuracy function is defined for all floating point data types and
+// returns the computation accuracy of the corresponding data type. Due to the limited
+// floating point accuracy of a CPU this value is needed as computation threshold. This
+// value is used in most computations throughout the Blaze library.
+// - \b fpuAccuracy: The \a fpuAccuracy function is defined for all floating point data types
+// and returns the floating point accuracy of the according point data type. Due to the
+// limited floating point accuracy of a CPU this value is needed as zero threshold in
+// computations.
+//
+// Code examples:
+
+ \code
+ // Positiv infinity value
+ unsigned int ui = Limits<unsigned int>::inf();
+
+ // Negative infinity value
+ double d = Limits<double>::ninf();
+ \endcode
+*/
+template< typename Type >
+struct Limits
+{};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SPECIALIZATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<unsigned char> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<unsigned char>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive unsigned char value. */
+ static inline unsigned char inf() { return std::numeric_limits<unsigned char>::max(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<char> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<char>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive char value. */
+ static inline char inf () { return std::numeric_limits<char>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative char value. */
+ static inline char ninf() { return std::numeric_limits<char>::min(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<signed char> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<signed char>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive signed char value. */
+ static inline signed char inf () { return std::numeric_limits<signed char>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative signed char value. */
+ static inline signed char ninf() { return std::numeric_limits<signed char>::min(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<wchar_t> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<wchar_t>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive wchar_t value. */
+ static inline wchar_t inf () { return std::numeric_limits<wchar_t>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative wchar_t value. */
+ static inline wchar_t ninf() { return std::numeric_limits<wchar_t>::min(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<unsigned short> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<unsigned short>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive unsigned short value. */
+ static inline unsigned short inf() { return std::numeric_limits<unsigned short>::max(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<short> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<short>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive short value. */
+ static inline short inf () { return std::numeric_limits<short>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative short value. */
+ static inline short ninf() { return std::numeric_limits<short>::min(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<unsigned int> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<unsigned int>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive unsigned int value. */
+ static inline unsigned int inf() { return std::numeric_limits<unsigned int>::max(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<int> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<int>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive int value. */
+ static inline int inf () { return std::numeric_limits<int>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative int value. */
+ static inline int ninf() { return std::numeric_limits<int>::min(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<unsigned long> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<unsigned long>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive unsigned long value. */
+ static inline unsigned long inf() { return std::numeric_limits<unsigned long>::max(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<long> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<long>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive long value. */
+ static inline long inf () { return std::numeric_limits<long>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative long value. */
+ static inline long ninf() { return std::numeric_limits<long>::min(); }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if defined(_WIN64)
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<size_t> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<std::size_t>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive size_t value. */
+ static inline size_t inf() { return std::numeric_limits<size_t>::max(); }
+};
+/*! \endcond */
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+#if defined(_WIN64)
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<ptrdiff_t> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<ptrdiff_t>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive ptrdiff_t value. */
+ static inline ptrdiff_t inf () { return std::numeric_limits<ptrdiff_t>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative ptrdiff_t value. */
+ static inline ptrdiff_t ninf() { return std::numeric_limits<ptrdiff_t>::min(); }
+};
+/*! \endcond */
+#endif
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<float> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<float>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive float value. */
+ static inline float inf () { return std::numeric_limits<float>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative float value. */
+ static inline float ninf() { return -std::numeric_limits<float>::max(); }
+
+ /*!\brief Machine epsilon.
+ // \return The smallest possible difference between two float values. */
+ static inline float epsilon() { return std::numeric_limits<float>::epsilon(); }
+
+ /*!\brief The compuation accuracy of the Blaze library.
+ // \return The computation threshold for single precision floating point values. */
+ static inline float accuracy() { return 1E-6F; }
+
+ /*!\brief The machine floating point accuracy.
+ // \return The machine accuracy for single precision floating point values. */
+ static inline float fpuAccuracy() { return 1E-12F; }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<double> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<double>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive double value. */
+ static inline double inf () { return std::numeric_limits<double>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative double value. */
+ static inline double ninf() { return -std::numeric_limits<double>::max(); }
+
+ /*!\brief Machine epsilon.
+ // \return The smallest possible difference between two double values. */
+ static inline double epsilon() { return std::numeric_limits<double>::epsilon(); }
+
+ /*!\brief The compuation accuracy of the Blaze library.
+ // \return The computation threshold for double precision floating point values. */
+ static inline double accuracy() { return 1E-8; }
+
+ /*!\brief The machine floating point accuracy.
+ // \return The machine accuracy for double precision floating point values. */
+ static inline double fpuAccuracy() { return 1E-15; }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Limits<long double> specialization.
+// \ingroup util
+*/
+template<>
+struct Limits<long double>
+{
+ /*!\brief Positive infinity value.
+ // \return The largest possible positive long double value. */
+ static inline long double inf () { return std::numeric_limits<long double>::max(); }
+
+ /*!\brief Negative infinity value.
+ // \return The largest possible negative long double value. */
+ static inline long double ninf() { return -std::numeric_limits<long double>::max(); }
+
+ /*!\brief Machine epsilon.
+ // \return The smallest possible difference between two long double values. */
+ static inline long double epsilon() { return std::numeric_limits<long double>::epsilon(); }
+
+ /*!\brief The compuation accuracy of the Blaze library.
+ // \return The computation threshold for long double floating point values. */
+ static inline long double accuracy() { return 1E-10L; }
+
+ /*!\brief The machine floating point accuracy.
+ // \return The machine accuracy for long double floating point values. */
+ static inline long double fpuAccuracy() { return 1E-15L; }
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Logging.h b/src/cpu/blaze/util/Logging.h
new file mode 100644
index 00000000..2c5388f7
--- /dev/null
+++ b/src/cpu/blaze/util/Logging.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Logging.h
+// \brief Header file for the logging functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_H_
+#define _BLAZE_UTIL_LOGGING_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/logging/DebugSection.h>
+#include <blaze/util/logging/DetailSection.h>
+#include <blaze/util/logging/ErrorSection.h>
+#include <blaze/util/logging/FunctionTrace.h>
+#include <blaze/util/logging/InfoSection.h>
+#include <blaze/util/logging/ProgressSection.h>
+#include <blaze/util/logging/WarningSection.h>
+
+#endif
diff --git a/src/cpu/blaze/util/MPL.h b/src/cpu/blaze/util/MPL.h
new file mode 100644
index 00000000..0b87b600
--- /dev/null
+++ b/src/cpu/blaze/util/MPL.h
@@ -0,0 +1,64 @@
+//=================================================================================================
+/*!
+// \file blaze/util/MPL.h
+// \brief Header file for all meta-programming tools
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_H_
+#define _BLAZE_UTIL_MPL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/And.h>
+#include <blaze/util/mpl/Bool.h>
+#include <blaze/util/mpl/Char.h>
+#include <blaze/util/mpl/Equal.h>
+#include <blaze/util/mpl/Greater.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Int.h>
+#include <blaze/util/mpl/Less.h>
+#include <blaze/util/mpl/Long.h>
+#include <blaze/util/mpl/Max.h>
+#include <blaze/util/mpl/Min.h>
+#include <blaze/util/mpl/Minus.h>
+#include <blaze/util/mpl/Modulus.h>
+#include <blaze/util/mpl/NextMultiple.h>
+#include <blaze/util/mpl/Not.h>
+#include <blaze/util/mpl/Or.h>
+#include <blaze/util/mpl/Plus.h>
+#include <blaze/util/mpl/SizeT.h>
+#include <blaze/util/mpl/Times.h>
+#include <blaze/util/mpl/Xor.h>
+
+#endif
diff --git a/src/cpu/blaze/util/Memory.h b/src/cpu/blaze/util/Memory.h
new file mode 100644
index 00000000..2f11b20c
--- /dev/null
+++ b/src/cpu/blaze/util/Memory.h
@@ -0,0 +1,278 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Memory.h
+// \brief Header file for memory allocation and deallocation functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MEMORY_H_
+#define _BLAZE_UTIL_MEMORY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#if defined(_MSC_VER)
+# include <malloc.h>
+#endif
+#include <cstdlib>
+#include <new>
+#include <blaze/util/Assert.h>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/Exception.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/AlignmentOf.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// BACKEND ALLOCATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation for aligned array allocation.
+// \ingroup util
+//
+// \param size The number of bytes to be allocated.
+// \param alignment The required minimum alignment.
+// \return Byte pointer to the first element of the aligned array.
+// \exception std::bad_alloc Allocation failed.
+//
+// This function provides the functionality to allocate memory based on the given alignment
+// restrictions. For that purpose it uses the according system-specific memory allocation
+// functions.
+*/
+inline byte_t* allocate_backend( size_t size, size_t alignment )
+{
+ void* raw( nullptr );
+
+#if defined(_MSC_VER)
+ raw = _aligned_malloc( size, alignment );
+ if( raw == nullptr ) {
+#else
+ if( posix_memalign( &raw, alignment, size ) ) {
+#endif
+ BLAZE_THROW_BAD_ALLOC;
+ }
+
+ return reinterpret_cast<byte_t*>( raw );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Backend implementation for the deallocation of aligned memory.
+// \ingroup util
+//
+// \param address The address of the first element of the array to be deallocated.
+// \return void
+//
+// This function deallocates the given memory that was previously allocated via the allocate()
+// function. For that purpose it uses the according system-specific memory deallocation functions.
+*/
+inline void deallocate_backend( const void* address ) noexcept
+{
+#if defined(_MSC_VER)
+ _aligned_free( const_cast<void*>( address ) );
+#else
+ free( const_cast<void*>( address ) );
+#endif
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ALLOCATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Aligned array allocation for built-in data types.
+// \ingroup util
+//
+// \param size The number of elements of the given type to allocate.
+// \return Pointer to the first element of the aligned array.
+// \exception std::bad_alloc Allocation failed.
+//
+// The allocate() function provides the functionality to allocate memory based on the alignment
+// restrictions of the given built-in data type. For instance, in case SSE vectorization is
+// possible, the returned memory is guaranteed to be at least 16-byte aligned. In case AVX is
+// active, the memory is even guaranteed to be at least 32-byte aligned.
+//
+// Examples:
+
+ \code
+ // Guaranteed to be 16-byte aligned (32-byte aligned in case AVX is used)
+ double* dp = allocate<double>( 10UL );
+ \endcode
+*/
+template< typename T >
+EnableIf_< IsBuiltin<T>, T* > allocate( size_t size )
+{
+ const size_t alignment( AlignmentOf<T>::value );
+
+ if( alignment >= 8UL ) {
+ return reinterpret_cast<T*>( allocate_backend( size*sizeof(T), alignment ) );
+ }
+ else return ::new T[size];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Aligned array allocation for user-specific class types.
+// \ingroup util
+//
+// \param size The number of elements of the given type to allocate.
+// \return Pointer to the first element of the aligned array.
+// \exception std::bad_alloc Allocation failed.
+//
+// The allocate() function provides the functionality to allocate memory based on the alignment
+// restrictions of the given user-specific class type. For instance, in case the given type has
+// the requirement to be 32-byte aligned, the returned pointer is guaranteed to be 32-byte
+// aligned. Additionally, all elements of the array are guaranteed to be default constructed.
+// Note that the allocate() function provides exception safety similar to the new operator: In
+// case any element throws an exception during construction, all elements that have already been
+// constructed are destroyed in reverse order and the allocated memory is deallocated again.
+*/
+template< typename T >
+DisableIf_< IsBuiltin<T>, T* > allocate( size_t size )
+{
+ const size_t alignment ( AlignmentOf<T>::value );
+ const size_t headersize( ( sizeof(size_t) < alignment ) ? ( alignment ) : ( sizeof( size_t ) ) );
+
+ BLAZE_INTERNAL_ASSERT( headersize >= alignment , "Invalid header size detected" );
+ BLAZE_INTERNAL_ASSERT( headersize % alignment == 0UL, "Invalid header size detected" );
+
+ if( alignment >= 8UL )
+ {
+ byte_t* const raw( allocate_backend( size*sizeof(T)+headersize, alignment ) );
+
+ *reinterpret_cast<size_t*>( raw ) = size;
+
+ T* const address( reinterpret_cast<T*>( raw + headersize ) );
+ size_t i( 0UL );
+
+ try {
+ for( ; i<size; ++i )
+ ::new (address+i) T();
+ }
+ catch( ... ) {
+ while( i != 0UL )
+ address[--i].~T();
+ deallocate_backend( raw );
+ throw;
+ }
+
+ return address;
+ }
+ else return ::new T[size];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deallocation of memory for built-in data types.
+// \ingroup util
+//
+// \param address The address of the first element of the array to be deallocated.
+// \return void
+//
+// This function deallocates the given memory that was previously allocated via the allocate()
+// function.
+*/
+template< typename T >
+EnableIf_< IsBuiltin<T> > deallocate( T* address ) noexcept
+{
+ if( address == nullptr )
+ return;
+
+ const size_t alignment( AlignmentOf<T>::value );
+
+ if( alignment >= 8UL ) {
+ deallocate_backend( address );
+ }
+ else delete[] address;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deallocation of memory for user-specific class types.
+// \ingroup util
+//
+// \param address The address of the first element of the array to be deallocated.
+// \return void
+//
+// This function deallocates the given memory that was previously allocated via the allocate()
+// function.
+*/
+template< typename T >
+DisableIf_< IsBuiltin<T> > deallocate( T* address )
+{
+ if( address == nullptr )
+ return;
+
+ const size_t alignment ( AlignmentOf<T>::value );
+ const size_t headersize( ( sizeof(size_t) < alignment ) ? ( alignment ) : ( sizeof( size_t ) ) );
+
+ BLAZE_INTERNAL_ASSERT( headersize >= alignment , "Invalid header size detected" );
+ BLAZE_INTERNAL_ASSERT( headersize % alignment == 0UL, "Invalid header size detected" );
+
+ if( alignment >= 8UL )
+ {
+ const byte_t* const raw = reinterpret_cast<byte_t*>( address ) - headersize;
+
+ const size_t size( *reinterpret_cast<const size_t*>( raw ) );
+ for( size_t i=0UL; i<size; ++i )
+ address[i].~T();
+
+ deallocate_backend( raw );
+ }
+ else delete[] address;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/MemoryPool.h b/src/cpu/blaze/util/MemoryPool.h
new file mode 100644
index 00000000..9979ef9d
--- /dev/null
+++ b/src/cpu/blaze/util/MemoryPool.h
@@ -0,0 +1,300 @@
+//=================================================================================================
+/*!
+// \file blaze/util/MemoryPool.h
+// \brief Header file for the memory pool class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MEMORYPOOL_H_
+#define _BLAZE_UTIL_MEMORYPOOL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <vector>
+#include <blaze/util/Assert.h>
+#include <blaze/util/NonCopyable.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Memory pool for small objects.
+// \ingroup util
+//
+// The memory pool efficiently improves the performance of dynamic memory allocations for small
+// objects. By allocating a large block of memory that can be dynamically assigned to small
+// objects, the memory allocation is reduced from a few hundred cycles to only a few cycles.\n
+// The memory pool is build from memory blocks of type Block, which hold the memory for a
+// specified number of objects. The memory of these blocks is managed as a single free list.
+*/
+template< typename Type, size_t Blocksize >
+class MemoryPool : private NonCopyable
+{
+ private:
+ //**union FreeObject****************************************************************************
+ /*!\brief A single element of the free list of the memory pool.
+ */
+ union FreeObject {
+ FreeObject* next_; //!< Pointer to the next free object.
+ byte_t dummy_[ sizeof(Type) ]; //!< Dummy array to create an object of the appropriate size.
+ };
+ //**********************************************************************************************
+
+ //**struct Block********************************************************************************
+ /*!\brief Memory block within the memory bool.
+ //
+ // One memory block holds the memory for exactly \a Blocksize objects of type \a Type.
+ */
+ struct Block
+ {
+ public:
+ //**Memory management functions**************************************************************
+ /*!\name Memory management functions */
+ //@{
+ void init();
+ void free();
+ //@}
+ //*******************************************************************************************
+
+ //**Member variables*************************************************************************
+ /*!\name Member variables */
+ //@{
+ FreeObject* rawMemory_; //!< Allocated memory pool of the block.
+ //@}
+ //*******************************************************************************************
+ };
+ //**********************************************************************************************
+
+ //**Type definitions****************************************************************************
+ typedef std::vector<Block> Blocks; //!< Vector of memory blocks.
+ //**********************************************************************************************
+
+ public:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ inline MemoryPool();
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~MemoryPool();
+ //@}
+ //**********************************************************************************************
+
+ //**Memory management functions*****************************************************************
+ /*!\name Memory management functions */
+ //@{
+ inline void* malloc();
+ inline void free( void* rawMemory );
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Memory management functions*****************************************************************
+ /*!\name Memory management functions */
+ //@{
+ inline bool checkMemory( FreeObject* rawMemory ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ FreeObject* freeList_; //!< Head of the free list.
+ Blocks blocks_; //!< Vector of available memory blocks.
+ //@}
+ //**********************************************************************************************
+};
+
+
+
+
+//=================================================================================================
+//
+// CLASS MEMORYPOOL::BLOCK
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Initialization of a memory block.
+//
+// \return void
+//
+// The \a init function allocates a single memory block for \a Blocksize objects of type \a Type.
+// This memory is already prepared for the inclusion in the free list of the memory pool.
+*/
+template< typename Type, size_t Blocksize >
+inline void MemoryPool<Type,Blocksize>::Block::init()
+{
+ rawMemory_ = new FreeObject[ Blocksize ];
+ for( size_t i=0; i<Blocksize-1; ++i ) {
+ rawMemory_[i].next_ = &rawMemory_[i+1];
+ }
+ rawMemory_[Blocksize-1].next_ = 0;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Release of the entire memory block.
+//
+// \return void
+*/
+template< typename Type, size_t Blocksize >
+inline void MemoryPool<Type,Blocksize>::Block::free()
+{
+ delete [] rawMemory_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS MEMORYPOOL
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor of the memory pool.
+*/
+template< typename Type, size_t Blocksize >
+inline MemoryPool<Type,Blocksize>::MemoryPool()
+{
+ blocks_.push_back( Block() );
+ Block& block = blocks_.back();
+ block.init();
+ freeList_ = block.rawMemory_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Destructor of the memory pool.
+*/
+template< typename Type, size_t Blocksize >
+inline MemoryPool<Type,Blocksize>::~MemoryPool()
+{
+ for( typename Blocks::iterator it=blocks_.begin(); it!=blocks_.end(); ++it )
+ it->free();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Allocation of raw memory for an object of type \a Type.
+//
+// \return Pointer to the raw memory.
+*/
+template< typename Type, size_t Blocksize >
+inline void* MemoryPool<Type,Blocksize>::malloc()
+{
+ if( !freeList_ ) {
+ blocks_.push_back( Block() );
+ Block& block = blocks_.back();
+ block.init();
+ freeList_ = block.rawMemory_;
+ }
+
+ void* ptr = freeList_;
+ freeList_ = freeList_->next_;
+ return ptr;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deallocation of raw memory for an object of type \a Type.
+//
+// \param rawMemory Pointer to the raw memory.
+// \return void
+*/
+template< typename Type, size_t Blocksize >
+inline void MemoryPool<Type,Blocksize>::free( void* rawMemory )
+{
+ FreeObject* ptr = reinterpret_cast<FreeObject*>( rawMemory );
+ BLAZE_INTERNAL_ASSERT( checkMemory( ptr ), "Memory pool check failed" );
+ ptr->next_ = freeList_;
+ freeList_ = ptr;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Performing a number of checks on the memory to be released.
+//
+// \param toRelease Pointer to the memory to be released.
+// \return \a true if the memory check succeeds, \a false if an error is encountered.
+*/
+template< typename Type, size_t Blocksize >
+inline bool MemoryPool<Type,Blocksize>::checkMemory( FreeObject* toRelease ) const
+{
+ for( typename Blocks::const_iterator it=blocks_.begin(); it!=blocks_.end(); ++it )
+ {
+ // Range check
+ if( toRelease >= it->rawMemory_ && toRelease < it->rawMemory_+Blocksize )
+ {
+ // Alignment check
+ const byte_t* const ptr1( reinterpret_cast<const byte_t*>(toRelease) );
+ const byte_t* const ptr2( reinterpret_cast<const byte_t*>(it->rawMemory_) );
+
+ if( ( ptr1 - ptr2 ) % sizeof(FreeObject) != 0 ) return false;
+
+ // Duplicate free check
+ FreeObject* ptr( freeList_ );
+ while( ptr ) {
+ if( ptr == toRelease ) return false;
+ ptr = ptr->next_;
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Misalignment.h b/src/cpu/blaze/util/Misalignment.h
new file mode 100644
index 00000000..fb2614ae
--- /dev/null
+++ b/src/cpu/blaze/util/Misalignment.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Misalignment.h
+// \brief Header file for the misalignment function
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MISALIGNMENT_H_
+#define _BLAZE_UTIL_MISALIGNMENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Inline.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/AlignmentOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SIZETRAIT CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Computes the misalignment of the given address.
+// \ingroup util
+//
+// \param address The address to be checked.
+// \return The number of bytes the given address is misaligned.
+//
+// This function computes the misalignment of the given address with respect to the given data
+// type \a Type and the available instruction set (SSE, AVX, ...). It returns the number of bytes
+// the address is larger than the next smaller properly aligned address.
+*/
+template< typename T >
+BLAZE_ALWAYS_INLINE size_t misalignment( const T* address )
+{
+ return ( reinterpret_cast<size_t>( address ) % AlignmentOf<T>::value );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/NonCopyable.h b/src/cpu/blaze/util/NonCopyable.h
new file mode 100644
index 00000000..cdda3611
--- /dev/null
+++ b/src/cpu/blaze/util/NonCopyable.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/util/NonCopyable.h
+// \brief Base class for non-copyable class instances
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_NONCOPYABLE_H_
+#define _BLAZE_UTIL_NONCOPYABLE_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for non-copyable class instances.
+// \ingroup util
+//
+// The NonCopyable class is intended to work as a base class for non-copyable classes. Both the
+// copy constructor and the copy assignment operator are explicitly deleted in order to prohibit
+// copy operations of the derived classes.\n
+//
+// \note It is not necessary to publicly derive from this class. It is sufficient to derive
+// privately to prevent copy operations on the derived class.
+
+ \code
+ class A : private NonCopyable
+ { ... };
+ \endcode
+*/
+class NonCopyable
+{
+ protected:
+ //**Constructor and destructor******************************************************************
+ /*!\name Constructor and destructor */
+ //@{
+ inline NonCopyable() {} //!< Default constructor for the NonCopyable class.
+ inline ~NonCopyable() {} //!< Destructor of the NonCopyable class.
+ //@}
+ //**********************************************************************************************
+
+ //**Copy constructor and copy assignment operator***********************************************
+ /*!\name Copy constructor and copy assignment operator */
+ //@{
+ NonCopyable( const NonCopyable& ) = delete; //!< Copy constructor (explicitly deleted)
+ NonCopyable& operator=( const NonCopyable& ) = delete; //!< Copy assignment operator (explicitly deleted)
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/NonCreatable.h b/src/cpu/blaze/util/NonCreatable.h
new file mode 100644
index 00000000..95cc9f01
--- /dev/null
+++ b/src/cpu/blaze/util/NonCreatable.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/NonCreatable.h
+// \brief Base class for non-creatable (static) classes
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_NONCREATABLE_H_
+#define _BLAZE_UTIL_NONCREATABLE_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Base class for non-creatable (static) classes.
+// \ingroup util
+//
+// The NonCreatable class is intended to work as a base class for non-creatable classes, i.e.
+// classes that cannot be instantiated and exclusively offer static functions/data. Both the
+// standard as well as the copy constructor and the copy assignment operator are declared
+// private and left undefinded in order to prohibit the instantiation of objects of derived
+// classes.\n
+//
+// \note It is not necessary to publicly derive from this class. It is sufficient to derive
+// privately to prevent the instantiation of the derived class.
+
+ \code
+ class A : private NonCreatable
+ { ... };
+ \endcode
+*/
+class NonCreatable
+{
+ protected:
+ //**Constructors and copy assignment operator***************************************************
+ /*!\name Constructors and copy assignment operator */
+ //@{
+ NonCreatable() = delete; //!< Constructor (explicitly deleted)
+ NonCreatable( const NonCreatable& ) = delete; //!< Copy constructor (explicitly deleted)
+ NonCreatable& operator=( const NonCreatable& ) = delete; //!< Copy assignment operator (explicitly deleted)
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/NullType.h b/src/cpu/blaze/util/NullType.h
new file mode 100644
index 00000000..9267122c
--- /dev/null
+++ b/src/cpu/blaze/util/NullType.h
@@ -0,0 +1,60 @@
+//=================================================================================================
+/*!
+// \file blaze/util/NullType.h
+// \brief Utility type for generic codes
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_NULLTYPE_H_
+#define _BLAZE_UTIL_NULLTYPE_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Utility type for generic codes.
+// \ingroup util
+//
+// The NullType class represents an invalid or terminating data type for generic codes. For
+// instance, the TypeList class uses the NullType as terminating data type for the type list.
+*/
+class NullType
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/PointerCast.h b/src/cpu/blaze/util/PointerCast.h
new file mode 100644
index 00000000..3a4bc370
--- /dev/null
+++ b/src/cpu/blaze/util/PointerCast.h
@@ -0,0 +1,286 @@
+//=================================================================================================
+/*!
+// \file blaze/util/PointerCast.h
+// \brief Cast operators for pointer types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POINTERCAST_H_
+#define _BLAZE_UTIL_POINTERCAST_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// POINTER CAST OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Pointer cast operators */
+//@{
+template< typename To, typename From > inline To* static_pointer_cast( From* ptr );
+template< typename To, typename From > inline To* dynamic_pointer_cast( From* ptr );
+template< typename To, typename From > inline To* const_pointer_cast( From* ptr);
+template< typename To, typename From > inline To* reinterpret_pointer_cast( From* ptr );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Static cast for pointer types.
+// \ingroup util
+//
+// \param ptr The pointer to be cast.
+// \return The casted value.
+//
+// The static_pointer_cast function is used exactly as the built-in static_cast operator but
+// for pointer types.
+
+ \code
+ class B { ... };
+ class D : public B { ... };
+
+ B* b = new D(); // Base pointer to a derived class object
+ D* d = static_pointer_cast<D>( b ); // Static down-cast
+ \endcode
+*/
+template< typename To, typename From >
+inline To* static_pointer_cast( From* ptr )
+{
+ return static_cast<To*>( ptr );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Dynamic cast for pointer types.
+// \ingroup util
+//
+// \param ptr The pointer to be cast.
+// \return The casted value.
+//
+// The dynamic_pointer_cast function is used exactly as the built-in dynamic_cast operator but
+// for pointer types. As in case with the built-in dynamic_cast 0 is returned if the runtime
+// type conversion doesn't succeed.
+
+ \code
+ class B { ... };
+ class D : public B { ... };
+
+ B* b = ...; // Base pointer
+ D* d = dynamic_pointer_cast<D>( b ); // Dynamic down-cast
+ \endcode
+*/
+template< typename To, typename From >
+inline To* dynamic_pointer_cast( From* ptr )
+{
+ return dynamic_cast<To*>( ptr );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Const cast for pointer types.
+// \ingroup util
+//
+// \param ptr The pointer to be cast.
+// \return The casted value.
+//
+// The const_pointer_cast function is used exactly as the built-in const_cast operator but
+// for pointer types.
+
+ \code
+ class A { ... };
+
+ const A* a1; // Pointer to a constant A object
+ A* a2 = const_pointer_cast<A>( a1 ); // Const cast to a pointer to a non-constant A object
+ \endcode
+*/
+template< typename To, typename From >
+inline To* const_pointer_cast( From* ptr)
+{
+ return const_cast<To*>( ptr );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reinterpret cast for pointer types.
+// \ingroup util
+//
+// \param ptr The pointer to be cast.
+// \return The casted value.
+//
+// The reinterpret_pointer_cast function is used exactly as the built-in reinterpret_cast
+// operator but for pointer types.
+
+ \code
+ class A { ... };
+
+ unsigned char* raw = new unsigned char[ sizeof(A)*10 ]; // Allocation of raw memory
+ A* a = reinterpret_pointer_cast<A>( raw ); // Reinterpretation cast
+ \endcode
+*/
+template< typename To, typename From >
+inline To* reinterpret_pointer_cast( From* ptr )
+{
+ return reinterpret_cast<To*>( ptr );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SMART POINTER CAST OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Smart pointer cast operators */
+//@{
+template< typename To, template<typename> class S, typename From > inline S<To> static_pointer_cast( S<From> ptr );
+template< typename To, template<typename> class S, typename From > inline S<To> dynamic_pointer_cast( S<From> ptr );
+template< typename To, template<typename> class S, typename From > inline S<To> const_pointer_cast( S<From> ptr);
+template< typename To, template<typename> class S, typename From > inline S<To> reinterpret_pointer_cast( S<From> ptr );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Static cast for smart pointers.
+// \ingroup util
+//
+// \param ptr The smart pointer to be cast.
+// \return The casted smart pointer.
+//
+// The static_pointer_cast function is used exactly as the built-in static_cast operator but
+// for smart pointers.
+
+ \code
+ class B { ... };
+ class D : public B { ... };
+
+ typedef SharedPtr<B> BPtr;
+ typedef SharedPtr<D> DPtr;
+
+ BPtr b = BPtr( new D() ); // Base smart pointer to a derived class object
+ DPtr d = static_pointer_cast<D>( b ); // Static down-cast
+ \endcode
+*/
+template< typename To, template<typename> class S, typename From >
+inline S<To> static_pointer_cast( S<From> ptr )
+{
+ return S<To>( static_cast<To*>( ptr.get() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Dynamic cast for smart pointers.
+// \ingroup util
+//
+// \param ptr The smart pointer to be cast.
+// \return The casted smart pointer.
+//
+// The dynamic_pointer_cast function is used exactly as the built-in dynamic_cast operator
+// but for smart pointers. As in case with the built-in dynamic_cast 0 is returned if the
+// runtime type conversion doesn't succeed.
+
+ \code
+ class B { ... };
+ class D : public B { ... };
+
+ typedef SharedPtr<B> BPtr;
+ typedef SharedPtr<D> DPtr;
+
+ BPtr b = ...; // Base smart pointer
+ DPtr d = dynamic_pointer_cast<D>( b ); // Dynamic down-cast
+ \endcode
+*/
+template< typename To, template<typename> class S, typename From >
+inline S<To> dynamic_pointer_cast( S<From> ptr )
+{
+ return S<To>( dynamic_cast<To*>( ptr.get() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Const cast for smart pointers.
+// \ingroup util
+//
+// \param ptr The smart pointer to be cast.
+// \return The casted smart pointer.
+//
+// The const_pointer_cast function is used exactly as the built-in const_cast operator but
+// for smart pointers.
+
+ \code
+ class A { ... };
+
+ typedef SharedPtr<A> APtr;
+ typedef SharedPtr<const A> ConstAPtr;
+
+ ConstAPtr a1; // Smart pointer to a constant A object
+ APtr a2 = const_pointer_cast<A>( a1 ); // Const cast to a smart pointer to a non-constant A object
+ \endcode
+*/
+template< typename To, template<typename> class S, typename From >
+inline S<To> const_pointer_cast( S<From> ptr )
+{
+ return S<To>( const_cast<To*>( ptr.get() ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reinterpret cast for smart pointers.
+// \ingroup util
+//
+// \param ptr The smart pointer to be cast.
+// \return The casted smart pointer.
+//
+// The reinterpret_pointer_cast function is used exactly as the built-in reinterpret_cast
+// operator but for smart pointers.
+*/
+template< typename To, template<typename> class S, typename From >
+inline S<To> reinterpret_pointer_cast( S<From> ptr )
+{
+ return S<To>( reinterpret_cast<To*>( ptr.get() ) );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Policies.h b/src/cpu/blaze/util/Policies.h
new file mode 100644
index 00000000..17908426
--- /dev/null
+++ b/src/cpu/blaze/util/Policies.h
@@ -0,0 +1,52 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Policies.h
+// \brief Header file for policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_H_
+#define _BLAZE_UTIL_POLICIES_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/policies/ArrayDelete.h>
+#include <blaze/util/policies/ConstantGrowth.h>
+#include <blaze/util/policies/Deallocate.h>
+#include <blaze/util/policies/DefaultDelete.h>
+#include <blaze/util/policies/LinearGrowth.h>
+#include <blaze/util/policies/NoDelete.h>
+#include <blaze/util/policies/OptimalGrowth.h>
+#include <blaze/util/policies/PtrDelete.h>
+
+#endif
diff --git a/src/cpu/blaze/util/PtrIterator.h b/src/cpu/blaze/util/PtrIterator.h
new file mode 100644
index 00000000..70290733
--- /dev/null
+++ b/src/cpu/blaze/util/PtrIterator.h
@@ -0,0 +1,563 @@
+//=================================================================================================
+/*!
+// \file blaze/util/PtrIterator.h
+// \brief Iterator class for pointer vectors
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_PTRITERATOR_H_
+#define _BLAZE_UTIL_PTRITERATOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <iterator>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of an iterator for pointer vectors.
+// \ingroup util
+//
+// The PtrIterator class follows the example of the random-access iterator classes of the STL.
+// However, the focus of this iterator implementation is the use with (polymorphic) pointers.
+// The implementation of the Blaze library eases the use of iterators over a range of pointers
+// and improves the semantics on these pointers.\n
+//
+// In contrast to the STL iterators, the PtrIterator class slightly changes the meaning of the
+// access operators. Consider the following example:
+
+ \code
+ // Definition of class A
+ class A
+ {
+ public:
+ A( int i=0 ):i_(i) {}
+
+ void set( int i ) { i_ = i; }
+ int get() const { return i_; }
+
+ private:
+ int i_;
+ };
+
+ // Definition of a pointer vector for class A
+ typedef blaze::PtrVector<A> AVector;
+
+ AVector vector;
+ AVector::Iterator it = vector.begin();
+
+ // The subscript operator returns a handle to the underlying object
+ A* a1 = it[0];
+
+ // The dereference operator returns a handle to the underlying object
+ A* a2 = *it;
+
+ // The member access operator offers direct access to the underlying object
+ it->set( 2 );
+ \endcode
+
+// The constant iterators (iterator over constant objects) prohibit the access to non-const
+// member functions. Therefore the following operation results in a compile-time error:
+
+ \code
+ AVector vector;
+ AVector::ConstIterator it = vector.begin();
+
+ it->set( 2 ); // Compile-time error!
+ \endcode
+*/
+template< typename Type >
+class PtrIterator
+{
+ public:
+ //**Type definitions****************************************************************************
+ // blaze naming convention
+ typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef Type* ValueType; //!< Type of the underlying pointers.
+ typedef Type* PointerType; //!< Pointer return type.
+ typedef ValueType const& ReferenceType; //!< Reference return type.
+ typedef ValueType const* IteratorType; //!< Type of the internal pointer.
+ typedef std::ptrdiff_t DifferenceType; //!< Difference between two iterators.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline PtrIterator();
+ explicit inline PtrIterator( const IteratorType& it );
+
+ template< typename Other >
+ inline PtrIterator( const PtrIterator<Other>& it );
+
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Copy assignment operator********************************************************************
+ // No explicitly declared copy assignment operator.
+ //**********************************************************************************************
+
+ //**Operators***********************************************************************************
+ /*!\name Operators */
+ //@{
+ inline PtrIterator& operator++();
+ inline PtrIterator operator++( int );
+ inline PtrIterator& operator--();
+ inline PtrIterator operator--( int );
+ inline PtrIterator& operator+=( DifferenceType n );
+ inline PtrIterator operator+ ( DifferenceType n ) const;
+ inline PtrIterator& operator-=( DifferenceType n );
+ inline PtrIterator operator- ( DifferenceType n ) const;
+ inline DifferenceType operator- ( const PtrIterator& it ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline PointerType operator[]( DifferenceType n ) const;
+ inline PointerType operator*() const;
+ inline PointerType operator->() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline const IteratorType& base() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ IteratorType it_; //!< Pointer to the current memory location.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default constructor for PtrIterator.
+*/
+template< typename Type >
+inline PtrIterator<Type>::PtrIterator()
+ : it_( nullptr ) // Pointer to the current memory location
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Standard constructor for PtrIterator.
+//
+// \param it The value of the iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type>::PtrIterator( const IteratorType& it )
+ : it_( it ) // Pointer to the current memory location
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different PtrIterator instances.
+//
+// \param it The foreign PtrIterator instance to be copied.
+*/
+template< typename Type >
+template< typename Other >
+inline PtrIterator<Type>::PtrIterator( const PtrIterator<Other>& it )
+ : it_( it.base() ) // Pointer to the current memory location
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Pre-increment operator.
+//
+// \return Reference to the incremented pointer iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type>& PtrIterator<Type>::operator++()
+{
+ ++it_;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Post-increment operator.
+//
+// \return The incremented pointer iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type> PtrIterator<Type>::operator++( int )
+{
+ PtrIterator tmp( *this );
+ ++it_;
+ return tmp;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Pre-decrement operator.
+//
+// \return Reference to the decremented pointer iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type>& PtrIterator<Type>::operator--()
+{
+ --it_;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Post-decrement operator.
+//
+// \return The decremented pointer iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type> PtrIterator<Type>::operator--( int )
+{
+ PtrIterator tmp( *this );
+ --it_;
+ return tmp;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Shifting the iterator by \a n elements to the higher elements.
+//
+// \param n The number of elements.
+// \return Reference to the shifted pointer iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type>& PtrIterator<Type>::operator+=( DifferenceType n )
+{
+ it_ += n;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Shifting the iterator by \a n elements to the higher elements.
+//
+// \param n The number of elements.
+// \return The shifted pointer iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type> PtrIterator<Type>::operator+( DifferenceType n ) const
+{
+ return PtrIterator( it_ + n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Shifting the iterator by \a n elements to the lower elements.
+//
+// \param n The number of elements.
+// \return Reference to the shifted pointer iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type>& PtrIterator<Type>::operator-=( DifferenceType n )
+{
+ it_ -= n;
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Shifting the iterator by \a n elements to the lower elements.
+//
+// \param n The number of elements.
+// \return The shifted pointer iterator.
+*/
+template< typename Type >
+inline PtrIterator<Type> PtrIterator<Type>::operator-( DifferenceType n ) const
+{
+ return PtrIterator( it_ - n );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Calculating the number of elements between two pointer iterators.
+//
+// \param it The right hand side iterator.
+// \return The number of elements between the two pointer iterators.
+*/
+template< typename Type >
+inline typename PtrIterator<Type>::DifferenceType PtrIterator<Type>::operator-( const PtrIterator& it ) const
+{
+ return it_ - it.it_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct element access.
+//
+// \param index Access index. Accesses the element \a index elements away from the current iterator position.
+// \return Handle to the accessed element.
+*/
+template< typename Type >
+inline typename PtrIterator<Type>::PointerType PtrIterator<Type>::operator[]( DifferenceType index ) const
+{
+ return it_[index];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a handle to the element at the current iterator position.
+//
+// \return Handle to the element at the current iterator position.
+*/
+template< typename Type >
+inline typename PtrIterator<Type>::PointerType PtrIterator<Type>::operator*() const
+{
+ return *it_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the element at the current iterator position.
+//
+// \return Reference to the element at the current iterator position.
+*/
+template< typename Type >
+inline typename PtrIterator<Type>::PointerType PtrIterator<Type>::operator->() const
+{
+ return *it_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access to the underlying member of the pointer iterator.
+//
+// \return Pointer to the current memory location.
+*/
+template< typename Type >
+inline const typename PtrIterator<Type>::IteratorType& PtrIterator<Type>::base() const
+{
+ return it_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name PtrIterator operators */
+//@{
+template< typename TypeL, typename TypeR >
+inline bool operator==( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs );
+
+template< typename TypeL, typename TypeR >
+inline bool operator!=( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs );
+
+template< typename TypeL, typename TypeR >
+inline bool operator<( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs );
+
+template< typename TypeL, typename TypeR >
+inline bool operator>( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs );
+
+template< typename TypeL, typename TypeR >
+inline bool operator<=( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs );
+
+template< typename TypeL, typename TypeR >
+inline bool operator>=( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two PtrIterator objects.
+//
+// \param lhs The left-hand side pointer iterator.
+// \param rhs The right-hand side pointer iterator.
+// \return \a true if the iterators point to the same element, \a false if not.
+*/
+template< typename TypeL, typename TypeR >
+inline bool operator==( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs )
+{
+ return lhs.base() == rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two PtrIterator objects.
+//
+// \param lhs The left-hand side pointer iterator.
+// \param rhs The right-hand side pointer iterator.
+// \return \a true if the iterators don't point to the same element, \a false if they do.
+*/
+template< typename TypeL, typename TypeR >
+inline bool operator!=( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs )
+{
+ return lhs.base() != rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between two PtrIterator objects.
+//
+// \param lhs The left-hand side pointer iterator.
+// \param rhs The right-hand side pointer iterator.
+// \return \a true if the left-hand side iterator points to a lower element, \a false if not.
+*/
+template< typename TypeL, typename TypeR >
+inline bool operator<( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs )
+{
+ return lhs.base() < rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between two PtrIterator objects.
+//
+// \param lhs The left-hand side pointer iterator.
+// \param rhs The right-hand side pointer iterator.
+// \return \a true if the left-hand side iterator points to a higher element, \a false if not.
+*/
+template< typename TypeL, typename TypeR >
+inline bool operator>( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs )
+{
+ return lhs.base() > rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between two PtrIterator objects.
+//
+// \param lhs The left-hand side pointer iterator.
+// \param rhs The right-hand side pointer iterator.
+// \return \a true if the left-hand side iterator points to a lower or the same element, \a false if not.
+*/
+template< typename TypeL, typename TypeR >
+inline bool operator<=( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs )
+{
+ return lhs.base() <= rhs.base();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between two PtrIterator objects.
+//
+// \param lhs The left-hand side pointer iterator.
+// \param rhs The right-hand side pointer iterator.
+// \return \a true if the left-hand side iterator points to a higher or the same element, \a false if not.
+*/
+template< typename TypeL, typename TypeR >
+inline bool operator>=( const PtrIterator<TypeL>& lhs, const PtrIterator<TypeR>& rhs )
+{
+ return lhs.base() >= rhs.base();
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/PtrVector.h b/src/cpu/blaze/util/PtrVector.h
new file mode 100644
index 00000000..7b595bba
--- /dev/null
+++ b/src/cpu/blaze/util/PtrVector.h
@@ -0,0 +1,2615 @@
+//=================================================================================================
+/*!
+// \file blaze/util/PtrVector.h
+// \brief Implementation of a vector for (polymorphic) pointers
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_PTRVECTOR_H_
+#define _BLAZE_UTIL_PTRVECTOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <algorithm>
+#include <blaze/util/Algorithm.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/constraints/Convertible.h>
+#include <blaze/util/constraints/DerivedFrom.h>
+#include <blaze/util/Exception.h>
+#include <blaze/util/policies/PtrDelete.h>
+#include <blaze/util/policies/OptimalGrowth.h>
+#include <blaze/util/PtrIterator.h>
+#include <blaze/util/Template.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of a vector for (polymorphic) pointers.
+// \ingroup util
+//
+// \section basics Basic usage
+//
+// The \a std::vector is one of the standard libraries most useful tools. It is the standard
+// solution for a dynamically allocated, automatically growing, and memory managed array. It
+// provides fast random access to its elements, since a vector guarantees that the elements
+// lie adjacent in memory and manages the dynamically allocated memory according to the RAII
+// idiom.\n
+// Yet there are some situations, where users of \a std::vector experience several drawbacks,
+// especially when \a std::vector is used in combination with pointers. For instance, a
+// \a const_iterator over a range of pointers will not allow the stored pointers to change,
+// but the objects behind the pointers remain changeable. The following example illustrates
+// that it is possible to change the values of \a double values through an iterator-to-const:
+
+ \code
+ typedef std::vector<double*> Doubles;
+
+ Doubles doubles; // Creating a vector for pointers to double values
+
+ // Filling the vector with pointers to double values. All values are initialized with 1.
+ for( size_t i=0; i<10; ++i )
+ doubles.push_back( new double( 1.0 ) );
+
+ // Accessing the first rigid body
+ Doubles::const_iterator first = doubles.begin();
+ **first = 2.0; // Changes the double value through an iterator-to-const
+ \endcode
+
+// The basic reason for this behavior is that \a std::vector is unaware of the fact that it
+// stores pointers instead of objects and therefore the pointer are considered constant, not
+// the objects behind the pointer.\n
+// Another drawback of \a std::vector is the fact that during destruction of a vector object
+// the dynamically allocated bodies are not deleted. Again, \a std::vector is unaware of the
+// special property of pointers and therefore does not apply any kind of deletion policy. It
+// basically calls the default destructor for pointers, which in turn does nothing and
+// especially does not destroy the attached objects.\n
+// A different approach is taken by the Boost \a ptr_vector. A \a ptr_vector is perfectly
+// aware of the fact that is stores pointers to dynamically objects (and in consequence may
+// only be used with pointers to dynamically allocated objects) and takes full responsibilty
+// for these resources. However, in order to accomplish this task, \a ptr_vector completely
+// abstracts from the fact that it stores pointers and provides a view as if it would contain
+// objects instead of pointers. Unfortunately, this strict memory management might cause
+// problems, for instance in case the vector to pointers is used both internally (including
+// proper resource management) and outside by the user (without any resource management).\n
+// In case both \a std::vector and \a boost::ptr_vector are not suitable data structures, the
+// Blaze library provides a special vector container for pointers, which is a cross of the
+// functionalities of the \a std::vector and \a ptr_vector. The Blaze PtrVector is not a RAII
+// class in the classic sense (as for instance the Boost \a ptr_vector) since it does not
+// strictly encapsule the resource management. As in the case of \a std::vector, it still is
+// the responsibility of a user of PtrVector to manage the resources accordingly. However,
+// PtrVector can be used internally to store pointers to dynamically allocated objects and
+// resources within RAII classes, and outside by a user as storage for handles to resources
+// that are managed elsewhere. In contrast to the \a boost::ptr_vector, the PtrVector provides
+// full access to the contained pointers, but its iterators work similar to the \a ptr_vector
+// iterator and only provide access to the objects behind the pointers, creating the illusion
+// that objects are stored instead of pointers:
+
+ \code
+ typedef blaze::PtrVector<double> Doubles;
+ Doubles doubles; // Creating an empty PtrVector for pointers to double values
+
+ doubles.pushBack( new double(1.0) ); // A new pointer-to-double is added to the vector
+
+ double_vector::iterator first = doubles.begin();
+ *first = 2.0; // No indirection needed
+
+ Doubles::ConstIterator second( first+1 );
+ *second = 3.0; // Compile time error! It is not possible to change double
+ // values via an iterator-to-const
+ \endcode
+
+// Notice the differences in the usage of the iterator in contrast to the \a std::vector and
+// \a boost::ptr_vector. In contrast to them the functions of PtrVector follow the naming
+// convention of the Blaze library (i.e. pushBack instead of push_back). In addition, the
+// underlying iterator adds an additional dereference to all access operators, which eases
+// the access to the underlying objects:
+
+ \code
+ // STL style:
+ **first = 2.0;
+
+ // pe style:
+ *first = 2.0;
+ \endcode
+
+// A noteworthy difference between the STL vector and the pointer vector is the used template
+// argument: instead of the pointer type, the Blaze pointer vector is only provided with the
+// type of the underlying objects:
+
+ \code
+ // STL style:
+ std::vector<double*> vector;
+
+ // pe style:
+ blaze::PtrVector<double> vector;
+ \endcode
+
+// Additionally, the Blaze pointer vector offers some limited possibilities to configure the
+// memory management and the growth of the internal storage, and implements special features
+// for polymorphic pointers, as for instance a convenient way to iterate over a subset of
+// polymorphic objects contained in the pointer vector.\n\n
+//
+//
+// \section polymorphic Polymorphic pointers
+//
+// For polymorphic pointers, the PtrVector class additionally offers two special iterators to
+// iterate over all objects of a specific type: the CastIterator and ConstCastIterator.
+
+ \code
+ // Definition of class A and the derived type B
+ class A { ... };
+ class B : public A { ... };
+
+ // Definition of function f for non-const pointer vectors
+ void f( blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::CastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::CastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ ...
+ }
+
+ // Definition of function f for const pointer vectors
+ void f( const blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::ConstCastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::ConstCastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ }
+ \endcode
+
+// In the example, the cast iterators are used to iterate over all objects of type \a B within
+// the pointer vector, where \a B must be a type derived from \a A. The attempt to use these
+// iterators for types that are not derived from \a A results in a compile time error. Note that
+// the usage of the cast iterators is computaionally more expensive than the use of the standard
+// iterators. Therefore these iterators should not be used unless a down-cast is really necessary,
+// e.g. in order to access a type specific function.\n\n
+//
+//
+// \section container Using a pointer vector within other container classes
+//
+// If a pointer vector is used within an other container and is used to store polymorphic pointers,
+// you might face the problem of not being able to create type definitions for the cast iterators.
+// Whereas it is possible to create typedefs for the standard iterators, it is unfortunately not
+// possible (yet) to create type definitions for template classes. In order to create a new return
+// type within the container, the following approach could be taken:
+
+ \code
+ template< typename A >
+ class Container
+ {
+ public:
+ template< typename C >
+ struct CastIterator : public blaze::PtrVector<A>::CastIterator<C>
+ {
+ CastIterator( const blaze::PtrVector<A>::CastIterator<C>& it )
+ : blaze::PtrVector<A>::CastIterator<C>( it ) // Initializing the base class
+ {}
+ };
+
+ template< typename C >
+ CastIterator<C> begin();
+
+ template< typename C >
+ CastIterator<C> end();
+
+ private:
+ blaze::PtrVector<A> vector_;
+ };
+ \endcode
+
+// Instead of a typedef within the Container class, a new class CastIterator is derived from the
+// PtrVector::CastIterator class. This approach acts similar as the typedef as a user can now
+// use the Container as follows:
+
+ \code
+ class A { ... };
+ class B : public A { ... };
+
+ Container<A>::CastIterator<B> begin;
+ \endcode
+
+// This provides the same abstraction from the internal implementation as the desired typedef. The
+// same approach could be taken for a ConstCastIterator definition.\n\n
+//
+//
+// \section adaptions Adapting a pointer vector
+//
+// The growth and deletion behavior of the PtrVector class can be adapted to any specific task. The
+// second template argument of the PtrVector specifies the growth rate. The following growth rates
+// can be selected:
+//
+// - ConstantGrowth
+// - LinearGrowth
+// - OptimalGrowth (the default behavior)
+//
+// The third template argument of the PtrVector specifies the deletion behavior for the case that
+// the pointer vector is destroyed. Note that the deletion behavior has only limited effect on
+// the memory management of the contained resources. For instance, copying a PtrVector always
+// results in a shallow copy, i.e., the contained resources are not copied/cloned. Therefore the
+// deletion policy should be considered a convenience functionality in the context of a resource
+// managing class. The following policies can be selected:
+//
+// - NoDelete : No deletion of the contained pointers.
+// - PtrDelete : Applies \a delete to all contained pointers (the default behavior).
+// - ArrayDelete : Applies \a delete[] to all contained pointers.\n\n
+*/
+template< typename T // Type
+ , typename D = PtrDelete // Deletion policy
+ , typename G = OptimalGrowth > // Growth policy
+class PtrVector
+{
+ private:
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T2, typename D2, typename G2 > friend class PtrVector;
+ /*! \endcond */
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ // Blaze naming convention
+ typedef T* ValueType; //!< Type of the underlying values.
+ typedef T* PointerType; //!< Pointer to a non-const object.
+ typedef const T* ConstPointerType; //!< Pointer to a const object.
+ typedef T*& ReferenceType; //!< Reference to a non-const object.
+ typedef T*const& ConstReferenceType; //!< Reference to a const object.
+ typedef size_t SizeType; //!< Size type of the pointer vector.
+ typedef PtrIterator<T> Iterator; //!< Iterator over non-const objects.
+ typedef PtrIterator<const T> ConstIterator; //!< Iterator over const objects.
+ typedef D DeletionPolicy; //!< Type of the deletion policy.
+ typedef G GrowthPolicy; //!< Type of the growth policy.
+
+ // STL iterator requirements
+ typedef ValueType value_type; //!< Type of the underlying values.
+ typedef PointerType pointer; //!< Pointer to a non-const object.
+ typedef ConstPointerType const_pointer; //!< Pointer to a const object.
+ typedef ReferenceType reference; //!< Reference to a non-const object.
+ typedef ConstReferenceType const_reference; //!< Reference to a const object.
+ typedef SizeType size_type; //!< Size type of the pointer vector.
+ //**********************************************************************************************
+
+ //**Forward declarations for nested classes*****************************************************
+ template< typename C > class CastIterator;
+ template< typename C > class ConstCastIterator;
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline PtrVector( SizeType initCapacity = 0 );
+ inline PtrVector( const PtrVector& pv );
+
+ template< typename T2, typename D2, typename G2 >
+ inline PtrVector( const PtrVector<T2,D2,G2>& pv );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~PtrVector();
+ //@}
+ //**********************************************************************************************
+
+ //**Assignment operators************************************************************************
+ /*!\name Assignment operators */
+ //@{
+ PtrVector& operator=( const PtrVector& pv );
+
+ template< typename T2, typename D2, typename G2 >
+ PtrVector& operator=( const PtrVector<T2,D2,G2>& pv );
+ //@}
+ //**********************************************************************************************
+
+ //**Get functions*******************************************************************************
+ /*!\name Get functions */
+ //@{
+ inline SizeType maxSize() const;
+ inline SizeType size() const;
+ template< typename C > inline SizeType size() const;
+ inline SizeType capacity() const;
+ inline bool isEmpty() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Access functions****************************************************************************
+ /*!\name Access functions */
+ //@{
+ inline ReferenceType operator[]( SizeType index );
+ inline ConstReferenceType operator[]( SizeType index ) const;
+ inline ReferenceType front();
+ inline ConstReferenceType front() const;
+ inline ReferenceType back();
+ inline ConstReferenceType back() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Iterator functions**************************************************************************
+ /*!\name Iterator functions */
+ //@{
+ inline Iterator begin();
+ inline ConstIterator begin() const;
+ template< typename C > inline CastIterator<C> begin();
+ template< typename C > inline ConstCastIterator<C> begin() const;
+
+ inline Iterator end();
+ inline ConstIterator end() const;
+ template< typename C > inline CastIterator<C> end();
+ template< typename C > inline ConstCastIterator<C> end() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Element functions***************************************************************************
+ /*!\name Element functions */
+ //@{
+ inline void pushBack ( PointerType p );
+ inline void popBack ();
+ inline void releaseBack();
+
+ template< typename IteratorType >
+ inline void assign( IteratorType first, IteratorType last );
+
+ inline Iterator insert( Iterator pos, PointerType p );
+
+ template< typename IteratorType >
+ inline void insert( Iterator pos, IteratorType first, IteratorType last );
+
+ /*! \cond BLAZE_INTERNAL */
+ template< typename IteratorType >
+ inline void insert( Iterator pos, IteratorType* first, IteratorType* last );
+ /*! \endcond */
+
+ inline Iterator erase ( Iterator pos );
+ template< typename C > inline CastIterator<C> erase ( CastIterator<C> pos );
+ inline Iterator release( Iterator pos );
+ template< typename C > inline CastIterator<C> release( CastIterator<C> pos );
+ inline void clear ();
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ void reserve( SizeType newCapacity );
+ inline void swap( PtrVector& pv ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Helper functions****************************************************************************
+ /*!\name Helper functions */
+ //@{
+ inline size_t calcCapacity ( size_t minCapacity ) const;
+ inline void deleteElement( PointerType ptr ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Insertion helper functions******************************************************************
+ /*!\name Insertion helper functions */
+ //@{
+ void insert( T**const pos, PointerType p );
+
+ /*! \cond BLAZE_INTERNAL */
+ template< typename IteratorType >
+ inline void insert( Iterator pos, IteratorType first, IteratorType last, std::input_iterator_tag );
+
+ template< typename IteratorType >
+ inline void insert( Iterator pos, IteratorType first, IteratorType last, std::random_access_iterator_tag );
+ /*! \endcond */
+
+ template< typename IteratorType >
+ void insert( T** pos, IteratorType first, IteratorType last, SizeType n );
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ SizeType size_; //!< The current size of the pointer vector.
+ SizeType capacity_; //!< The capacity of the pointer vector.
+ PointerType* begin_; //!< Pointer to the first element of the pointer vector.
+ PointerType* end_; //!< Pointer to the last element of the pointer vector.
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**CastIterator/ConstCastIterator comparison operators*****************************************
+ // The following comparison operators cannot be defined as namespace or member functions
+ // but have to be injected into the surrounding scope via the Barton-Nackman trick since
+ // the template arguments of nested templates cannot be deduced (C++ standard 14.8.2.4/4).
+ /*!\name CastIterator/ConstCastIterator comparison operators */
+ //@{
+
+ //**********************************************************************************************
+ /*!\brief Equality comparison between two CastIterator objects.
+ //
+ // \param lhs The left hand side cast iterator.
+ // \param rhs The right hand side cast iterator.
+ // \return \a true if the iterators point to the same element, \a false if not.
+ */
+ template< typename L, typename R >
+ friend inline bool operator==( const CastIterator<L>& lhs, const CastIterator<R>& rhs )
+ {
+ return lhs.base() == rhs.base();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Equality comparison between a CastIterator and a ConstCastIterator.
+ //
+ // \param lhs The left hand side cast iterator.
+ // \param rhs The right hand side constant cast iterator.
+ // \return \a true if the iterators point to the same element, \a false if not.
+ */
+ template< typename L, typename R >
+ friend inline bool operator==( const CastIterator<L>& lhs, const ConstCastIterator<R>& rhs )
+ {
+ return lhs.base() == rhs.base();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Equality comparison between a ConstCastIterator and a CastIterator.
+ //
+ // \param lhs The left hand side constant cast iterator.
+ // \param rhs The right hand side cast iterator.
+ // \return \a true if the iterators point to the same element, \a false if not.
+ */
+ template< typename L, typename R >
+ friend inline bool operator==( const ConstCastIterator<L>& lhs, const CastIterator<R>& rhs )
+ {
+ return lhs.base() == rhs.base();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Equality comparison between two ConstCastIterator objects.
+ //
+ // \param lhs The left hand side constant cast iterator.
+ // \param rhs The right hand side constant cast iterator.
+ // \return \a true if the iterators point to the same element, \a false if not.
+ */
+ template< typename L, typename R >
+ friend inline bool operator==( const ConstCastIterator<L>& lhs, const ConstCastIterator<R>& rhs )
+ {
+ return lhs.base() == rhs.base();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Inequality comparison between two CastIterator objects.
+ //
+ // \param lhs The left hand side cast iterator.
+ // \param rhs The right hand side cast iterator.
+ // \return \a true if the iterators don't point to the same element, \a false if they do.
+ */
+ template< typename L, typename R >
+ friend inline bool operator!=( const CastIterator<L>& lhs, const CastIterator<R>& rhs )
+ {
+ return lhs.base() != rhs.base();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Inequality comparison between a CastIterator and a ConstCastIterator.
+ //
+ // \param lhs The left hand side cast iterator.
+ // \param rhs The right hand side constant cast iterator.
+ // \return \a true if the iterators don't point to the same element, \a false if they do.
+ */
+ template< typename L, typename R >
+ friend inline bool operator!=( const CastIterator<L>& lhs, const ConstCastIterator<R>& rhs )
+ {
+ return lhs.base() != rhs.base();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Inequality comparison between a ConstCastIterator and a CastIterator.
+ //
+ // \param lhs The left hand side constant cast iterator.
+ // \param rhs The right hand side cast iterator.
+ // \return \a true if the iterators don't point to the same element, \a false if they do.
+ */
+ template< typename L, typename R >
+ friend inline bool operator!=( const ConstCastIterator<L>& lhs, const CastIterator<R>& rhs )
+ {
+ return lhs.base() != rhs.base();
+ }
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ /*!\brief Inequality comparison between two ConstCastIterator objects.
+ //
+ // \param lhs The left hand side constant cast iterator.
+ // \param rhs The right hand side constant cast iterator.
+ // \return \a true if the iterators don't point to the same element, \a false if they do.
+ */
+ template< typename L, typename R >
+ friend inline bool operator!=( const ConstCastIterator<L>& lhs, const ConstCastIterator<R>& rhs )
+ {
+ return lhs.base() != rhs.base();
+ }
+ //**********************************************************************************************
+
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Standard constructor for PtrVector.
+//
+// \param initCapacity The initial capacity of the pointer vector.
+//
+// The default initial capacity of the pointer vector is specified by the selected growth policy.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline PtrVector<T,D,G>::PtrVector( SizeType initCapacity )
+ : size_( 0 ) // Current size of the pointer vector
+ , capacity_( initCapacity ) // Capacity of the pointer vector
+ , begin_( new PointerType[initCapacity] ) // Pointer to the first element
+ , end_( begin_ ) // Pointer to the last element
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Copy constructor for PtrVector.
+//
+// \param pv The pointer vector to be copied.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline PtrVector<T,D,G>::PtrVector( const PtrVector& pv )
+ : size_( pv.size_ ) // Current size of the pointer vector
+ , capacity_( pv.size_ ) // Capacity of the pointer vector
+ , begin_( new PointerType[capacity_] ) // Pointer to the first element
+ , end_( begin_+size_ ) // Pointer to the last element
+{
+ for( SizeType i=0; i<size_; ++i )
+ begin_[i] = pv.begin_[i];
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different PtrVector instances.
+//
+// \param pv The pointer vector to be copied.
+*/
+template< typename T // Type of the pointer vector
+ , typename D // Deletion policy of the pointer vector
+ , typename G > // Growth policy of the pointer vector
+template< typename T2 // Type of the foreign pointer vector
+ , typename D2 // Deletion policy of the foreign pointer vector
+ , typename G2 > // Growth policy of the foreign pointer vector
+inline PtrVector<T,D,G>::PtrVector( const PtrVector<T2,D2,G2>& pv )
+ : size_( pv.size_ ) // Current size of the pointer vector
+ , capacity_( pv.size_ ) // Capacity of the pointer vector
+ , begin_( new PointerType[capacity_] ) // Pointer to the first element
+ , end_( begin_+size_ ) // Pointer to the last element
+{
+ for( SizeType i=0; i<size_; ++i )
+ begin_[i] = pv.begin_[i];
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Destructor for PtrVector.
+//
+// In the destructor, the selected deletion policy is applied to all elements of the pointer
+// vector.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline PtrVector<T,D,G>::~PtrVector()
+{
+ for( PointerType* it=begin_; it!=end_; ++it )
+ deleteElement( *it );
+ delete [] begin_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Copy assignment operator for PtrVector.
+//
+// \param pv The pointer vector to be copied.
+// \return Reference to the assigned pointer vector.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+PtrVector<T,D,G>& PtrVector<T,D,G>::operator=( const PtrVector& pv )
+{
+ if( &pv == this ) return *this;
+
+ if( pv.size_ > capacity_ ) {
+ PointerType* newBegin( new PointerType[pv.size_] );
+ end_ = std::copy( pv.begin_, pv.end_, newBegin );
+ std::swap( begin_, newBegin );
+ delete [] newBegin;
+
+ size_ = pv.size_;
+ capacity_ = pv.size_;
+ }
+ else {
+ end_ = std::copy( pv.begin_, pv.end_, begin_ );
+ size_ = pv.size_;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assignment operator for different PtrVector instances.
+//
+// \param pv The pointer vector to be copied.
+// \return Reference to the assigned pointer vector.
+*/
+template< typename T // Type of the pointer vector
+ , typename D // Deletion policy of the pointer vector
+ , typename G > // Growth policy of the pointer vector
+template< typename T2 // Type of the foreign pointer vector
+ , typename D2 // Deletion policy of the foreign pointer vector
+ , typename G2 > // Growth policy of the foreign pointer vector
+PtrVector<T,D,G>& PtrVector<T,D,G>::operator=( const PtrVector<T2,D2,G2>& pv )
+{
+ if( pv.size_ > capacity_ ) {
+ PointerType* newBegin( new PointerType[pv.size_] );
+ end_ = std::copy( pv.begin_, pv.end_, newBegin );
+ std::swap( begin_, newBegin );
+ delete [] newBegin;
+
+ size_ = pv.size_;
+ capacity_ = pv.size_;
+ }
+ else {
+ end_ = std::copy( pv.begin_, pv.end_, begin_ );
+ size_ = pv.size_;
+ }
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GET FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the maximum possible size of a pointer vector.
+//
+// \return The maximum possible size.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::SizeType PtrVector<T,D,G>::maxSize() const
+{
+ return SizeType(-1) / sizeof(PointerType);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current size of the pointer vector.
+//
+// \return The current size.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::SizeType PtrVector<T,D,G>::size() const
+{
+ return size_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the total number of objects of type \a C contained in the pointer vector.
+//
+// \return The total number of objects of type \a C.
+//
+// This function calculates the total number of objects of type \a C within the pointer vector,
+// where \a C is a type derived from the type \a T of objects contained in the pointer vector.
+// The attempt to use this function for types that are not derived from \a T results in a
+// compile time error.
+
+ \code
+ // Definition of class A and the derived type B
+ class A { ... };
+ class B : public A { ... };
+
+ // Definition of a pointer vector for class A
+ typedef blaze::PtrVector<A> AVector;
+ AVector vector;
+
+ AVector::SizeType total = vector.size(); // Calculating the total number of pointers
+ AVector::SizeType numB = vector.size<B>(); // Calculating the total number of B objects
+ \endcode
+
+// \note The total number of objects of type \a C is not cached inside the pointer vector
+// but is calculated each time the function is called. Using the templated version of size()
+// to calculate the total number objects of type \a C is therefore more expensive than using
+// the non-template version of size() to get the total number of pointers in the vector!
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::SizeType PtrVector<T,D,G>::size() const
+{
+ // The polymorphicCount() function returns the number of objects with dynamic type 'C'
+ // contained in the range [begin,end). An equivalent code might look like this:
+ //
+ // SizeType count( 0 );
+ // for( PointerType* it=begin_; it!=end_; ++it )
+ // if( dynamic_cast<C*>( *it ) ) ++count;
+ // return count;
+ //
+ // However, the specialization of polymorphicCount() for special type combinations is
+ // much more efficient (and easier) than the specialization of this function!
+ return polymorphicCount<C>( begin_, end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the capacity of the pointer vector.
+//
+// \return The capacity.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::SizeType PtrVector<T,D,G>::capacity() const
+{
+ return capacity_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns \a true if the pointer vector has no elements.
+//
+// \return \a true if the pointer vector is empty, \a false if it is not.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline bool PtrVector<T,D,G>::isEmpty() const
+{
+ return size_ == 0;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the pointer vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..size-1]\f$.
+// \return Handle to the accessed element.
+//
+// \note No runtime check is performed to insure the validity of the access index.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::ReferenceType PtrVector<T,D,G>::operator[]( SizeType index )
+{
+ return *(begin_+index);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Subscript operator for the direct access to the pointer vector elements.
+//
+// \param index Access index. The index has to be in the range \f$[0..size-1]\f$.
+// \return Handle to the accessed element.
+//
+// \note No runtime check is performed to insure the validity of the access index.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::ConstReferenceType PtrVector<T,D,G>::operator[]( SizeType index ) const
+{
+ return *(begin_+index);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a reference to the first element of the pointer vector.
+//
+// \return Handle to the first element.
+//
+// \note No runtime check is performed if the first element exists!
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::ReferenceType PtrVector<T,D,G>::front()
+{
+ BLAZE_USER_ASSERT( size_ > 0, "Pointer vector is empty, invalid access to the front element" );
+ return *begin_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a reference to the first element of the pointer vector.
+//
+// \return Handle to the first element.
+//
+// \note No runtime check is performed if the first element exists!
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::ConstReferenceType PtrVector<T,D,G>::front() const
+{
+ BLAZE_USER_ASSERT( size_ > 0, "Pointer vector is empty, invalid access to the front element" );
+ return *begin_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a reference to the last element of the pointer vector.
+//
+// \return Handle to the last element.
+//
+// \note No runtime check is performed if the last element exists!
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::ReferenceType PtrVector<T,D,G>::back()
+{
+ BLAZE_USER_ASSERT( size_ > 0, "Pointer vector is empty, invalid access to the back element" );
+ return *(end_-1);
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a reference to the last element of the pointer vector.
+//
+// \return Handle to the last element.
+//
+// \note No runtime check is performed if the last element exists!
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::ConstReferenceType PtrVector<T,D,G>::back() const
+{
+ BLAZE_USER_ASSERT( size_ > 0, "Pointer vector is empty, invalid access to the back element" );
+ return *(end_-1);
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ITERATOR FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the beginning of the pointer vector.
+//
+// \return Iterator to the beginning of the pointer vector.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::Iterator PtrVector<T,D,G>::begin()
+{
+ return Iterator( begin_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the beginning of the pointer vector.
+//
+// \return Iterator to the beginning of the pointer vector.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::ConstIterator PtrVector<T,D,G>::begin() const
+{
+ return ConstIterator( begin_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of type \a C within the pointer vector.
+//
+// \return Iterator to the first element of type \a C.
+//
+// This function returns an iterator to the first element of type \a C within in the pointer
+// vector, where \a C is a type derived from the type \a T of objects contained in the pointer
+// vector. In case there is no element of type \a C contained in the vector, an iterator just
+// past the last element of the pointer vector is returned. In combination with the according
+// end function (see example), this iterator allows to iterate over all objects of type \a C
+// in the range of the pointer vector. The attempt to use this function for types that are not
+// derived from \a T results in a compile time error.
+
+ \code
+ // Definition of class A and the derived type B
+ class A { ... };
+ class B : public A { ... };
+
+ // Definition of function f for non-const pointer vectors
+ void f( blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::CastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::CastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ ...
+ }
+
+ // Definition of function f for const pointer vectors
+ void f( const blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::ConstCastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::ConstCastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ }
+ \endcode
+
+// \note Using the templated versions of begin() and end() to traverse all elements of type
+// \a C in the element range of the pointer vector is more expensive than using the non-template
+// versions to traverse the entire range of elements. Use this function only if you require a
+// type-specific member of type \a C.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C> PtrVector<T,D,G>::begin()
+{
+ return CastIterator<C>( begin_, end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator to the first element of type \a C within the pointer vector.
+//
+// \return Iterator to the first element of type \a C.
+//
+// This function returns an iterator to the first element of type \a C within in the pointer
+// vector, where \a C is a type derived from the type \a T of objects contained in the pointer
+// vector. In case there is no element of type \a C contained in the vector, an iterator just
+// past the last element of the pointer vector is returned. In combination with the according
+// end function (see example), this iterator allows to iterate over all objects of type \a C
+// in the range of the pointer vector. The attempt to use this function for types that are not
+// derived from \a T results in a compile time error.
+
+ \code
+ // Definition of class A and the derived type B
+ class A { ... };
+ class B : public A { ... };
+
+ // Definition of function f for non-const pointer vectors
+ void f( blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::CastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::CastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ ...
+ }
+
+ // Definition of function f for const pointer vectors
+ void f( const blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::ConstCastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::ConstCastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ }
+ \endcode
+
+// \note Using the templated versions of begin() and end() to traverse all elements of type
+// \a C in the element range of the pointer vector is more expensive than using the non-template
+// version to traverse the entire range of elements. Use this function only if you require a
+// type-specific member of type \a C.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE ConstCastIterator<C> PtrVector<T,D,G>::begin() const
+{
+ return ConstCastIterator<C>( begin_, end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the pointer vector.
+//
+// \return Iterator just past the last element of the pointer vector.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::Iterator PtrVector<T,D,G>::end()
+{
+ return Iterator( end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the pointer vector.
+//
+// \return Iterator just past the last element of the pointer vector.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::ConstIterator PtrVector<T,D,G>::end() const
+{
+ return ConstIterator( end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the pointer vector.
+//
+// \return Iterator just past the last element of the pointer vector.
+//
+// This function returns an iterator just past the last element of the pointer vector. In
+// combination with the according begin function (see example), this iterator allows to iterate
+// over all objects of type \a C in the range of the pointer vector. The attempt to use this
+// function for types that are not derived from \a T results in a compile time error.
+
+ \code
+ // Definition of class A and the derived type B
+ class A { ... };
+ class B : public A { ... };
+
+ // Definition of function f for non-const pointer vectors
+ void f( blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::CastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::CastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ ...
+ }
+
+ // Definition of function f for const pointer vectors
+ void f( const blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::ConstCastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::ConstCastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ }
+ \endcode
+
+// \note Using the templated versions of begin() and end() to traverse all elements of type
+// \a C in the element range of the pointer vector is more expensive than using the non-template
+// versions to traverse the entire range of elements. Use this function only if you require a
+// type-specific member of type \a C.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C> PtrVector<T,D,G>::end()
+{
+ return CastIterator<C>( end_, end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns an iterator just past the last element of the pointer vector.
+//
+// \return Iterator just past the last element of the pointer vector.
+//
+// This function returns an iterator just past the last element of the pointer vector. In
+// combination with the according begin function (see example), this iterator allows to iterate
+// over all objects of type \a C in the range of the pointer vector. The attempt to use this
+// function for types that are not derived from \a T results in a compile time error.
+
+ \code
+ // Definition of class A and the derived type B
+ class A { ... };
+ class B : public A { ... };
+
+ // Definition of function f for non-const pointer vectors
+ void f( blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::CastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::CastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ ...
+ }
+
+ // Definition of function f for const pointer vectors
+ void f( const blaze::PtrVector<A>& vector )
+ {
+ blaze::PtrVector<A>::ConstCastIterator<B> begin = vector.begin<B>();
+ blaze::PtrVector<A>::ConstCastIterator<B> end = vector.end<B>();
+
+ // Loop over all objects of type B contained in the vector
+ for( ; begin!=end; ++begin )
+ }
+ \endcode
+
+// \note Using the templated versions of begin() and end() to traverse all elements of type
+// \a C in the element range of the pointer vector is more expensive than using the non-template
+// version to traverse the entire range of elements. Use this function only if you require a
+// type-specific member of type \a C.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE ConstCastIterator<C> PtrVector<T,D,G>::end() const
+{
+ return ConstCastIterator<C>( end_, end_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ELEMENT FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Adding an element to the end of the pointer vector.
+//
+// \param p The pointer to be added to the end of the pointer vector.
+// \return void
+// \exception std::length_error Maximum pointer vector length exceeded.
+//
+// The pushBack function runs in constant time.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline void PtrVector<T,D,G>::pushBack( PointerType p )
+{
+ if( size_ != capacity_ ) {
+ *end_ = p;
+ ++end_;
+ ++size_;
+ }
+ else {
+ insert( end_, p );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing an element from the end of the pointer vector.
+//
+// \return void
+//
+// This function removes the element at the end of the pointer vector, i.e. the element
+// is deleted according to the deletion policy and removed from the vector. Note that in
+// case the deletion policy is NoDelete, this function is identical to the releaseBack()
+// function.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline void PtrVector<T,D,G>::popBack()
+{
+ deleteElement( *--end_ );
+ --size_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Releasing the element at the end of the pointer vector.
+//
+// \return void
+//
+// This function releases the element at the end of the pointer vector, i.e. the element is
+// removed without applying the deletion policy. Therefore the responsibility to delete the
+// element is passed to the function caller. Note that in case the deletion policy is NoDelete,
+// this function is identical to the popBack() function.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline void PtrVector<T,D,G>::releaseBack()
+{
+ --end_;
+ --size_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Assigning a range of elements to the pointer vector.
+//
+// \param first Iterator to the first element of the element range.
+// \param last Iterator to the element one past the last element of the element range.
+// \return void
+// \exception std::length_error Maximum pointer vector length exceeded.
+//
+// This functions assigns the elements in the range \f$ [first,last) \f$ to the pointer vector.
+// All elements previously contained in the pointer vector are removed. The assign function runs
+// in linear time.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename IteratorType >
+inline void PtrVector<T,D,G>::assign( IteratorType first, IteratorType last )
+{
+ clear();
+ insert( end(), first, last );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting an element into the pointer vector.
+//
+// \param pos The position before which the element is inserted.
+// \param p The pointer to be inserted into the pointer vector.
+// \return Iterator to the inserted element.
+// \exception std::length_error Maximum pointer vector length exceeded.
+//
+// The insert function runs in linear time. Note however that inserting elements into a pointer
+// vector can be a relatively time-intensive operation.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::Iterator PtrVector<T,D,G>::insert( Iterator pos, PointerType p )
+{
+ T** const base = const_cast<T**>( pos.base() );
+ const SizeType diff( base - begin_ );
+
+ if( size_ != capacity_ && base == end_ ) {
+ *end_ = p;
+ ++end_;
+ ++size_;
+ }
+ else {
+ insert( base, p );
+ }
+
+ return Iterator( begin_+diff );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting a range of elements into the pointer vector.
+//
+// \param pos The position before which the elements are inserted.
+// \param first Iterator to the first element of the element range.
+// \param last Iterator to the element one past the last element of the element range.
+// \return void
+// \exception std::length_error Maximum pointer vector length exceeded.
+//
+// This functions inserts the elements in the range \f$ [first,last) \f$ into the pointer vector.
+// The insert function runs in linear time. Note however that inserting elements into a pointer
+// vector can be a relatively time-intensive operation.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename IteratorType >
+inline void PtrVector<T,D,G>::insert( Iterator pos, IteratorType first, IteratorType last )
+{
+ insert( pos, first, last, typename IteratorType::iterator_category() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting a range of elements into the pointer vector.
+//
+// \param pos The position before which the elements are inserted.
+// \param first Pointer to the first element of the element range.
+// \param last Pointer to the element one past the last element of the element range.
+// \return void
+// \exception std::length_error Maximum pointer vector length exceeded.
+//
+// This functions inserts the elements in the range \f$ [first,last) \f$ into the pointer vector.
+// The insert function runs in linear time. Note however that inserting elements into a pointer
+// vector can be a relatively time-intensive operation.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename IteratorType >
+inline void PtrVector<T,D,G>::insert( Iterator pos, IteratorType* first, IteratorType* last )
+{
+ insert( pos, first, last, std::random_access_iterator_tag() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing an element from the pointer vector.
+//
+// \param pos The position of the element to be removed.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the pointer vector, i.e. the element is deleted
+// according to the deletion policy of the pointer vector and removed from the vector.
+// Note that in case the deletion policy is NoDelete, this function is identical to the
+// release() function.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::Iterator PtrVector<T,D,G>::erase( Iterator pos )
+{
+ T** const base = const_cast<T**>( pos.base() );
+ deleteElement( *base );
+ std::copy( base+1, end_, base );
+
+ --size_;
+ --end_;
+
+ return pos;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing an element from the pointer vector.
+//
+// \param pos The position of the element to be removed.
+// \return Iterator to the element after the erased element.
+//
+// This function erases an element from the pointer vector, i.e. the element is deleted
+// according to the deletion policy of the pointer vector and removed from the vector.
+// Note that in case the deletion policy is NoDelete, this function is identical to the
+// release() function.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C>
+ PtrVector<T,D,G>::erase( CastIterator<C> pos )
+{
+ T** const base = const_cast<T**>( pos.base() );
+ deleteElement( *base );
+ std::copy( base+1, end_, base );
+
+ --size_;
+ --end_;
+
+ return CastIterator<C>( base, end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Releasing an element from the pointer vector.
+//
+// \param pos The position of the element to be released.
+// \return Iterator to the element after the released element.
+//
+// This function releases an element from the pointer vector, i.e. the element is removed
+// without applying the deletion policy. Therefore the responsibility to delete the element
+// is passed to the function caller.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline typename PtrVector<T,D,G>::Iterator PtrVector<T,D,G>::release( Iterator pos )
+{
+ T** const base = const_cast<T**>( pos.base() );
+ std::copy( base+1, end_, base );
+
+ --size_;
+ --end_;
+
+ return pos;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Releasing an element from the pointer vector.
+//
+// \param pos The position of the element to be released.
+// \return Iterator to the element after the released element.
+//
+// This function releases an element from the pointer vector, i.e. the element is removed
+// without applying the deletion policy. Therefore the responsibility to delete the element
+// is passed to the function caller.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C>
+ PtrVector<T,D,G>::release( CastIterator<C> pos )
+{
+ T** const base = const_cast<T**>( pos.base() );
+ std::copy( base+1, end_, base );
+
+ --size_;
+ --end_;
+
+ return CastIterator<C>( base, end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing all elements from the pointer vector.
+//
+// \return void
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline void PtrVector<T,D,G>::clear()
+{
+ for( PointerType* it=begin_; it!=end_; ++it )
+ deleteElement( *it );
+
+ end_ = begin_;
+ size_ = 0;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Setting the minimum capacity of the pointer vector.
+//
+// \param newCapacity The new minimum capacity of the pointer vector.
+// \return void
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+void PtrVector<T,D,G>::reserve( SizeType newCapacity )
+{
+ if( newCapacity > capacity_ )
+ {
+ // Calculating the new capacity
+ newCapacity = calcCapacity( newCapacity );
+
+ // Allocating a new array
+ PointerType* tmp = new PointerType[newCapacity];
+
+ // Replacing the old array
+ std::copy( begin_, end_, tmp );
+ std::swap( tmp, begin_ );
+ capacity_ = newCapacity;
+ end_ = begin_ + size_;
+ delete [] tmp;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two pointer vectors.
+//
+// \param pv The pointer vector to be swapped.
+// \return void
+// \exception no-throw guarantee.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline void PtrVector<T,D,G>::swap( PtrVector& pv ) noexcept
+{
+ // By using the 'std::swap' function to swap all member variables,
+ // the function can give the nothrow guarantee.
+ std::swap( size_, pv.size_ );
+ std::swap( capacity_, pv.capacity_ );
+ std::swap( begin_, pv.begin_ );
+ std::swap( end_, pv.end_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// HELPER FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Calculating the new capacity of the vector based on its growth policy.
+//
+// \param minCapacity The minimum necessary capacity.
+// \return The new capacity.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline size_t PtrVector<T,D,G>::calcCapacity( size_t minCapacity ) const
+{
+ BLAZE_INTERNAL_ASSERT( minCapacity > capacity_, "Invalid new vector capacity" );
+ const size_t newCapacity( GrowthPolicy()( capacity_, minCapacity ) );
+ BLAZE_INTERNAL_ASSERT( newCapacity > capacity_, "Invalid new vector capacity" );
+ return newCapacity;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deleting an element of the pointer vector according to the deletion policy.
+//
+// \param ptr The element to be deleted.
+// \return void
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline void PtrVector<T,D,G>::deleteElement( PointerType ptr ) const
+{
+ DeletionPolicy()( ptr );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// INSERTION HELPER FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Inserting an element into the pointer vector.
+//
+// \param pos The position before which the element is inserted.
+// \param p The pointer to be inserted into the pointer vector.
+// \return void
+// \exception std::length_error Maximum pointer vector length exceeded.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+void PtrVector<T,D,G>::insert( T**const pos, PointerType p )
+{
+ if( size_ != capacity_ ) {
+ std::copy_backward( pos, end_, end_+1 );
+ *pos = p;
+ ++end_;
+ ++size_;
+ }
+ else if( size_ == maxSize() ) {
+ BLAZE_THROW_LENGTH_ERROR( "Maximum pointer vector length exceeded!" );
+ }
+ else {
+ SizeType newCapacity( calcCapacity( capacity_+1 ) );
+ if( newCapacity > maxSize() || newCapacity < capacity_ ) newCapacity = maxSize();
+
+ PointerType* newBegin = new PointerType[newCapacity];
+ PointerType* newEnd = std::copy( begin_, pos, newBegin );
+ *newEnd = p;
+ ++newEnd;
+ end_ = std::copy( pos, end_, newEnd );
+
+ std::swap( newBegin, begin_ );
+ delete [] newBegin;
+ capacity_ = newCapacity;
+ ++size_;
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting a range of elements into the pointer vector.
+//
+// \param pos The position before which the elements are inserted.
+// \param first Iterator to the first element of the element range.
+// \param last Iterator to the element one past the last element of the element range.
+// \return void
+// \exception std::length_error Maximum pointer vector length exceeded.
+//
+// This functions inserts the elements in the range \f$ [first,last) \f$ into the pointer vector.
+// The iterators are treated as input iterators.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename IteratorType >
+inline void PtrVector<T,D,G>::insert( Iterator pos, IteratorType first, IteratorType last,
+ std::input_iterator_tag )
+{
+ for( ; first!=last; ++first ) {
+ pos = insert( pos, *first );
+ ++pos;
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Inserting a range of elements into the pointer vector.
+//
+// \param pos The position before which the elements are inserted.
+// \param first Iterator to the first element of the element range.
+// \param last Iterator to the element one past the last element of the element range.
+// \return void
+// \exception std::length_error Maximum pointer vector length exceeded.
+//
+// This functions inserts the elements in the range \f$ [first,last) \f$ into the pointer vector.
+// The iterators are treated as random access iterators.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename IteratorType >
+inline void PtrVector<T,D,G>::insert( Iterator pos, IteratorType first, IteratorType last,
+ std::random_access_iterator_tag )
+{
+ T** const base = const_cast<T**>( pos.base() );
+ const SizeType diff( last - first );
+
+ if( size_+diff <= capacity_ && base == end_ ) {
+ for( ; first!=last; ++first, ++end_ ) {
+ *end_ = *first;
+ }
+ size_ += diff;
+ }
+ else {
+ insert( base, first, last, diff );
+ }
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inserting a range of elements into the pointer vector.
+//
+// \param pos The position before which the elements are inserted.
+// \param first Iterator to the first element of the element range.
+// \param last Iterator to the element one past the last element of the element range.
+// \param n The number of elements to be inserted.
+// \return void
+// \exception std::length_error Maximum pointer vector length exceeded.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename IteratorType >
+void PtrVector<T,D,G>::insert( T** pos, IteratorType first, IteratorType last, SizeType n )
+{
+ const SizeType newSize( size_ + n );
+
+ if( newSize <= capacity_ ) {
+ std::copy_backward( pos, end_, end_+n );
+ for( ; first!=last; ++first, ++pos ) {
+ *pos = *first;
+ }
+ end_ += n;
+ size_ = newSize;
+ }
+ else if( newSize > maxSize() || newSize < size_ ) {
+ BLAZE_THROW_LENGTH_ERROR( "Maximum pointer vector length exceeded!" );
+ }
+ else {
+ PointerType* newBegin = new PointerType[newSize];
+ PointerType* newEnd = std::copy( begin_, pos, newBegin );
+
+ for( ; first!=last; ++first, ++newEnd ) {
+ *newEnd = *first;
+ }
+
+ end_ = std::copy( pos, end_, newEnd );
+
+ std::swap( newBegin, begin_ );
+ delete [] newBegin;
+ capacity_ = newSize;
+ size_ = newSize;
+ }
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name PtrVector operators */
+//@{
+template< typename T, typename D, typename G >
+inline bool operator==( const PtrVector<T,D,G>& lhs, const PtrVector<T,D,G>& rhs );
+
+template< typename T, typename D, typename G >
+inline bool operator!=( const PtrVector<T,D,G>& lhs, const PtrVector<T,D,G>& rhs );
+
+template< typename T, typename D, typename G >
+inline void swap( PtrVector<T,D,G>& a, PtrVector<T,D,G>& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two pointer vectors.
+//
+// \param lhs The left hand side pointer vector.
+// \param rhs The right hand side pointer vector.
+// \return \a true if the two pointer vectors are equal, \a false if they are not.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline bool operator==( const PtrVector<T,D,G>& lhs, const PtrVector<T,D,G>& rhs )
+{
+ return lhs.size() == rhs.size() && std::equal( lhs.begin(), lhs.end(), rhs.begin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two pointer vectors.
+//
+// \param lhs The left hand side pointer vector.
+// \param rhs The right hand side pointer vector.
+// \return \a true if the two pointer vectors are inequal, \a false if they are not.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline bool operator!=( const PtrVector<T,D,G>& lhs, const PtrVector<T,D,G>& rhs )
+{
+ return lhs.size() != rhs.size() || !std::equal( lhs.begin(), lhs.end(), rhs.begin() );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two pointer vectors.
+//
+// \param a The first pointer vector to be swapped.
+// \param b The second pointer vector to be swapped.
+// \return void
+// \exception no-throw guarantee.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+inline void swap( PtrVector<T,D,G>& a, PtrVector<T,D,G>& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// NESTED CLASS PTRVECTOR::CASTITERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Dynamic cast iterator for polymorphic pointer vectors.
+// \ingroup util
+//
+// The CastIterator class is part of the PtrVector class and represent a forward iterator
+// over all elements of type \a C contained in a range of elements of type \a T, where \a C
+// is a type derived from \a T.
+
+ \code
+ class A { ... };
+ class B : public class A { ... };
+
+ blaze::PtrVector<A>::CastIterator<B> begin;
+ blaze::PtrVector<A>::CastIterator<B> end;
+
+ // Loop over all elements of type B within the range [begin..end)
+ for( ; begin!=end; ++begin )
+ ...
+ \endcode
+
+// \note Using a CastIterator is computationally more expensive than using a standard iterator
+// over all elements contained in the vector.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+class PtrVector<T,D,G>::CastIterator
+{
+ public:
+ //**Type definitions****************************************************************************
+ // Blaze naming convention
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef C* ValueType; //!< Type of the underlying pointers.
+ typedef C* PointerType; //!< Pointer return type.
+ typedef C* const& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+ typedef T* const* IteratorType; //!< Type of the internal pointer.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline CastIterator();
+ inline CastIterator( IteratorType begin, IteratorType end );
+
+ template< typename Other >
+ inline CastIterator( const CastIterator<Other>& it );
+
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Copy assignment operator********************************************************************
+ // No explicitly declared copy assignment operator.
+ //**********************************************************************************************
+
+ //**Operators***********************************************************************************
+ /*!\name Operators */
+ //@{
+ inline CastIterator& operator++();
+ inline CastIterator operator++( int );
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline PointerType operator*() const;
+ inline PointerType operator->() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline const IteratorType& base() const;
+ inline const IteratorType& stop() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ IteratorType cur_; //!< Pointer to the current memory location.
+ IteratorType end_; //!< Pointer to the element one past the last element in the element range.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default constructor for CastIterator.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline PtrVector<T,D,G>::CastIterator<C>::CastIterator()
+ : cur_( nullptr ) // Pointer to the current memory location
+ , end_( nullptr ) // Pointer to the element one past the last element in the element range
+{
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_DERIVED_FROM( C, T );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Standard constructor for CastIterator.
+//
+// \param begin The beginning of the element range.
+// \param end The end of the element range.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline PtrVector<T,D,G>::CastIterator<C>::CastIterator( IteratorType begin, IteratorType end )
+ : cur_(begin) // Pointer to the current memory location
+ , end_(end) // Pointer to the element one past the last element in the element range
+{
+ // The polymorphicFind() function finds the next pointer to an object with dynamic type 'C'
+ // contained in the range [cur_,end). An equivalent code might look like this:
+ //
+ // while( cur_ != end_ && !dynamic_cast<C*>( *cur_ ) ) ++cur_;
+ //
+ // However, the specialization of polymorphicFind() for special type combinations is much
+ // more efficient (and way easier!) than the specialization of this function!
+ cur_ = polymorphicFind<C>( cur_, end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different CastIterator instances.
+//
+// \param it The foreign CastIterator instance to be copied.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+template< typename Other > // The foreign cast iterator type
+inline PtrVector<T,D,G>::CastIterator<C>::CastIterator( const CastIterator<Other>& it )
+ : cur_( it.base() ) // Pointer to the current memory location
+ , end_( it.stop() ) // Pointer to the element one past the last element in the element range
+{
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_DERIVED_FROM( C, T );
+ BLAZE_CONSTRAINT_MUST_BE_CONVERTIBLE( Other*, C* );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Pre-increment operator.
+//
+// \return Reference to the incremented cast iterator.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C>&
+ PtrVector<T,D,G>::CastIterator<C>::operator++()
+{
+ // The polymorphicFind() function finds the next pointer to an object with dynamic type 'C'
+ // contained in the range [cur_+1,end). An equivalent code might look like this:
+ //
+ // while( ++cur_ != end_ && !dynamic_cast<C*>( *cur_ ) ) {}
+ //
+ // However, the specialization of polymorphicFind() for special type combinations is much
+ // more efficient (and way easier!) than the specialization of this function!
+ cur_ = polymorphicFind<C>( ++cur_, end_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Post-increment operator.
+//
+// \return The incremented cast iterator.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C>
+ PtrVector<T,D,G>::CastIterator<C>::operator++( int )
+{
+ CastIterator tmp( *this );
+
+ // The polymorphicFind() function finds the next pointer to an object with dynamic type 'C'
+ // contained in the range [cur_+1,end). An equivalent code might look like this:
+ //
+ // while( ++cur_ != end_ && !dynamic_cast<C*>( *cur_ ) ) {}
+ //
+ // However, the specialization of polymorphicFind() for special type combinations is much
+ // more efficient (and way easier!) than the specialization of this function!
+ cur_ = polymorphicFind<C>( ++cur_, end_ );
+
+ return tmp;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns a handle to the element at the current iterator position.
+//
+// \return Handle to the element at the current iterator position.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C>::PointerType
+ PtrVector<T,D,G>::CastIterator<C>::operator*() const
+{
+ return static_cast<C*>( *cur_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the element at the current iterator position.
+//
+// \return Reference to the element at the current iterator position.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C>::PointerType
+ PtrVector<T,D,G>::CastIterator<C>::operator->() const
+{
+ return static_cast<C*>( *cur_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the current memory location of the cast iterator.
+//
+// \return Pointer to the current memory location.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline const typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C>::IteratorType&
+ PtrVector<T,D,G>::CastIterator<C>::base() const
+{
+ return cur_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the final memory location of the cast iterator.
+//
+// \return Pointer to the final memory location.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline const typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<C>::IteratorType&
+ PtrVector<T,D,G>::CastIterator<C>::stop() const
+{
+ return end_;
+}
+//*************************************************************************************************
+
+
+
+
+
+
+
+
+//=================================================================================================
+//
+// NESTED CLASS PTRVECTOR::CONSTCASTITERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Dynamic cast iterator for polymorphic pointer vectors.
+// \ingroup util
+//
+// The ConstCastIterator class is part of the PtrVector class and represent a forward iterator
+// over all elements of type \a C contained in a range of elements of type \a T, where \a C
+// is a type derived from \a T. The ConstCastIterator is the counterpart of CastIterator for
+// constant vectors.
+
+ \code
+ class A { ... };
+ class B : public class A { ... };
+
+ blaze::PtrVector<A>::ConstCastIterator<B> begin;
+ blaze::PtrVector<A>::ConstCastIterator<B> end;
+
+ // Loop over all elements of type B within the range [begin..end)
+ for( ; begin!=end; ++begin )
+ ...
+ \endcode
+
+// \note Using a ConstCastIterator is computationally more expensive than using a standard
+// iterator over all elements contained in the vector.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+class PtrVector<T,D,G>::ConstCastIterator
+{
+ public:
+ //**Type definitions****************************************************************************
+ // Blaze naming convention
+ typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category.
+ typedef const C* ValueType; //!< Type of the underlying pointers.
+ typedef const C* PointerType; //!< Pointer return type.
+ typedef const C* const& ReferenceType; //!< Reference return type.
+ typedef ptrdiff_t DifferenceType; //!< Difference between two iterators.
+ typedef const T* const* IteratorType; //!< Type of the internal pointer.
+
+ // STL iterator requirements
+ typedef IteratorCategory iterator_category; //!< The iterator category.
+ typedef ValueType value_type; //!< Type of the underlying pointers.
+ typedef PointerType pointer; //!< Pointer return type.
+ typedef ReferenceType reference; //!< Reference return type.
+ typedef DifferenceType difference_type; //!< Difference between two iterators.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ inline ConstCastIterator();
+ inline ConstCastIterator( IteratorType begin, IteratorType end );
+
+ template< typename Other >
+ inline ConstCastIterator( const ConstCastIterator<Other>& it );
+
+ template< typename Other >
+ inline ConstCastIterator( const typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<Other>& it );
+
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Copy assignment operator********************************************************************
+ // No explicitly declared copy assignment operator.
+ //**********************************************************************************************
+
+ //**Operators***********************************************************************************
+ /*!\name Operators */
+ //@{
+ inline ConstCastIterator& operator++();
+ inline ConstCastIterator operator++( int );
+ //@}
+ //**********************************************************************************************
+
+ //**Access operators****************************************************************************
+ /*!\name Access operators */
+ //@{
+ inline PointerType operator*() const;
+ inline PointerType operator->() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline const IteratorType& base() const;
+ inline const IteratorType& stop() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ IteratorType cur_; //!< Pointer to the current memory location.
+ IteratorType end_; //!< Pointer to the element one past the last element in the element range.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default constructor for ConstCastIterator.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline PtrVector<T,D,G>::ConstCastIterator<C>::ConstCastIterator()
+ : cur_( nullptr ) // Pointer to the current memory location
+ , end_( nullptr ) // Pointer to the element one past the last element in the element range
+{
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_DERIVED_FROM( C, T );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Standard constructor for ConstCastIterator.
+//
+// \param begin The beginning of the element range.
+// \param end The end of the element range.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline PtrVector<T,D,G>::ConstCastIterator<C>::ConstCastIterator( IteratorType begin, IteratorType end )
+ : cur_(begin) // Pointer to the current memory location
+ , end_(end) // Pointer to the element one past the last element in the element range
+{
+ // The polymorphicFind() function finds the next pointer to an object with dynamic type 'C'
+ // contained in the range [cur_,end). An equivalent code might look like this:
+ //
+ // while( cur_ != end_ && !dynamic_cast<C*>( *cur_ ) ) ++cur_;
+ //
+ // However, the specialization of polymorphicFind() for special type combinations is much
+ // more efficient (and way easier!) than the specialization of this function!
+ cur_ = polymorphicFind<C>( cur_, end_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from different ConstCastIterator instances.
+//
+// \param it The foreign ConstCastIterator instance to be copied.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+template< typename Other > // The foreign constant cast iterator type
+inline PtrVector<T,D,G>::ConstCastIterator<C>::ConstCastIterator( const ConstCastIterator<Other>& it )
+ : cur_( it.base() ) // Pointer to the current memory location
+ , end_( it.stop() ) // Pointer to the element one past the last element in the element range
+{
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_DERIVED_FROM( C, T );
+ BLAZE_CONSTRAINT_MUST_BE_CONVERTIBLE( Other*, C* );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Conversion constructor from CastIterator instances.
+//
+// \param it The foreign CastIterator instance to be copied.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+template< typename Other > // The foreign cast iterator type
+inline PtrVector<T,D,G>::ConstCastIterator<C>::ConstCastIterator( const typename PtrVector<T,D,G>::BLAZE_TEMPLATE CastIterator<Other>& it )
+ : cur_( it.base() ) // Pointer to the current memory location
+ , end_( it.stop() ) // Pointer to the element one past the last element in the element range
+{
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_DERIVED_FROM( C, T );
+ BLAZE_CONSTRAINT_MUST_BE_CONVERTIBLE( Other*, C* );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Pre-increment operator.
+//
+// \return Reference to the incremented cast iterator.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE ConstCastIterator<C>&
+ PtrVector<T,D,G>::ConstCastIterator<C>::operator++()
+{
+ // The polymorphicFind() function finds the next pointer to an object with dynamic type 'C'
+ // contained in the range [cur_+1,end). An equivalent code might look like this:
+ //
+ // while( ++cur_ != end_ && !dynamic_cast<const C*>( *cur_ ) ) {}
+ //
+ // However, the specialization of polymorphicFind() for special type combinations is much
+ // more efficient (and way easier!) than the specialization of this function!
+ cur_ = polymorphicFind<const C>( ++cur_, end_ );
+
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Post-increment operator.
+//
+// \return The incremented cast iterator.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE ConstCastIterator<C>
+ PtrVector<T,D,G>::ConstCastIterator<C>::operator++( int )
+{
+ ConstCastIterator tmp( *this );
+
+ // The polymorphicFind() function finds the next pointer to an object with dynamic type 'C'
+ // contained in the range [cur_+1,end). An equivalent code might look like this:
+ //
+ // while( ++cur_ != end_ && !dynamic_cast<const C*>( *cur_ ) ) {}
+ //
+ // However, the specialization of polymorphicFind() for special type combinations is much
+ // more efficient (and way easier!) than the specialization of this function!
+ cur_ = polymorphicFind<const C>( ++cur_, end_ );
+
+ return tmp;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns a handle to the element at the current iterator position.
+//
+// \return Handle to the element at the current iterator position.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE ConstCastIterator<C>::PointerType
+ PtrVector<T,D,G>::ConstCastIterator<C>::operator*() const
+{
+ return static_cast<const C*>( *cur_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the element at the current iterator position.
+//
+// \return Reference to the element at the current iterator position.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline typename PtrVector<T,D,G>::BLAZE_TEMPLATE ConstCastIterator<C>::PointerType
+ PtrVector<T,D,G>::ConstCastIterator<C>::operator->() const
+{
+ return static_cast<const C*>( *cur_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Direct access to the current memory location of the constant cast iterator.
+//
+// \return Pointer to the current memory location.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline const typename PtrVector<T,D,G>::BLAZE_TEMPLATE ConstCastIterator<C>::IteratorType&
+ PtrVector<T,D,G>::ConstCastIterator<C>::base() const
+{
+ return cur_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Direct access to the final memory location of the constant cast iterator.
+//
+// \return Pointer to the final memory location.
+*/
+template< typename T // Type
+ , typename D // Deletion policy
+ , typename G > // Growth policy
+template< typename C > // Cast type
+inline const typename PtrVector<T,D,G>::BLAZE_TEMPLATE ConstCastIterator<C>::IteratorType&
+ PtrVector<T,D,G>::ConstCastIterator<C>::stop() const
+{
+ return end_;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Random.h b/src/cpu/blaze/util/Random.h
new file mode 100644
index 00000000..1946ce5a
--- /dev/null
+++ b/src/cpu/blaze/util/Random.h
@@ -0,0 +1,1000 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Random.h
+// \brief Implementation of a random number generator.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_RANDOM_H_
+#define _BLAZE_UTIL_RANDOM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <ctime>
+#include <limits>
+#include <random>
+#include <blaze/system/Random.h>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/NonCreatable.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup random Random number generation
+// \ingroup util
+//
+// The random number module provides the functionality to generate pseudo-random numbers within
+// the Blaze library. In order to create series of random numbers, the following functions are
+// are provided:
+//
+// - blaze::rand<T>();
+// - blaze::getSeed();
+// - blaze::setSeed( uint32_t seed );
+//
+// The templated rand() function is capable of generating random numbers for built-in integer
+// and floating point data types as well as complex values. The rand() function can be given up
+// to five parameters that depending on the type of the random number may have different meaning.
+// The following example demonstrates the random number generation:
+
+ \code
+ using namespace blaze;
+
+ // The setSeed function sets the seed for the random number generator. This function can
+ // be used to set a specific seed for the random number generation, e.g. in order to
+ // reproduce an exact series of random numbers. If the setSeed function is not used, the
+ // random number generation uses a random seed.
+ setSeed( 12345 );
+
+ // In order to acquire the currently used seed, the getSeed() function can be used.
+ uint32_t seed = getSeed();
+
+ // Generating random numbers of built-in type. In case no range is provided, random numbers
+ // of integral type are generated in the range [0..max], where max is the largest possible
+ // value of the specified type and random floating point numbers are generated in the range
+ // [0..1). In the example, the random double precision floating point value is created in
+ // the range [2..4].
+ int i = rand<int>();
+ double d = rand<double>( 2.0, 4.0 );
+
+ // Generating random complex numbers. In case no range is provided, both the real and the
+ // imaginary part are created depending on the element type of the complex number. In case
+ // one range is specified, both the real and the imaginary part are created within the
+ // specified range. In the example, both parts are created within the range [1..4]. If two
+ // ranges are provided, the real part is created in the first range and the imaginary part
+ // is created in the second range. The last example demonstrates this by restricting the
+ // real part to the range [2..3] and the imaginary part to the range [1..5].
+ complex<float> c1 = rand< complex<float> >();
+ complex<float> c2 = rand< complex<float> >( 1.0F, 4.0F );
+ complex<float> c3 = rand< complex<float> >( 2.0F, 3.0F, 1.0F, 5.0F );
+ \endcode
+
+// \note In order to reproduce certain series of random numbers, the seed of the random number
+// generator has to be set explicitly via the setSeed() function. Otherwise a random seed is used
+// for the random number generation.
+*/
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Random number functions */
+//@{
+template< typename T >
+inline T rand();
+
+template< typename T, typename... Args >
+inline T rand( Args&&... args );
+
+template< typename T >
+inline void randomize( T& value );
+
+template< typename T, typename... Args >
+inline void randomize( T& value, Args&&... args );
+
+inline uint32_t defaultSeed();
+inline uint32_t getSeed();
+inline void setSeed( uint32_t seed );
+//@}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Random number generator.
+// \ingroup random
+//
+// The Random class encapsulates the initialization of the given random number generator with
+// a pseudo-random seed obtained by the std::time() function. Currently, the mersenne-twister
+// mt19937 as provided by the C++ standard library is used per default. For more information
+// see the for instance the following documentation of the random number functionality of the
+// C++11 standard library:
+//
+// http://en.cppreference.com/w/cpp/numeric/random
+*/
+template< typename Type > // Type of the random number generator
+class Random : private NonCreatable
+{
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ static uint32_t seed_; //!< The current seed for the variate generator.
+ static Type rng_; //!< The mersenne twister variate generator.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ template< typename T > friend class Rand;
+ friend uint32_t getSeed();
+ friend void setSeed( uint32_t seed );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
+//
+//=================================================================================================
+
+template< typename Type > uint32_t Random<Type>::seed_( defaultSeed() );
+template< typename Type > Type Random<Type>::rng_ ( defaultSeed() );
+
+
+
+
+//=================================================================================================
+//
+// CLASS RAND
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default implementation of the Rand class for integral data types.
+// \ingroup random
+//
+// This default implementation of the Rand class creates random, integral numbers in the range
+// \f$ [0..max] \f$, where \a max is the maximal value of the given data type \a T.
+*/
+template< typename T > // Type of the random number
+class Rand
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline T generate() const;
+ inline T generate( T min, T max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( T& value ) const;
+ inline void randomize( T& value, T min, T max ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Generation of a random value in the range \f$ [0..max] \f$.
+//
+// \return The generated random value.
+//
+// This \a generate function creates a random number in the range \f$ [0..max] \f$, where \a max
+// is the maximal value of the given data type \a T.
+*/
+template< typename T > // Type of the random number
+inline T Rand<T>::generate() const
+{
+ std::uniform_int_distribution<T> dist( 0, std::numeric_limits<T>::max() );
+ return dist( Random<RNG>::rng_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Generation of a random value in the range \f$ [min..max] \f$.
+//
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return The generated random value.
+//
+// This \a generate function creates a random number in the range \f$ [min..max] \f$, where
+// \a min must be smaller or equal to \a max. Note that this requirement is only checked in
+// debug mode. In release mode, no check is performed to enforce the validity of the values.
+// Therefore the returned value is undefined if \a min is larger than \a max.
+*/
+template< typename T > // Type of the random number
+inline T Rand<T>::generate( T min, T max ) const
+{
+ BLAZE_INTERNAL_ASSERT( min <= max, "Invalid min/max value pair" );
+ std::uniform_int_distribution<T> dist( min, max );
+ return dist( Random<RNG>::rng_ );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Randomization of the given variable with a new value in the range \f$ [0..max] \f$.
+//
+// \param value The variable to be randomized.
+// \return void
+//
+// This function randomizes the given variable to a new value in the range \f$ [0..max] \f$,
+// where \a max is the maximal value of the given data type \a T.
+*/
+template< typename T > // Type of the random number
+inline void Rand<T>::randomize( T& value ) const
+{
+ value = generate();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Randomization of the given variable with a new value in the range \f$ [min..max] \f$.
+//
+// \param value The variable to be randomized.
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return void
+//
+// This function randomizes the given variable to a new value in the range \f$ [min..max] \f$, where
+// \a min must be smaller or equal to \a max. Note that this requirement is only checked in debug
+// mode. In release mode, no check is performed to enforce the validity of the values. Therefore
+// the returned value is undefined if \a min is larger than \a max.
+*/
+template< typename T > // Type of the random number
+inline void Rand<T>::randomize( T& value, T min, T max ) const
+{
+ value = generate( min, max );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION (FLOAT)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for single precision floating point values.
+// \ingroup random
+//
+// This specialization of the Rand class creates random, single precision values in the range
+// \f$ [0..1) \f$.
+*/
+template<>
+class Rand<float>
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline float generate() const;
+ inline float generate( float min, float max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( float& value ) const;
+ inline void randomize( float& value, float min, float max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random single precision value in the range \f$ [0..1) \f$.
+//
+// \return The generated random single precision value.
+//
+// This function creates a random single precision value in the range \f$ [0..1) \f$.
+*/
+inline float Rand<float>::generate() const
+{
+ std::uniform_real_distribution<float> dist( 0.0, 1.0 );
+ return dist( Random<RNG>::rng_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random single precision value in the range \f$ [min..max] \f$.
+//
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return The generated random single precision value.
+//
+// This function creates a random single precision number in the range \f$ [min..max] \f$, where
+// \a min must be smaller or equal to \a max. Note that this requirement is only checked in debug
+// mode. In release mode, no check is performed to enforce the validity of the values. Therefore
+// the returned value is undefined if \a min is larger than \a max.
+*/
+inline float Rand<float>::generate( float min, float max ) const
+{
+ BLAZE_INTERNAL_ASSERT( min <= max, "Invalid min/max values" );
+ std::uniform_real_distribution<float> dist( min, max );
+ return dist( Random<RNG>::rng_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of the given single precision variable to a value in in the range \f$ [0..1) \f$.
+//
+// \param value The variable to be randomized.
+// \return void
+//
+// This function randomizes the given single precision variable to a value in the range \f$ [0..1) \f$.
+*/
+inline void Rand<float>::randomize( float& value ) const
+{
+ value = generate();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of the given single precision variable to a value in the range \f$ [min..max] \f$.
+//
+// \param value The variable to be randomized.
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return void
+//
+// This function randomizes the given single precision variable to a value in the range
+// \f$ [min..max] \f$, where \a min must be smaller or equal to \a max. Note that this requirement
+// is only checked in debug mode. In release mode, no check is performed to enforce the validity
+// of the values. Therefore the returned value is undefined if \a min is larger than \a max.
+*/
+inline void Rand<float>::randomize( float& value, float min, float max ) const
+{
+ value = generate( min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION (DOUBLE)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for double precision floating point values.
+// \ingroup random
+//
+// This specialization of the Rand class creates random, double precision values in the range
+// \f$ [0..1) \f$.
+*/
+template<>
+class Rand<double>
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline double generate() const;
+ inline double generate( double min, double max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( double& value ) const;
+ inline void randomize( double& value, double min, double max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random double precision value in the range \f$ [0..1) \f$.
+//
+// \return The generated random double precision value.
+//
+// This function creates a random double precision value in the range \f$ [0..1) \f$.
+*/
+inline double Rand<double>::generate() const
+{
+ std::uniform_real_distribution<double> dist( 0.0, 1.0 );
+ return dist( Random<RNG>::rng_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random double precision value in the range \f$ [min..max] \f$.
+//
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return The generated random double precision value.
+//
+// This function creates a random double precision number in the range \f$ [min..max] \f$, where
+// \a min must be smaller or equal to \a max. Note that this requirement is only checked in debug
+// mode. In release mode, no check is performed to enforce the validity of the values. Therefore
+// the returned value is undefined if \a min is larger than \a max.
+*/
+inline double Rand<double>::generate( double min, double max ) const
+{
+ BLAZE_INTERNAL_ASSERT( min <= max, "Invalid min/max values" );
+ std::uniform_real_distribution<double> dist( min, max );
+ return dist( Random<RNG>::rng_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of the given double precision variable to a value in in the range \f$ [0..1) \f$.
+//
+// \param value The variable to be randomized.
+// \return void
+//
+// This function randomizes the given double precision variable to a value in the range \f$ [0..1) \f$.
+*/
+inline void Rand<double>::randomize( double& value ) const
+{
+ value = generate();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of the given double precision variable to a value in the range \f$ [min..max] \f$.
+//
+// \param value The variable to be randomized.
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return void
+//
+// This function randomizes the given double precision variable to a value in the range
+// \f$ [min..max] \f$, where \a min must be smaller or equal to \a max. Note that this requirement
+// is only checked in debug mode. In release mode, no check is performed to enforce the validity
+// of the values. Therefore the returned value is undefined if \a min is larger than \a max.
+*/
+inline void Rand<double>::randomize( double& value, double min, double max ) const
+{
+ value = generate( min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION (LONG DOUBLE)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for extended precision floating point values.
+// \ingroup random
+//
+// This specialization of the Rand class creates random, extended precision values in the range
+// \f$ [0..1) \f$.
+*/
+template<>
+class Rand<long double>
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline long double generate() const;
+ inline long double generate( long double min, long double max ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( long double& value ) const;
+ inline void randomize( long double& value, long double min, long double max ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random extended precision value in the range \f$ [0..1) \f$.
+//
+// \return The generated random extended precision value.
+//
+// This function creates a random extended precision value in the range \f$ [0..1) \f$.
+*/
+inline long double Rand<long double>::generate() const
+{
+ std::uniform_real_distribution<long double> dist( 0.0, 1.0 );
+ return dist( Random<RNG>::rng_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random extended precision value in the range \f$ [min..max] \f$.
+//
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return The generated random extended precision value.
+//
+// This function creates a random extended precision number in the range \f$ [min..max] \f$, where
+// \a min must be smaller or equal to \a max. Note that this requirement is only checked in debug
+// mode. In release mode, no check is performed to enforce the validity of the values. Therefore
+// the returned value is undefined if \a min is larger than \a max.
+*/
+inline long double Rand<long double>::generate( long double min, long double max ) const
+{
+ BLAZE_INTERNAL_ASSERT( min <= max, "Invalid min/max values" );
+ std::uniform_real_distribution<long double> dist( min, max );
+ return dist( Random<RNG>::rng_ );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of the given extended precision variable to a value in in the range \f$ [0..1) \f$.
+//
+// \param value The variable to be randomized.
+// \return void
+//
+// This function randomizes the given extended precision variable to a value in the range \f$ [0..1) \f$.
+*/
+inline void Rand<long double>::randomize( long double& value ) const
+{
+ value = generate();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of the given extended precision variable to a value in the range \f$ [min..max] \f$.
+//
+// \param value The variable to be randomized.
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return void
+//
+// This function randomizes the given extended precision variable to a value in the range
+// \f$ [min..max] \f$, where \a min must be smaller or equal to \a max. Note that this requirement
+// is only checked in debug mode. In release mode, no check is performed to enforce the validity
+// of the values. Therefore the returned value is undefined if \a min is larger than \a max.
+*/
+inline void Rand<long double>::randomize( long double& value, long double min, long double max ) const
+{
+ value = generate( min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RAND SPECIALIZATION (COMPLEX)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Rand class template for complex values.
+// \ingroup random
+//
+// This specialization of the Rand class creates random, complex values.
+*/
+template< typename T > // Type of the values
+class Rand< complex<T> >
+{
+ public:
+ //**Generate functions**************************************************************************
+ /*!\name Generate functions */
+ //@{
+ inline const complex<T> generate() const;
+ inline const complex<T> generate( const T& min, const T& max ) const;
+ inline const complex<T> generate( const T& realmin, const T& realmax,
+ const T& imagmin, const T& imagmax ) const;
+ //@}
+ //**********************************************************************************************
+
+ //**Randomize functions*************************************************************************
+ /*!\name Randomize functions */
+ //@{
+ inline void randomize( complex<T>& value ) const;
+ inline void randomize( complex<T>& value, const T& min, const T& max ) const;
+ inline void randomize( complex<T>& value, const T& realmin, const T& realmax,
+ const T& imagmin, const T& imagmax ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random complex number.
+//
+// \return The generated random complex number.
+//
+// This function generates a random complex number, where both the real and the imaginary part
+// are initialized with random values in the full range of the data type \a T.
+*/
+template< typename T > // Type of the values
+inline const complex<T> Rand< complex<T> >::generate() const
+{
+ Rand<T> tmp;
+ return complex<T>( tmp.generate(), tmp.generate() );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random complex number in the range \f$ [min..max] \f$.
+//
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return The generated random complex number.
+//
+// This function generates a random complex number, where both the real and the imaginary part
+// are initialized with random values in the range \f$ [min..max] \f$. Note that \a min must be
+// smaller or equal to \a max. This requirement is only checked in debug mode. In release mode,
+// no check is performed to enforce the validity of the values. Therefore the returned value is
+// undefined if \a min is larger than \a max.
+*/
+template< typename T > // Type of the values
+inline const complex<T> Rand< complex<T> >::generate( const T& min, const T& max ) const
+{
+ Rand<T> tmp;
+ return complex<T>( tmp.generate( min, max ), tmp.generate( min, max ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Generation of a random complex number.
+//
+// \param realmin The smallest possible random value for the real part.
+// \param realmax The largest possible random value for the real part
+// \param realmin The smallest possible random value for the imaginary part.
+// \param realmax The largest possible random value for the imaginary part.
+// \return The generated random complex number.
+//
+// This function creates a random, complex number, where the real part is in the range
+// \f$ [realmin..realmax] \f$ and the imaginary part is in the range \f$ [imagmin..imagmax] \f$.
+// \a realmin must be smaller or equal to \a realmax and \a imagmin must be smaller or equal to
+// \a imagmax. These requirements are only checked in debug mode. In release mode, no check is
+// performed to enforce the validity of the values. Therefore the returned value is undefined
+// if \a realmin is larger than \a realmax or \a imagmin is larger than \a imagmax.
+*/
+template< typename T > // Type of the values
+inline const complex<T> Rand< complex<T> >::generate( const T& realmin, const T& realmax,
+ const T& imagmin, const T& imagmax ) const
+{
+ Rand<T> tmp;
+ return complex<T>( tmp.generate( realmin, realmax ), tmp.generate( imagmin, imagmax ) );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a complex number.
+//
+// \param value The variable to be randomized.
+// \return void
+//
+// This function randomizes the given complex number. Both the real and the imaginary part are
+// initialized with random values in the full range of the data type \a T.
+*/
+template< typename T > // Type of the values
+inline void Rand< complex<T> >::randomize( complex<T>& value ) const
+{
+ value = generate();
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a complex number to values in the range \f$ [min..max] \f$.
+//
+// \param value The variable to be randomized.
+// \param min The smallest possible random value.
+// \param max The largest possible random value.
+// \return void
+//
+// This function randomizes the given complex number. Both the real and the imaginary part are
+// initialized with random values in the range \f$ [min..max] \f$. Note that \a min must be
+// smaller or equal to \a max. This requirement is only checked in debug mode. In release mode,
+// no check is performed to enforce the validity of the values. Therefore the returned value is
+// undefined if \a min is larger than \a max.
+*/
+template< typename T > // Type of the values
+inline void Rand< complex<T> >::randomize( complex<T>& value, const T& min, const T& max ) const
+{
+ value = generate( min, max );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Randomization of a complex number.
+//
+// \param value The variable to be randomized.
+// \param realmin The smallest possible random value for the real part.
+// \param realmax The largest possible random value for the real part
+// \param realmin The smallest possible random value for the imaginary part.
+// \param realmax The largest possible random value for the imaginary part.
+// \return void
+//
+// This function randomizes the given complex number. The real part is set to a random value in
+// the range \f$ [realmin..realmax] \f$ and the imaginary part is set to a value in the range
+// \f$ [imagmin..imagmax] \f$. \a realmin must be smaller or equal to \a realmax and \a imagmin
+// must be smaller or equal to \a imagmax. These requirements are only checked in debug mode.
+// In release mode, no check is performed to enforce the validity of the values. Therefore the
+// returned value is undefined if \a realmin is larger than \a realmax or \a imagmin is larger
+// than \a imagmax.
+*/
+template< typename T > // Type of the values
+inline void Rand< complex<T> >::randomize( complex<T>& value, const T& realmin, const T& realmax,
+ const T& imagmin, const T& imagmax ) const
+{
+ value = generate( realmin, realmax, imagmin, imagmax );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// RANDOM NUMBER FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Random number function.
+// \ingroup random
+//
+// \return The generated random number.
+//
+// The rand() function returns a default random number depending on the given data type. In case
+// of integral data types, the function returns a random number in the range \f$ [0..max] \f$,
+// where \a max is the maximal value of the data type \a T. In case of floating point data types,
+// the function returns a random number in the range \f$ [0..1) \f$. In case of complex data
+// types, the function returns a random complex value where both the real and the imaginary part
+// have been set according to the element type of the complex value (\f$ [0..max] \f$ for integral
+// elements, \f$ [0..1) \f$ for floating point elements).
+*/
+template< typename T > // Type of the random number
+inline T rand()
+{
+ Rand<T> tmp;
+ return tmp.generate();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Random number function.
+// \ingroup random
+//
+// \param args The arguments for the random number generation.
+// \return The generated random number.
+//
+// This rand() function creates a random number based on the given arguments \a args.
+*/
+template< typename T // Type of the random number
+ , typename... Args > // Types of the optional arguments
+inline T rand( Args&&... args )
+{
+ Rand<T> tmp;
+ return tmp.generate( std::forward<Args>( args )... );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Randomization of a given variable.
+// \ingroup random
+//
+// \param value The variable to be randomized.
+// \return void
+//
+// The randomize() function randomizes the given variable depending on its data type. In case
+// of integral data types, the function returns a random number in the range \f$ [0..max] \f$,
+// where \a max is the maximal value of the data type \a T. In case of floating point data types,
+// the function returns a random number in the range \f$ [0..1) \f$. In case of complex data
+// types, the function returns a random complex value where both the real and the imaginary part
+// have been set according to the element type of the complex value (\f$ [0..max] \f$ for integral
+// elements, \f$ [0..1) \f$ for floating point elements).
+*/
+template< typename T > // Type of the random number
+inline void randomize( T& value )
+{
+ Rand<T> tmp;
+ tmp.randomize( value );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Randomization of a given variable.
+// \ingroup random
+//
+// \param value The value to be randomized.
+// \param args The arguments for the random number generation.
+// \return void
+//
+// This randomize() function randomizes the given variable based on the given arguments \a args.
+*/
+template< typename T // Type of the random number
+ , typename... Args > // Types of the optional arguments
+inline void randomize( T& value, Args&&... args )
+{
+ Rand<T> tmp;
+ tmp.randomize( value, std::forward<Args>( args )... );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the default random seed.
+// \ingroup random
+//
+// \return The default random seed.
+*/
+inline uint32_t defaultSeed()
+{
+ static const uint32_t seed = static_cast<uint32_t>( std::time(0) );
+ return seed;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current seed of the random number generator.
+// \ingroup random
+//
+// \return The current seed of the random number generator.
+*/
+inline uint32_t getSeed()
+{
+ return Random<RNG>::seed_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Setting the seed of the random number generator.
+// \ingroup random
+//
+// \param seed The new seed for the random number generator.
+// \return void
+//
+// This function can be used to set the seed for the random number generation in order to
+// create a reproducible series of random numbers.
+*/
+inline void setSeed( uint32_t seed )
+{
+ Random<RNG>::seed_ = seed;
+ Random<RNG>::rng_.seed( seed );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Serialization.h b/src/cpu/blaze/util/Serialization.h
new file mode 100644
index 00000000..cb9f244a
--- /dev/null
+++ b/src/cpu/blaze/util/Serialization.h
@@ -0,0 +1,45 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Serialization.h
+// \brief Header file for all serialization functionality
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_SERIALIZATION_H_
+#define _BLAZE_UTIL_SERIALIZATION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/serialization/Archive.h>
+
+#endif
diff --git a/src/cpu/blaze/util/Singleton.h b/src/cpu/blaze/util/Singleton.h
new file mode 100644
index 00000000..eb77dd3a
--- /dev/null
+++ b/src/cpu/blaze/util/Singleton.h
@@ -0,0 +1,46 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Singleton.h
+// \brief Header file for the Singleton class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+// //=================================================================================================
+
+#ifndef _BLAZE_UTIL_SINGLETON_H_
+#define _BLAZE_UTIL_SINGLETON_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/singleton/Dependency.h>
+#include <blaze/util/singleton/Singleton.h>
+
+#endif
diff --git a/src/cpu/blaze/util/StaticAssert.h b/src/cpu/blaze/util/StaticAssert.h
new file mode 100644
index 00000000..be437597
--- /dev/null
+++ b/src/cpu/blaze/util/StaticAssert.h
@@ -0,0 +1,129 @@
+//=================================================================================================
+/*!
+// \file blaze/util/StaticAssert.h
+// \brief Compile time assertion
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_STATICASSERT_H_
+#define _BLAZE_UTIL_STATICASSERT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Suffix.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// COMPILE TIME ASSERTION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup static_assert Compile time assertion
+// \ingroup assert
+//
+// Static assertion offers the possibility to stop the compilation process if a specific compile
+// time condition is not met. The blaze::BLAZE_STATIC_ASSERT and blaze::BLAZE_STATIC_ASSERT_MSG
+// macros can be used to check a constant expression at compile time. If the expression evaluates
+// to \a false, a compilation error is generated that stops the compilation process. If the
+// expression (hopefully) evaluates to \a true, the compilation process is not aborted and the
+// static check leaves neither code nor data and is therefore not affecting the performance.\n
+//
+// Both static assertion macros can be used wherever a standard typedef statement can be declared,
+// i.e. in namespace scope, in class scope and in function scope. The following examples illustrate
+// the use of the static assertion macros: The element type of the rotation matrix is checked at
+// compile time and restricted to be of floating point type.
+
+ \code
+ #include <blaze/util/StaticAssert.h>
+ #include <blaze/util/typetraits/FloatingPoint.h>
+
+ template< typename T >
+ class RotationMatrix {
+ ...
+ BLAZE_STATIC_ASSERT( IsFloatingPoint<T>::value );
+ // ... or ...
+ BLAZE_STATIC_ASSERT_MSG( IsFloatingPoint<T>::value, "Given type is not a floating point type" );
+ ...
+ };
+ \endcode
+
+// The static assertion implementation is based on the C++11 \c static_assert declaration. Thus
+// the error message contains the violated compile time condition and directly refers to the
+// violated static assertion. The following examples show a possible error message from the GNU
+// g++ compiler:
+
+ \code
+ error: static assertion failed: Compile time condition violated
+ static_assert( expr, "Compile time condition violated" )
+ ^
+ note: in expansion of macro 'BLAZE_STATIC_ASSERT'
+ BLAZE_STATIC_ASSERT( IsFloatingPoint<T>::value );
+
+ error: static assertion failed: Given type is not a floating point type
+ static_assert( expr, msg )
+ ^
+ note: in expansion of macro 'BLAZE_STATIC_ASSERT_MSG'
+ BLAZE_STATIC_ASSERT_MSG( IsFloatingPoint<T>::value, "Given type is not a floating point type" );
+ \endcode
+*/
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time assertion macro.
+// \ingroup static_assert
+//
+// In case of an invalid compile time expression, a compilation error is created.
+*/
+#define BLAZE_STATIC_ASSERT(expr) \
+ static_assert( expr, "Compile time condition violated" )
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time assertion macro.
+// \ingroup static_assert
+//
+// In case of an invalid compile time expression, a compilation error is created.
+*/
+#define BLAZE_STATIC_ASSERT_MSG(expr,msg) \
+ static_assert( expr, msg )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Suffix.h b/src/cpu/blaze/util/Suffix.h
new file mode 100644
index 00000000..cc869e6a
--- /dev/null
+++ b/src/cpu/blaze/util/Suffix.h
@@ -0,0 +1,55 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Suffix.h
+// \brief Header file for compile time constraints
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_SUFFIX_H_
+#define _BLAZE_UTIL_SUFFIX_H_
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Helper macro for macro concatenation.
+// \ingroup util
+//
+// The following code was borrowed from the Boost C++ framework (www.boost.org). This piece of
+// macro magic joins the two arguments together, even when one of the arguments is itself a
+// macro (see 16.3.1 in C++ standard). The key is that macro expansion of macro arguments does
+// not occur in BLAZE_DO_JOIN2 but does in BLAZE_DO_JOIN.
+*/
+#define BLAZE_JOIN( X, Y ) BLAZE_DO_JOIN( X, Y )
+#define BLAZE_DO_JOIN( X, Y ) BLAZE_DO_JOIN2(X,Y)
+#define BLAZE_DO_JOIN2( X, Y ) X##Y
+/*! \endcond */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/SystemClock.h b/src/cpu/blaze/util/SystemClock.h
new file mode 100644
index 00000000..0e9a47f8
--- /dev/null
+++ b/src/cpu/blaze/util/SystemClock.h
@@ -0,0 +1,194 @@
+//=================================================================================================
+/*!
+// \file blaze/util/SystemClock.h
+// \brief Header file for the SystemClock class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_SYSTEMCLOCK_H_
+#define _BLAZE_UTIL_SYSTEMCLOCK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <ctime>
+#include <blaze/util/singleton/Singleton.h>
+#include <blaze/util/SystemClockID.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief System clock of the Blaze library.
+// \ingroup util
+//
+// The SystemClock class represents the system clock of the Blaze library. The system clock
+// is the central timing functionality that can be used to query for the start time of the
+// process, the current timestamp and the elapsed time since the start of the process. The
+// following example demonstrates how the single system clock instance is acquired via the
+// theSystemClock() functcion and how the system clock can be used:
+
+ \code
+ // The single system clock instance is accessible via the theSystemClock() function
+ SystemClockID systemClock = theSystemClock();
+
+ time_t start = systemClock->start(); // Querying the start time of the process
+ time_t current = systemClock->current(); // Querying the current timestamp
+ time_t elapsed = systemClock->elapsed(); // Querying the elapsed time
+ \endcode
+*/
+class SystemClock : private Singleton<SystemClock>
+{
+ private:
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit SystemClock();
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ ~SystemClock();
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline time_t start () const;
+ inline time_t now () const;
+ inline time_t elapsed() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ static time_t start_; //!< Timestamp for the start of the process.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend SystemClockID theSystemClock();
+ BLAZE_BEFRIEND_SINGLETON;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SYSTEM CLOCK SETUP FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name System clock setup functions */
+//@{
+inline SystemClockID theSystemClock();
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns a handle to the Blaze system clock.
+// \ingroup util
+//
+// \return Handle to the active system clock.
+*/
+inline SystemClockID theSystemClock()
+{
+ return SystemClock::instance();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the timestamp for the start of the process.
+//
+// \return Timestamp for the start of the process.
+*/
+inline time_t SystemClock::start() const
+{
+ return start_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current timestamp.
+//
+// \return The current timestamp.
+*/
+inline time_t SystemClock::now() const
+{
+ return time( nullptr );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the elapsed time since the start of the process (in seconds).
+//
+// \return Elapsed time since the start of the process (in seconds).
+*/
+inline time_t SystemClock::elapsed() const
+{
+ return std::time( nullptr ) - start_;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/SystemClockID.h b/src/cpu/blaze/util/SystemClockID.h
new file mode 100644
index 00000000..4d8b1758
--- /dev/null
+++ b/src/cpu/blaze/util/SystemClockID.h
@@ -0,0 +1,82 @@
+//=================================================================================================
+/*!
+// \file blaze/util/SystemClockID.h
+// \brief Implementation of a smart SystemClock handle
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_SYSTEMCLOCKID_H_
+#define _BLAZE_UTIL_SYSTEMCLOCKID_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+class SystemClock;
+
+
+
+
+//=================================================================================================
+//
+// TYPE DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Handle for the system clock of the Blaze library.
+// \ingroup util
+*/
+typedef std::shared_ptr<SystemClock> SystemClockID;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Handle for the system clock of the Blaze library.
+// \ingroup util
+*/
+typedef std::shared_ptr<const SystemClock> ConstSystemClockID;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Template.h b/src/cpu/blaze/util/Template.h
new file mode 100644
index 00000000..32d6aba7
--- /dev/null
+++ b/src/cpu/blaze/util/Template.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Template.h
+// \brief Header file for nested template disabiguation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TEMPLATE_H_
+#define _BLAZE_UTIL_TEMPLATE_H_
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Compiler specific patch for nested template disambiguation.
+// \ingroup util
+//
+// The BLAZE_TEMPLATE is a patch for the Microsoft Visual C++ compiler that does not correctly
+// parse definitions of nested templates of the following form:
+
+ \code
+ template< typename T >
+ class Alloc {
+ public:
+ ...
+ template< typename Other >
+ class rebind {
+ public:
+ typedef Alloc<Other> other;
+ };
+ ...
+ };
+
+ typedef Alloc<int> AI;
+ typedef AI::template rebind<double>::other Other; // Compilation error with Visual C++
+ \endcode
+
+// In order to circumvent this compilation error, the BLAZE_TEMPLATE macro should be used
+// instead the \a template keyword:
+
+ \code
+ ...
+ typedef AI::BLAZE_TEMPLATE rebind<double>::other Other; // No compilation errors
+ \endcode
+*/
+#if defined(_MSC_VER)
+# define BLAZE_TEMPLATE
+#else
+# define BLAZE_TEMPLATE template
+#endif
+/*! \endcond */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/Thread.h b/src/cpu/blaze/util/Thread.h
new file mode 100644
index 00000000..30d10006
--- /dev/null
+++ b/src/cpu/blaze/util/Thread.h
@@ -0,0 +1,498 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Thread.h
+// \brief Header file for the Thread class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_THREAD_H_
+#define _BLAZE_UTIL_THREAD_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <functional>
+#include <memory>
+#include <blaze/util/Assert.h>
+#include <blaze/util/NonCopyable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+template< typename TT, typename MT, typename LT, typename CT > class ThreadPool;
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of a single thread of execution.
+// \ingroup threads
+//
+// \section thread_general General
+//
+// The Thread template represents a thread of execution for the parallel execution of concurrent
+// tasks. Each Thread object incorporates a single thread of execution, or Not-a-Thread, and at
+// most one Thread object incorporates a given thread of execution since it is not possible to
+// copy a Thread.\n
+//
+//
+// \section thread_definition Class Definition
+//
+// The implementation of the Thread class template is based on the implementation of standard
+// threads as provided by the C++11 standard or the Boost library. Via the four template
+// parameters it is possible to configure a Thread instance as either a C++11 thread or as
+// Boost thread:
+
+ \code
+ template< typename TT, typename MT, typename LT, typename CT >
+ class Thread;
+ \endcode
+
+// - TT: specifies the type of the encapsulated thread. This can either be \c std::thread,
+// \c boost::thread, or any other standard conforming thread type.
+// - MT: specifies the type of the used synchronization mutex. This can for instance be
+// \c std::mutex, \c boost::mutex, or any other standard conforming mutex type.
+// - LT: specifies the type of lock used in combination with the given mutex type. This
+// can be any standard conforming lock type, as for instance \c std::unique_lock,
+// \c boost::unique_lock.
+// - CT: specifies the type of the used condition variable. This can for instance be
+// \c std::condition_variable, \c boost::condition_variable, or any other standard
+// conforming condition variable type.
+//
+// Examples:
+
+ \code
+ typedef blaze::Thread< boost::thread
+ , boost::mutex
+ , boost::unique_lock<boost::mutex>
+ , boost::condition_variable > BoostThread;
+
+ typedef blaze::Thread< std::thread
+ , std::mutex
+ , std::unique_lock<std::mutex>
+ , std::condition_variable > StdThread;
+ \endcode
+
+// For more information about the standard thread functionality, see [1] or [2] or the current
+// documentation at the Boost homepage: www.boost.org.
+//
+//
+// \section thread_setup Creating individual threads
+//
+// The Blaze library provides the functionality to create individual threads for specific tasks,
+// or to create thread pools for the execution of a larger number of tasks (see the ThreadPool
+// class description). The following example demonstrates the setup of individual threads to
+// handle specific tasks. In this example, a function without arguments and a functor with two
+// arguments are executed in parallel by two distinct threads:
+
+ \code
+ // Definition of a function with no arguments that returns void
+ void function0() { ... }
+
+ // Definition of a functor (function object) taking two arguments and returning void
+ struct Functor2
+ {
+ void operator()( int a, int b ) { ... }
+ };
+
+ int main()
+ {
+ // Creating a new thread executing the zero argument function.
+ StdThread thread1( function0 );
+
+ // Waiting for the thread to finish its task
+ thread1.join();
+
+ // After the thread has completed its tasks, it is not possible to reassign it a
+ // new task. Therefore it is necessary to create a new thread for optional follow
+ // up tasks.
+
+ // Creating a new thread executing the binary functor.
+ StdThread thread2( Functor2(), 4, 6 );
+
+ // Waiting for the second thread to finish its task
+ thread2.join();
+ }
+ \endcode
+
+// Note that the Thread class allows for up to five arguments for the given functions/functors.
+// Also note that the two tasks are not executed in parallel since the join() function is used
+// to wait for each thread's completion.
+//
+//
+// \section thread_exception Throwing exceptions in a thread parallel environment
+//
+// It can happen that during the execution of a given task a thread encounters an erroneous
+// situation and has to throw an exception. However, exceptions thrown in the usual way
+// cannot be caught by a try-catch-block in the main thread of execution:
+
+ \code
+ // Definition of a function throwing a std::runtime_error during its execution
+ void task()
+ {
+ ...
+ throw std::runtime_error( ... );
+ ...
+ }
+
+ // Creating a thread executing the throwing function. Although the setup, execution and
+ // destruction of the thread are encapsuled inside a try-catch-block, the exception cannot
+ // be caught and results in an abortion of the program.
+ try {
+ StdThread thread( task );
+ thread.join();
+ }
+ catch( ... )
+ {
+ ...
+ }
+ \endcode
+
+// For a detailed explanation how to portably transport exceptions between threads, see [1] or
+// [2]. In case of the Boost library, the according Boost functionality as demonstrated in the
+// following example has to be used. Note that any function/functor passed to a thread is
+// responsible to handle exceptions in this way!
+
+ \code
+ #include <boost/bind.hpp>
+ #include <boost/exception_ptr.hpp>
+
+ // Definition of a function that happens to throw an exception. In order to throw the
+ // exception, boost::enable_current_exception() is used in combination with throw.
+ void throwException()
+ {
+ ...
+ throw boost::enable_current_exception( std::runtime_error( ... ) );
+ ...
+ }
+
+ // Definition of a thread function. The try-catch-block catches the exception and uses the
+ // boost::current_exception() function to get a boost::exception_ptr object.
+ void task( boost::exception_ptr& error )
+ {
+ try {
+ throwException();
+ error = boost::exception_ptr();
+ }
+ catch( ... ) {
+ error = boost::current_exception();
+ }
+ }
+
+ // The function that start a thread of execution can pass along a boost::exception_ptr object
+ // that is set in case of an exception. Note that boost::current_exception() captures the
+ // original type of the exception object. The exception can be thrown again using the
+ // boost::rethrow_exception() function.
+ void work()
+ {
+ boost::exception_ptr error;
+
+ Thread<boost::thread> thread( boost::bind( task, boost::ref(error) ) );
+ thread.join();
+
+ if( error ) {
+ std::cerr << " Exception during thread execution!\n\n";
+ boost::rethrow_exception( error );
+ }
+ }
+ \endcode
+
+// \section thread_references References
+//
+// [1] A. Williams: C++ Concurrency in Action, Manning, 2012, ISBN: 978-1933988771\n
+// [2] B. Stroustrup: The C++ Programming Language, Addison-Wesley, 2013, ISBN: 978-0321563842\n
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+class Thread : private NonCopyable
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef TT ThreadType; //!< Type of the encapsulated thread.
+ typedef ThreadPool<TT,MT,LT,CT> ThreadPoolType; //!< Type of the managing thread pool.
+ typedef std::unique_ptr<ThreadType> ThreadHandle; //!< Handle for a single thread.
+ //**********************************************************************************************
+
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit Thread( ThreadPoolType* pool );
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ template< typename Callable, typename... Args >
+ explicit inline Thread( Callable func, Args&&... args );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ ~Thread();
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool joinable() const;
+ inline void join();
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline bool hasTerminated() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Thread execution functions******************************************************************
+ /*!\name Thread execution functions */
+ //@{
+ void run();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ volatile bool terminated_; //!< Thread termination flag.
+ /*!< This flag value is used by the managing thread
+ pool to learn whether the thread has terminated
+ its execution. */
+ ThreadPoolType* pool_; //!< Handle to the managing thread pool.
+ ThreadHandle thread_; //!< Handle to the thread of execution.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend class ThreadPool<TT,MT,LT,CT>;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Starting a thread in a thread pool.
+//
+// \param pool Handle to the managing thread pool.
+//
+// This function creates a new thread in the given thread pool. The thread is kept alive until
+// explicitly killed by the managing thread pool.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+Thread<TT,MT,LT,CT>::Thread( ThreadPoolType* pool )
+ : terminated_( false ) // Thread termination flag
+ , pool_ ( pool ) // Handle to the managing thread pool
+ , thread_ ( nullptr ) // Handle to the thread of execution
+{
+ thread_.reset( new ThreadType( std::bind( &Thread::run, this ) ) );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Starting a thread of execution on the given zero argument function/functor.
+//
+// \param func The given function/functor.
+// \param args The arguments for the function/functor.
+//
+// This function creates a new thread of execution on the given function/functor. The given
+// function/functor must be copyable, must be callable without arguments and must return void.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+template< typename Callable // Type of the function/functor
+ , typename... Args > // Types of the function/functor arguments
+inline Thread<TT,MT,LT,CT>::Thread( Callable func, Args&&... args )
+ : pool_ ( nullptr ) // Handle to the managing thread pool
+ , thread_( nullptr ) // Handle to the thread of execution
+{
+ thread_.reset( new ThreadType( func, std::forward<Args>( args )... ) );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Destructor for the Thread class.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+Thread<TT,MT,LT,CT>::~Thread()
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether this is a thread of execution.
+//
+// \return \a true if this is a thread of execution, \a false otherwise.
+//
+// This function returns whether this thread is still executing the given task or if it has
+// already finished the job. In case the thread is still execution, the function returns
+// \a true, else it returns \a false.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline bool Thread<TT,MT,LT,CT>::joinable() const
+{
+ return thread_->joinable();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Waiting for a thread of execution to complete.
+//
+// \return void
+//
+// If the thread is still executing the given task, this function blocks until the thread's
+// tasks is completed.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline void Thread<TT,MT,LT,CT>::join()
+{
+ thread_->join();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns whether the thread has terminated its execution.
+//
+// \return \a true in case the thread is terminated, \a false otherwise.
+//
+// This function is used by the managing thread pool to learn whether the thread has finished
+// its execution and can be destroyed.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline bool Thread<TT,MT,LT,CT>::hasTerminated() const
+{
+ return terminated_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// THREAD EXECUTION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Execution function for threads in a thread pool.
+//
+// This function is executed by any thread managed by a thread pool.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+void Thread<TT,MT,LT,CT>::run()
+{
+ // Checking the thread pool handle
+ BLAZE_INTERNAL_ASSERT( pool_, "Uninitialized pool handle detected" );
+
+ // Executing scheduled tasks
+ while( pool_->executeTask() ) {}
+
+ // Setting the termination flag
+ terminated_ = true;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/ThreadPool.h b/src/cpu/blaze/util/ThreadPool.h
new file mode 100644
index 00000000..32c0255a
--- /dev/null
+++ b/src/cpu/blaze/util/ThreadPool.h
@@ -0,0 +1,801 @@
+//=================================================================================================
+/*!
+// \file blaze/util/ThreadPool.h
+// \brief Header file of the ThreadPool class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_THREADPOOL_THREADPOOL_H_
+#define _BLAZE_UTIL_THREADPOOL_THREADPOOL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <functional>
+#include <blaze/util/Assert.h>
+#include <blaze/util/Exception.h>
+#include <blaze/util/NonCopyable.h>
+#include <blaze/util/PtrVector.h>
+#include <blaze/util/StaticAssert.h>
+#include <blaze/util/Thread.h>
+#include <blaze/util/threadpool/Task.h>
+#include <blaze/util/threadpool/TaskQueue.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup threads Thread parallelization
+// \ingroup util
+//
+// The Blaze library offers the capability to either create individual threads for specific
+// tasks (see the Thread class desciption for details) and to create a thread pool according
+// to the thread pool pattern (see the ThreadPool class description). Both class descriptions
+// offer examples for the setup of threads and the parallel execution of concurrent tasks.
+*/
+/*!\brief Implementation of a thread pool.
+// \ingroup threads
+//
+// \section threadpool_general General
+//
+// The ThreadPool class template represents a thread pool according to the thread pool pattern
+// (see for example http://en.wikipedia.org/wiki/Thread_pool_pattern). It manages a certain
+// number of threads in order to process a larger number of independent tasks.
+//
+// \image html threadpool.png
+// \image latex threadpool.eps "Thread pool pattern" width=430pt
+//
+// The primary purpose of a thread pool is the reuse of system resources: instead of creating
+// a single thread for every individual task, threads are reused to handle several tasks. This
+// increases the performance in comparison to different threading strategies, as illustrated
+// in the graph below. The first bar indicates the sequential performance of 1000 matrix-matrix
+// multiplications of arbitrarily sized square matrices. The second bar shows the performance
+// of the same work performed by 1000 distinct threads (i.e. one thread for each matrix-matrix
+// multiplication) on a quad-core system. In this case, all cores of the system can be used,
+// but the additional overhead of creating and managing new threads prevents the expected
+// performance increase by a factor of four. The third bar illustrates the performance of four
+// threads distributing the work between them (i.e. 250 matrix-matrix multiplications per
+// thread), again using the same quad-core system. This approach nearly achieves four times
+// the performance of the sequential execution. The fourth bar represents the performance of
+// the ThreadPool class using fourth threads for the execution of the 1000 individual
+// multiplications.
+//
+// \image html threadpool2.png
+// \image latex threadpool2.eps "Performance comparison of different thread strategies" width=450pt
+//
+// Additionally, the thread pool approach simplifies load balancing and increases the stability
+// of the system.
+//
+//
+// \section threadpool_definition Class Definition
+//
+// The implementation of the ThreadPool class template is based on the implementation of standard
+// thread functionality as provided by the C++11 standard or the Boost library. Via the four
+// template parameters it is possible to configure a ThreadPool instance as either a C++11 thread
+// pool or as Boost thread pool:
+
+ \code
+ template< typename TT, typename MT, typename LT, typename CT >
+ class ThreadPool;
+ \endcode
+
+// - TT: specifies the type of the encapsulated thread. This can either be \c std::thread,
+// \c boost::thread, or any other standard conforming thread type.
+// - MT: specifies the type of the used synchronization mutex. This can for instance be
+// \c std::mutex, \c boost::mutex, or any other standard conforming mutex type.
+// - LT: specifies the type of lock used in combination with the given mutex type. This
+// can be any standard conforming lock type, as for instance \c std::unique_lock,
+// \c boost::unique_lock.
+// - CT: specifies the type of the used condition variable. This can for instance be
+// \c std::condition_variable, \c boost::condition_variable, or any other standard
+// conforming condition variable type.
+//
+// The following example demonstrates how to configure the ThreadPool class template as either
+// C++11 standard thread pool or as Boost thread pool:
+
+ \code
+ typedef blaze::ThreadPool< boost::thread
+ , boost::mutex
+ , boost::unique_lock<boost::mutex>
+ , boost::condition_variable > BoostThreadPool;
+
+ typedef blaze::ThreadPool< std::thread
+ , std::mutex
+ , std::unique_lock<std::mutex>
+ , std::condition_variable > StdThreadPool;
+ \endcode
+
+// For more information about the standard thread functionality, see [1] or [2] or the current
+// documentation at the Boost homepage: www.boost.org.
+//
+//
+// \section threadpool_setup Using the ThreadPool class
+//
+// The following example demonstrates the use of the ThreadPool class. In contrast to the setup
+// of individual threads (see the Thread class description for more details), it is not necessary
+// to create and manage individual threads, but only to schedules tasks for the accordingly sized
+// thread pool.
+
+ \code
+ // Definition of a function with no arguments that returns void
+ void function0() { ... }
+
+ // Definition of a functor (function object) taking two arguments and returning void
+ struct Functor2
+ {
+ void operator()( int a, int b ) { ... }
+ };
+
+ int main()
+ {
+ // Creating a thread pool with initially two working threads
+ StdThreadPool threadpool( 2 );
+
+ // Scheduling two concurrent tasks
+ threadpool.schedule( function0 );
+ threadpool.schedule( Functor2(), 4, 6 );
+
+ // Waiting for the thread pool to complete both tasks
+ threadpool.wait();
+
+ // Resizing the thread pool to four working threads
+ threadpool.resize( 4 );
+
+ // Scheduling other concurrent tasks
+ ...
+ threadpool.schedule( function0 );
+ ...
+
+ // At the end of the thread pool scope, all tasks remaining in the task queue are removed
+ // and all currently running tasks are completed. Additionally, all acquired resources are
+ // safely released.
+ }
+ \endcode
+
+// Note that the ThreadPool class template schedule() function allows for up to five arguments
+// for the given functions/functors.
+//
+//
+// \section threadpool_exception Throwing exceptions in a thread parallel environment
+//
+// It can happen that during the execution of a given task a thread encounters an erroneous
+// situation and has to throw an exception. However, exceptions thrown in the usual way
+// cannot be caught by a try-catch-block in the main thread of execution:
+
+ \code
+ // Definition of a function throwing a std::runtime_error during its execution
+ void task()
+ {
+ ...
+ throw std::runtime_error( ... );
+ ...
+ }
+
+ // Creating a thread pool executing the throwing function. Although the setup, the scheduling
+ // of the task, the wait() function and the destruction of the thread pool are encapsuled
+ // inside a try-catch-block, the exception cannot be caught and results in an abortion of the
+ // program.
+ try {
+ StdThreadpool threadpool( 2 );
+ thread.schedule( task );
+ threadpool.wait();
+ }
+ catch( ... )
+ {
+ ...
+ }
+ \endcode
+
+// For a detailed explanation how to portably transport exceptions between threads, see [1] or
+// [2]. In case of the Boost library, the according Boost functionality as demonstrated in the
+// following example has to be used. Note that any function/functor scheduled for execution is
+// responsible to handle exceptions in this way!
+
+ \code
+ #include <boost/bind.hpp>
+ #include <boost/exception_ptr.hpp>
+
+ // Definition of a function that happens to throw an exception. In order to throw the
+ // exception, boost::enable_current_exception() is used in combination with throw.
+ void throwException()
+ {
+ ...
+ throw boost::enable_current_exception( std::runtime_error( ... ) );
+ ...
+ }
+
+ // Definition of a thread function. The try-catch-block catches the exception and uses the
+ // boost::current_exception() function to get a boost::exception_ptr object.
+ void task( boost::exception_ptr& error )
+ {
+ try {
+ throwException();
+ error = boost::exception_ptr();
+ }
+ catch( ... ) {
+ error = boost::current_exception();
+ }
+ }
+
+ // The function that start a thread of execution can pass along a boost::exception_ptr object
+ // that is set in case of an exception. Note that boost::current_exception() captures the
+ // original type of the exception object. The exception can be thrown again using the
+ // boost::rethrow_exception() function.
+ void work()
+ {
+ boost::exception_ptr error;
+
+ StdThreadPool threadpool( 2 );
+ threadpool.schedule( boost::bind( task, boost::ref(error) ) );
+ threadpool.wait();
+
+ if( error ) {
+ std::cerr << " Exception during thread execution!\n\n";
+ boost::rethrow_exception( error );
+ }
+ }
+ \endcode
+
+// \section threadpool_known_issues Known issues
+//
+// There is a known issue in Visual Studio 2012 and 2013 that may cause C++11 threads to hang
+// if their destructor is executed after the \c main() function:
+//
+// http://connect.microsoft.com/VisualStudio/feedback/details/747145
+//
+// In order to circumvent this problem, for Visual Studio compilers only, it is possible to
+// explicitly resize a ThreadPool instance to 0 threads and to block until all threads have
+// been destroyed:
+
+ \code
+ int main()
+ {
+ static StdThreadPool threadpool( 4 );
+
+ // ... Using the thread pool
+
+ threadpool( 0, true );
+ }
+ \endcode
+
+// Note that this should ONLY be used before the end of the \c main() function and ONLY if the
+// threadpool will not be used anymore.
+//
+//
+// \section threadpool_references References
+//
+// [1] A. Williams: C++ Concurrency in Action, Manning, 2012, ISBN: 978-1933988771\n
+// [2] B. Stroustrup: The C++ Programming Language, Addison-Wesley, 2013, ISBN: 978-0321563842\n
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+class ThreadPool : private NonCopyable
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef Thread<TT,MT,LT,CT> ManagedThread; //!< Type of the managed threads.
+ typedef PtrVector<ManagedThread> Threads; //!< Type of the thread container.
+ typedef threadpool::TaskQueue TaskQueue; //!< Type of the task queue.
+ typedef MT Mutex; //!< Type of the mutex.
+ typedef LT Lock; //!< Type of a locking object.
+ typedef CT Condition; //!< Condition variable type.
+ //**********************************************************************************************
+
+ public:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit ThreadPool( size_t n );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ ~ThreadPool();
+ //@}
+ //**********************************************************************************************
+
+ //**Get functions*******************************************************************************
+ /*!\name Get functions */
+ //@{
+ inline bool isEmpty() const;
+ inline size_t size() const;
+ inline size_t active() const;
+ inline size_t ready() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Task scheduling*****************************************************************************
+ /*!\name Task scheduling */
+ //@{
+ template< typename Callable, typename... Args >
+ void schedule( Callable func, Args&&... args );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ void resize( size_t n, bool block=false );
+ void wait();
+ void clear();
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Thread functions****************************************************************************
+ /*!\name Thread functions */
+ //@{
+ void createThread();
+ bool executeTask();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ volatile size_t total_; //!< Total number of threads in the thread pool.
+ volatile size_t expected_; //!< Expected number of threads in the thread pool.
+ /*!< This number may differ from the total number of threads
+ during a resize of the thread pool. */
+ volatile size_t active_; //!< Number of currently active/busy threads.
+ Threads threads_; //!< The threads contained in the thread pool.
+ TaskQueue taskqueue_; //!< Task queue for the scheduled tasks.
+ mutable Mutex mutex_; //!< Synchronization mutex.
+ Condition waitForTask_; //!< Wait condition for idle threads.
+ Condition waitForThread_; //!< Wait condition for the thread management.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend class Thread<TT,MT,LT,CT>;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor for the ThreadPool class.
+//
+// \param n Initial number of threads \f$[1..\infty)\f$.
+//
+// This constructor creates a thread pool with initially \a n new threads. All threads are
+// initially idle until a task is scheduled.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+ThreadPool<TT,MT,LT,CT>::ThreadPool( size_t n )
+ : total_ ( 0UL ) // Total number of threads in the thread pool
+ , expected_( 0UL ) // Expected number of threads in the thread pool
+ , active_ ( 0UL ) // Number of currently active/busy threads
+ , threads_ () // The threads contained in the thread pool
+ , taskqueue_ () // Task queue for the scheduled tasks
+ , mutex_ () // Synchronization mutex
+ , waitForTask_ () // Wait condition for idle threads
+ , waitForThread_() // Wait condition for the thread management
+{
+ resize( n );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Destructor for the ThreadPool class.
+//
+// The destructor clears all remaining tasks from the task queue and waits for the currently
+// active threads to complete their tasks.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+ThreadPool<TT,MT,LT,CT>::~ThreadPool()
+{
+ Lock lock( mutex_ );
+
+ // Removing all currently queued tasks
+ taskqueue_.clear();
+
+ // Setting the expected number of threads
+ expected_ = 0UL;
+
+ // Notifying all idle threads
+ waitForTask_.notify_all();
+
+ // Waiting for all threads to terminate
+ while( total_ != 0UL ) {
+ waitForThread_.wait( lock );
+ }
+
+ // Joining all threads
+ for( typename Threads::Iterator thread=threads_.begin(); thread!=threads_.end(); ++thread ) {
+ thread->join();
+ }
+
+ // Destroying all threads
+ threads_.clear();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GET FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns whether any tasks are scheduled for execution.
+//
+// \return \a true in case task are scheduled, \a false otherwise.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline bool ThreadPool<TT,MT,LT,CT>::isEmpty() const
+{
+ Lock lock( mutex_ );
+ return taskqueue_.isEmpty();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current size of the thread pool.
+//
+// \return The total number of threads in the thread pool.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline size_t ThreadPool<TT,MT,LT,CT>::size() const
+{
+ Lock lock( mutex_ );
+ return expected_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of currently active/busy threads.
+//
+// \return The number of currently active threads.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline size_t ThreadPool<TT,MT,LT,CT>::active() const
+{
+ Lock lock( mutex_ );
+ return active_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the number of currently ready/inactive threads.
+//
+// \return The number of currently ready threads.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+inline size_t ThreadPool<TT,MT,LT,CT>::ready() const
+{
+ Lock lock( mutex_ );
+ return expected_ - active_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SCHEDULING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Scheduling the given function/functor for execution.
+//
+// \param func The given function/functor.
+// \param args The arguments for the function/functor.
+// \return void
+//
+// This function schedules the given function/functor for execution. The given function/functor
+// must be copyable, must be callable with the given type and number of arguments and must return
+// \c void.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+template< typename Callable // Type of the function/functor
+ , typename... Args > // Types of the function/functor arguments
+void ThreadPool<TT,MT,LT,CT>::schedule( Callable func, Args&&... args )
+{
+ Lock lock( mutex_ );
+ taskqueue_.push( std::bind<void>( func, std::forward<Args>( args )... ) );
+ waitForTask_.notify_one();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Changes the total number of threads in the thread pool.
+//
+// \param n The new number of threads \f$[1..\infty)\f$.
+// \param block \a true if the function shall block, \a false if not.
+// \return void
+// \exception std::invalid_argument Invalid number of threads.
+//
+// This function changes the size of the thread pool, i.e. changes the total number of threads
+// contained in the pool. If \a n is smaller than the current size of the thread pool, the
+// according number of threads is removed from the pool, otherwise new threads are added to
+// the pool. Via the \a block flag it is possible to block the function until the desired
+// number of threads is available.
+//
+// Note that there is a known issue in Visual Studio 2012 and 2013 that may cause C++11 threads
+// to hang if their destructor is executed after the \c main() function:
+//
+// http://connect.microsoft.com/VisualStudio/feedback/details/747145
+//
+// In order to circumvent this problem, for Visual Studio compilers only, it is possible to
+// explicitly resize a ThreadPool instance to 0 threads and to block until all threads have
+// been destroyed:
+
+ \code
+ int main()
+ {
+ static ThreadPool< std::thread
+ , std::mutex
+ , std::unique_lock< std::mutex >
+ , std::condition_variable > threadpool( 4 );
+
+ // ... Using the thread pool
+
+ threadpool( 0, true );
+ }
+ \endcode
+
+// Note that this should ONLY be used before the end of the \c main() function and ONLY if the
+// threadpool will not be used anymore.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+void ThreadPool<TT,MT,LT,CT>::resize( size_t n, bool block )
+{
+ // Checking the given number of threads
+#if !(defined _MSC_VER)
+ if( n == 0UL ) {
+ BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of threads" );
+ }
+#endif
+
+ // Adjusting the number of threads
+ {
+ Lock lock( mutex_ );
+
+ // Adding new threads to the thread pool
+ if( n > expected_ ) {
+ for( size_t i=expected_; i<n; ++i )
+ createThread();
+ }
+
+ // Removing threads from the pool
+ else {
+ expected_ = n;
+ waitForTask_.notify_all();
+
+ while( block && total_ != expected_ ) {
+ waitForThread_.wait( lock );
+ }
+ }
+
+ // Joining and destroying any terminated thread
+ for( typename Threads::Iterator thread=threads_.begin(); thread!=threads_.end(); ) {
+ if( thread->hasTerminated() ) {
+ thread->join();
+ thread = threads_.erase( thread );
+ }
+ else ++thread;
+ }
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Waiting for all scheduled tasks to be completed.
+//
+// \return void
+//
+// This function blocks until all scheduled tasks have been completed.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+void ThreadPool<TT,MT,LT,CT>::wait()
+{
+ Lock lock( mutex_ );
+
+ while( !taskqueue_.isEmpty() || active_ > 0UL ) {
+ waitForThread_.wait( lock );
+ }
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing all scheduled tasks from the thread pool.
+//
+// \return void
+//
+// This function removes all currently scheduled tasks from the thread pool. The total number
+// of threads remains unchanged and all active threads continue completing their tasks.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+void ThreadPool<TT,MT,LT,CT>::clear()
+{
+ Lock lock( mutex_ );
+ taskqueue_.clear();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// THREAD FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Adding a new thread to the thread pool.
+//
+// \return void
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+void ThreadPool<TT,MT,LT,CT>::createThread()
+{
+ threads_.pushBack( new ManagedThread( this ) );
+ ++total_;
+ ++expected_;
+ ++active_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Executing a scheduled task.
+//
+// \return \a true in case a task was successfully finished, \a false if not.
+//
+// This function is repeatedly called by every thread to execute one of the scheduled tasks.
+// In case there is no task available, the thread blocks and waits for a new task to be
+// scheduled.
+*/
+template< typename TT // Type of the encapsulated thread
+ , typename MT // Type of the synchronization mutex
+ , typename LT // Type of the mutex lock
+ , typename CT > // Type of the condition variable
+bool ThreadPool<TT,MT,LT,CT>::executeTask()
+{
+ threadpool::Task task;
+
+ // Acquiring a scheduled task
+ {
+ Lock lock( mutex_ );
+
+ while( taskqueue_.isEmpty() )
+ {
+ --active_;
+ waitForThread_.notify_all();
+
+ if( total_ > expected_ ) {
+ --total_;
+ return false;
+ }
+
+ waitForTask_.wait( lock );
+ ++active_;
+ }
+
+ BLAZE_INTERNAL_ASSERT( !taskqueue_.isEmpty(), "Empty task queue detected" );
+ task = taskqueue_.pop();
+ }
+
+ // Executing the task
+ task();
+
+ return true;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Time.h b/src/cpu/blaze/util/Time.h
new file mode 100644
index 00000000..b321b6e0
--- /dev/null
+++ b/src/cpu/blaze/util/Time.h
@@ -0,0 +1,171 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Time.h
+// \brief Header file for time functions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TIME_H_
+#define _BLAZE_UTIL_TIME_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#if defined(_MSC_VER)
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+# include <windows.h>
+# include <winsock.h>
+# include <time.h>
+# include <sys/timeb.h>
+#else
+# include <sys/resource.h>
+# include <sys/time.h>
+# include <sys/types.h>
+#endif
+#include <ctime>
+#include <string>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// TIME FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name Time functions */
+//@{
+inline std::string getDate();
+inline std::string getTime();
+inline double getWcTime();
+inline double getCpuTime();
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a formated date string in the form YYYY-MM-DD
+// \ingroup util
+//
+// \return Formated date string
+*/
+inline std::string getDate()
+{
+ std::time_t t;
+ std::tm* localTime;
+ char c[50];
+
+ std::time( &t );
+ localTime = std::localtime( &t );
+ std::strftime( c, 50, "%Y-%m-%d", localTime );
+
+ return std::string( c );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating a formated time and date string
+// \ingroup util
+//
+// \return Formated time and date string in the format WEEKDAY DAY.MONTH YEAR, HOUR:MINUTES
+*/
+inline std::string getTime()
+{
+ std::time_t t;
+ std::tm* localTime;
+ char c[50];
+
+ std::time( &t );
+ localTime = std::localtime( &t );
+ std::strftime( c, 50, "%A, %d.%B %Y, %H:%M", localTime );
+
+ return std::string( c );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current wall clock time in seconds.
+// \ingroup util
+//
+// \return The current wall clock time in seconds.
+*/
+inline double getWcTime()
+{
+#ifdef WIN32
+ struct _timeb timeptr;
+ _ftime( &timeptr );
+ return ( static_cast<double>( timeptr.time ) + static_cast<double>( timeptr.millitm )/1E3 );
+#else
+ struct timeval tp;
+ gettimeofday( &tp, nullptr );
+ return ( static_cast<double>( tp.tv_sec ) + static_cast<double>( tp.tv_usec )/1E6 );
+#endif
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current CPU time in seconds.
+// \ingroup util
+//
+// \return The current CPU time in seconds.
+*/
+inline double getCpuTime()
+{
+#ifdef WIN32
+ FILETIME CreateTime, ExitTime, KernelTime, UserTime;
+ SYSTEMTIME SysTime;
+
+ if( GetProcessTimes( GetCurrentProcess(), &CreateTime, &ExitTime, &KernelTime, &UserTime ) != TRUE ) {
+ return 0.0;
+ }
+ else {
+ FileTimeToSystemTime( &UserTime, &SysTime );
+ return ( static_cast<double>( SysTime.wSecond ) + static_cast<double>( SysTime.wMilliseconds )/1E3 );
+ }
+#else
+ struct rusage ruse;
+ getrusage( RUSAGE_SELF, &ruse );
+ return ( static_cast<double>( ruse.ru_utime.tv_sec ) + static_cast<double>( ruse.ru_utime.tv_usec )/1E6 );
+#endif
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Timing.h b/src/cpu/blaze/util/Timing.h
new file mode 100644
index 00000000..8068a2b5
--- /dev/null
+++ b/src/cpu/blaze/util/Timing.h
@@ -0,0 +1,49 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Timing.h
+// \brief Header file for the timing submodule
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TIMING_H_
+#define _BLAZE_UTIL_TIMING_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/timing/CpuPolicy.h>
+#include <blaze/util/timing/CpuTimer.h>
+#include <blaze/util/timing/Timer.h>
+#include <blaze/util/timing/WcPolicy.h>
+#include <blaze/util/timing/WcTimer.h>
+
+#endif
diff --git a/src/cpu/blaze/util/TrueType.h b/src/cpu/blaze/util/TrueType.h
new file mode 100644
index 00000000..f625abb1
--- /dev/null
+++ b/src/cpu/blaze/util/TrueType.h
@@ -0,0 +1,66 @@
+//=================================================================================================
+/*!
+// \file blaze/util/TrueType.h
+// \brief Header file for the TrueType type/value trait base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TRUETYPE_H_
+#define _BLAZE_UTIL_TRUETYPE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ALIAS DECLARATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Type traits base class.
+// \ingroup util
+//
+// The TrueType class is used as base class for type traits and value traits that evaluate to
+// \a true.
+*/
+using TrueType = BoolConstant<true>;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/TypeList.h b/src/cpu/blaze/util/TypeList.h
new file mode 100644
index 00000000..12d1dc3b
--- /dev/null
+++ b/src/cpu/blaze/util/TypeList.h
@@ -0,0 +1,1071 @@
+//=================================================================================================
+/*!
+// \file blaze/util/TypeList.h
+// \brief Header file for a type list implementation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPELIST_H_
+#define _BLAZE_UTIL_TYPELIST_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/NullType.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS TYPELIST
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup typelist Type lists
+// \ingroup util
+//
+// Type lists provide the functionality to create lists of data types. In constrast to lists
+// of data values (as for instance the std::list class template), type lists are created at
+// compile time, not at run time. The type list implementation of the Blaze library closely
+// resembles the original implementation of Andrei Alexandrescu (taken from his book Modern
+// C++, ISBN: 0201704315). The following example demonstrates, how type lists are created
+// and manipulated:
+
+ \code
+ // Creating a type list consisting of two fundamental floating point data types
+ typedef BLAZE_TYPELIST_2( float, double ) Tmp;
+
+ // Appending a type to the type list
+ typedef blaze::Append< Tmp, long double >::Result Floats; // Type list contains all floating point data types
+
+ // Calculating the length of the type list (at compile time!)
+ const int length = Length< Floats >::value; // Value evaluates to 3
+
+ // Accessing a specific type of the type list via indexing
+ typedef blaze::TypeAt< Floats, 0 >::Result Index0;
+
+ // Searching the type list for a specific type
+ const int index1 = blaze::Contains< Floats, double >::value; // Value evaluates to 1
+ const int index2 = blaze::Contains< Floats, int >::value; // Value evaluates to 0
+
+ // Estimating the index of a specific type in the type list
+ const int index3 = blaze::IndexOf< Floats, double >::value; // Value evaluates to 1
+ const int index4 = blaze::IndexOf< Floats, int >::value; // Value evaluates to -1
+
+ // Erasing the first occurrence of float from the type list
+ typedef blaze::Erase< Floats, float >::Result NoFloat;
+
+ // Removing all duplicates from the type list
+ typedef blaze::Unique< Floats >::Result NoDuplicates;
+ \endcode
+*/
+/*!\brief Implementation of a type list.
+// \ingroup typelist
+//
+// The TypeList class is an implementation of a type list according to the example of Andrei
+// Alexandrescu. The type list merely consists of the two data types \a Head and \a Tail. In
+// order to create type lists of more data types, the TypeList class is used recursively:
+
+ \code
+ // Type list containing the three fundamental floating point data types
+ TypeList< float, TypeList< double, TypeList< long double, NullType > > >
+ \endcode
+
+// The NullType data type is used to terminate a type list.\n
+// In order to create a type list, one of the predefined setup macros should be used:
+
+ \code
+ // Creating a type list consisting of the three fundamental data types
+ typedef BLAZE_TYPELIST_3( float, double, long double ) Floats;
+ \endcode
+*/
+template< typename H // Head of the type list
+ , typename T > // Tail of the type list
+struct TypeList
+{
+ //**Type definitions****************************************************************************
+ typedef H Head; //!< Type of the head of the type list.
+ typedef T Tail; //!< Type of the tail of the type list.
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TYPE LIST GENERATION MACROS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list only consisting of the type \a T1. The terminating type for
+// the type list is the NullType. The following example demonstrates the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of a single data type
+ typedef BLAZE_TYPELIST_1( int ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_1( T1 ) \
+ TypeList< T1, NullType >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the two types \a T1 and \a T2. The terminating
+// type for the type list is the NullType. The following example demonstrates the use of this
+// macro:
+
+ \code
+ // Definition of a new type list consisting of two data types
+ typedef BLAZE_TYPELIST_2( int, unsigned int ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_2( T1, T2 ) \
+ TypeList< T1, BLAZE_TYPELIST_1( T2 ) >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the three types \a T1, \a T2 and \a T3. The
+// terminating type for the type list is the NullType. The following example demonstrates
+// the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of three data types
+ typedef BLAZE_TYPELIST_3( float, double, long double ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_3( T1, T2, T3 ) \
+ TypeList< T1, BLAZE_TYPELIST_2( T2, T3 ) >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the four types \a T1, \a T2, \a T3 and \a T4.
+// The terminating type for the type list is the NullType. The following example demonstrates
+// the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of four data types
+ typedef BLAZE_TYPELIST_4( unsigned char, signed char, char, wchar_t ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_4( T1, T2, T3, T4 ) \
+ TypeList< T1, BLAZE_TYPELIST_3( T2, T3, T4 ) >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the five types \a T1, \a T2, \a T3, \a T4
+// and \a T5. The terminating type for the type list is the NullType. The following example
+// demonstrates the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of five data types
+ typedef BLAZE_TYPELIST_5( char, short, int, long, float ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_5( T1, T2, T3, T4, T5 ) \
+ TypeList< T1, BLAZE_TYPELIST_4( T2, T3, T4, T5 ) >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the six types \a T1, \a T2, \a T3, \a T4, \a T5
+// and \a T6. The terminating type for the type list is the NullType. The following example
+// demonstrates the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of six data types
+ typedef BLAZE_TYPELIST_6( char, short, int, long, float, double ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_6( T1, T2, T3, T4, T5, T6 ) \
+ TypeList< T1, BLAZE_TYPELIST_5( T2, T3, T4, T5, T6 ) >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the seven types \a T1, \a T2, \a T3, \a T4,
+// \a T5, \a T6 and \a T7. The terminating type for the type list is the NullType. The
+// following example demonstrates the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of seven data types
+ typedef BLAZE_TYPELIST_7( char, short, int, long, float, double, long double ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_7( T1, T2, T3, T4, T5, T6, T7 ) \
+ TypeList< T1, BLAZE_TYPELIST_6( T2, T3, T4, T5, T6, T7 ) >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the eight types \a T1, \a T2, \a T3, \a T4,
+// \a T5, \a T6, \a T7 and \a T8. The terminating type for the type list is the NullType.
+// The following example demonstrates the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of eight data types
+ typedef BLAZE_TYPELIST_8( char, wchar_t, short, int, long, float, double, long double ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_8( T1, T2, T3, T4, T5, T6, T7, T8 ) \
+ TypeList< T1, BLAZE_TYPELIST_7( T2, T3, T4, T5, T6, T7, T8 ) >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the nine types \a T1, \a T2, \a T3, \a T4,
+// \a T5, \a T6, \a T7, \a T8 and \a T9. The terminating type for the type list is the NullType.
+// The following example demonstrates the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of nine data types
+ typedef BLAZE_TYPELIST_9( char, signed char, wchar_t, short, int, long, float, double, long double ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_9( T1, T2, T3, T4, T5, T6, T7, T8, T9 ) \
+ TypeList< T1, BLAZE_TYPELIST_8( T2, T3, T4, T5, T6, T7, T8, T9 ) >
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type list generation macro.
+// \ingroup typelist
+//
+// This macro creates a type list consisting of the ten types \a T1, \a T2, \a T3, \a T4,
+// \a T5, \a T6, \a T7, \a T8, \a T9 and \a T10. The terminating type for the type list is
+// the NullType. The following example demonstrates the use of this macro:
+
+ \code
+ // Definition of a new type list consisting of ten data types
+ typedef BLAZE_TYPELIST_10( unsigned char, signed char, char, wchar_t, unsigned short,
+ short, unsigned int, int, unsigned long, long ) MyTypes;
+
+ // Calculating the length of the type list
+ const int length = Length<MyTypes>::value;
+ \endcode
+*/
+#define BLAZE_TYPELIST_10( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 ) \
+ TypeList< T1, BLAZE_TYPELIST_9( T2, T3, T4, T5, T6, T7, T8, T9, T10 ) >
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LENGTH OF A TYPE LIST
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::Length
+// \brief Calculating the length of a type list.
+// \ingroup typelist
+//
+// The Length class can be used to obtain the length of a type list (i.e. the number
+// of contained types). In order to obtain the length of a type list, the Length class
+// has to be instantiated for a particular type list. The length of the type list can
+// be obtained using the member enumeration \a value. The following example gives an
+// impression of the use of the Length class:
+
+ \code
+ typedef BLAZE_TYPELIST_3( float, double, long double ) Floats; // Defining a new type list
+ const int length = blaze::Length< Floats >::value; // The length of the type list
+ \endcode
+*/
+template< typename TList > // Type of the type list
+struct Length;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Length class for empty type lists.
+// \ingroup typelist
+*/
+template<>
+struct Length< NullType >
+{
+ //**Member enumeration**************************************************************************
+ enum { value = 0 };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Length class for general type lists.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail > // Type of the tail of the type list
+struct Length< TypeList<Head,Tail> >
+{
+ //**Member enumeration**************************************************************************
+ enum { value = 1 + Length<Tail>::value };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// INDEXED ACCESS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::TypeAt
+// \brief Indexing a type list.
+// \ingroup typelist
+//
+// The TypeAt class can be used to access a type list at a specified position to query the
+// according type. In order to index a type list, the TypeAt class has to be instantiated
+// for a particular type list and an index value. The indexed type is available via the
+// member type definition \a Result. The following example gives an impression of the use
+// of the TypeAt class:
+
+ \code
+ typedef BLAZE_TYPELIST_3( float, double, long double ) Floats; // Defining a new type list
+ typedef blaze::TypeAt< Floats, 0 >::Result Index0; // Indexing of the type list at index 0
+ \endcode
+
+// \note The access index is zero based!
+*/
+template< typename TList // Type of the type list
+ , size_t Index > // Type list access index
+struct TypeAt;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TypeAt class for an index of 0.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail > // Type of the tail of the type list
+struct TypeAt< TypeList<Head,Tail>, 0 >
+{
+ //**Member enumeration**************************************************************************
+ typedef Head Result; //!< Data type at index 0.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the TypeAt class for the terminating NullType.
+// \ingroup typelist
+*/
+template< size_t Index > // Type list access index
+struct TypeAt< NullType, Index >
+{
+ //**Member enumeration**************************************************************************
+ typedef NullType Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the TypeAt class for a general index.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail // Type of the tail of the type list
+ , size_t Index > // Type list access index
+struct TypeAt< TypeList<Head,Tail>, Index >
+{
+ //**Member enumeration**************************************************************************
+ typedef typename TypeAt< Tail, Index-1 >::Result Result; //!< Data type at indexed position.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TYPE LIST SEARCH
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::Contains
+// \brief Searching a type list.
+// \ingroup typelist
+//
+// The Contains class can be used to search the type list for a particular type \a Type. In
+// contrast to the IndexOf class, the Contains class does not evaluate the index of the type
+// but only checks whether or not the type is contained in the type list. Additionally, in
+// contrast to the ContainsRelated class, the Contains class strictly searches for the given
+// type \a Type and not for a related data type. In case the type is contained in the type
+// list, the \a value member enumeration is set to 1, else it is set to 0. In order to check
+// whether a type is part of a type list, the Contains class has to be instantiated for a
+// particular type list and another type. The following example gives an impression of the
+// use of the Contains class:
+
+ \code
+ typedef BLAZE_TYPELIST_3( float, double, long double ) Floats; // Defining a new type list
+ const int index1 = blaze::Contains< Floats, double >::value; // Value evaluates to 1
+ const int index2 = blaze::Contains< Floats, int >::value; // Value evaluates to 0
+ \endcode
+*/
+template< typename TList // Type of the type list
+ , typename Type > // The search type
+struct Contains;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Contains class for the terminating NullType.
+// \ingroup typelist
+*/
+template< typename Type > // The search type
+struct Contains< NullType, Type >
+{
+ //**Member enumeration**************************************************************************
+ enum { value = 0 }; //!< \a Type is not contained in the type list.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Contains class for a successful search.
+// \ingroup typelist
+*/
+template< typename Tail // Type of the tail of the type list
+ , typename Type > // The search type
+struct Contains< TypeList<Type,Tail>, Type >
+{
+ //**Member enumeration**************************************************************************
+ enum { value = 1 }; //!< \a Type is the head of the type list.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Contains class for a general type list.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail // Type of the tail of the type list
+ , typename Type > // The search type
+struct Contains< TypeList<Head,Tail>, Type >
+{
+ //**Member enumeration**************************************************************************
+ enum { value = Contains<Tail,Type>::value }; //!< Search result for type \a Type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::ContainsRelated
+// \brief Searching a type list.
+// \ingroup typelist
+//
+// The ContainsRelated class can be used to search the type list for a type related to \a Type.
+// In contrast to the Contains class, the ContainsRelated class only searches for a type the
+// given data type \a Type can be converted to. In case a related type is found in the type
+// list, the \a value member enumeration is set to 1, else it is set to 0. In order to check
+// whether a related type is contained in the type list, the ContainsRelated class has to be
+// instantiated for a particular type list and another type. The following example gives an
+// impression of the use of the ContainsRelated class:
+
+ \code
+ class A {};
+ class B : public A {};
+ class C {};
+ class D {};
+
+ // Defining a new type list
+ typedef BLAZE_TYPELIST_2( A, C ) Types;
+
+ // Searching for the type A in the type list
+ const int a = blaze::ContainsRelated< Types, A >::value; // Evaluates to 1, type A is found
+
+ // Searching for the derived type B in the type list
+ const int b = blaze::ContainsRelated< Types, B >::value; // Evaluates to 1, base type A is found
+
+ // Searching for the type C in the type list
+ const int c = blaze::ContainsRelated< Types, D >::value; // Evaluates to 0, no related type found
+ \endcode
+*/
+template< typename TList // Type of the type list
+ , typename Type > // The search type
+struct ContainsRelated;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the ContainsRelated class for the terminating NullType.
+// \ingroup typelist
+*/
+template< typename Type > // The search type
+struct ContainsRelated< NullType, Type >
+{
+ //**Member enumeration**************************************************************************
+ enum { value = 0 }; //!< No related type of \a Type is contained in the type list.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the ContainsRelated class for a general type list.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail // Type of the tail of the type list
+ , typename Type > // The search type
+struct ContainsRelated< TypeList<Head,Tail>, Type >
+{
+ private:
+ //**********************************************************************************************
+ class No {};
+ class Yes { No no[2]; };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ static Yes test( Head );
+ static No test( ... );
+ static Type createType();
+ //**********************************************************************************************
+
+ //**Member enumeration**************************************************************************
+ enum { tmp = sizeof( test( createType() ) ) == sizeof( Yes ) ? 1 : 0 }; //!< Relationship evaluation.
+ //**********************************************************************************************
+
+ public:
+ //**Member enumeration**************************************************************************
+ enum { value = tmp == 1 ? 1 : ( ContainsRelated<Tail,Type>::value ) }; //!< Search result for type \a Type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::IndexOf
+// \brief Searching a type list.
+// \ingroup typelist
+//
+// The IndexOf class can be used to search the type list for a particular type \a Type. In
+// contrast to the Contains and the ContainsRelated classes, the IndexOf class evaluates the
+// index of the given type in the type list. In case the type is contained in the type list,
+// the \a value member represents the index of the queried type. Otherwise the \a value member
+// is set to -1. In order to search for a type, the IndexOf class has to be instantiated for
+// a particular type list and a search type. The following example gives an impression of the
+// use of the IndexOf class:
+
+ \code
+ typedef BLAZE_TYPELIST_3( float, double, long double ) Floats; // Defining a new type list
+ const int index1 = blaze::IndexOf< Floats, double >::value; // Value evaluates to 1
+ const int index2 = blaze::IndexOf< Floats, int >::value; // Value evaluates to -1
+ \endcode
+*/
+template< typename TList // Type of the type list
+ , typename Type > // The search type
+struct IndexOf;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the IndexOf class for the terminating NullType.
+// \ingroup typelist
+*/
+template< typename Type > // The search type
+struct IndexOf< NullType, Type >
+{
+ //**Member enumeration**************************************************************************
+ enum { value = -1 }; //!< \a Type is not contained in the type list.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the IndexOf class for a successful search.
+// \ingroup typelist
+*/
+template< typename Tail // Type of the tail of the type list
+ , typename Type > // The search type
+struct IndexOf< TypeList<Type,Tail>, Type >
+{
+ //**Member enumeration**************************************************************************
+ enum { value = 0 }; //!< \a Type is the head of the type list.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the IndexOf class for a general type list.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail // Type of the tail of the type list
+ , typename Type > // The search type
+struct IndexOf< TypeList<Head,Tail>, Type >
+{
+ private:
+ //**Member enumeration**************************************************************************
+ enum { tmp = IndexOf<Tail,Type>::value }; //!< Index of \a Type in the tail of the type list.
+ //**********************************************************************************************
+
+ public:
+ //**Member enumeration**************************************************************************
+ enum { value = tmp == -1 ? -1 : 1 + tmp }; //!< Index of \a Type in the entire type list.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// APPENDING TO TYPE LISTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::Append
+// \brief Appending a type to a type list.
+// \ingroup typelist
+//
+// The Append class can be used to append the data type \a Type to a type list \a TList. In
+// order to append a data type, the Append class has to be instantiated for a particular type
+// list and another type. The following example gives an impression of the use of the Append
+// class:
+
+ \code
+ typedef BLAZE_TYPELIST_2( float, double ) Tmp; // Defining a temporary type list
+ typedef blaze::Append<Tmp,long double>::Result Floats; // Type list contains all floating point data types
+ \endcode
+*/
+template< typename TList // Type of the type list
+ , typename Type > // The type to be appended to the type list
+struct Append;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Append class for appending the NullType.
+// \ingroup typelist
+*/
+template<>
+struct Append< NullType, NullType >
+{
+ //**Type definitions****************************************************************************
+ typedef NullType Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Append class for appending a general type to the NullType.
+// \ingroup typelist
+*/
+template< typename Type > // The type to be appended to the type list
+struct Append< NullType, Type >
+{
+ //**Type definitions****************************************************************************
+ typedef BLAZE_TYPELIST_1( Type ) Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Append class for appending a type list to the NullType.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail > // Type of the tail of the type list
+struct Append< NullType, TypeList<Head,Tail> >
+{
+ //**Type definitions****************************************************************************
+ typedef TypeList<Head,Tail> Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Append class for appending a general type to a type list.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail // Type of the tail of the type list
+ , typename Type > // The type to be appended to the type list
+struct Append< TypeList<Head,Tail>, Type >
+{
+ //**Type definitions****************************************************************************
+ typedef TypeList< Head, typename Append<Tail,Type>::Result > Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ERASING FROM TYPE LISTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::Erase
+// \brief Erasing the first occurrence of a type from a type list.
+// \ingroup typelist
+//
+// The Erase class can be used to erase the first occurrence of data type \a Type from a type
+// list \a TList. In order to erase the first occurrence of a data type, the Erase class has to
+// be instantiated for a particular type list and another type. The following example gives an
+// impression of the use of the Erase class:
+
+ \code
+ // Defining a temporary type list containing the type int twice
+ typedef BLAZE_TYPELIST_4( float, int, double, int ) Tmp;
+
+ // Erasing the first occurrence of int from the type list
+ typedef blaze::Erase<Tmp,int>::Result SingleInt;
+ \endcode
+*/
+template< typename TList // Type of the type list
+ , typename Type > // The type to be erased from the type list
+struct Erase;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Erase class for the terminating NullType.
+// \ingroup typelist
+*/
+template< typename Type > // The type to be erased from the type list
+struct Erase< NullType, Type >
+{
+ //**Type definitions****************************************************************************
+ typedef NullType Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Erase class for erasing the first occurrence of T.
+// \ingroup typelist
+*/
+template< typename Type // The type to be erased from the type list
+ , typename Tail > // Type of the tail of the type list
+struct Erase< TypeList<Type,Tail>, Type >
+{
+ //**Type definitions****************************************************************************
+ typedef Tail Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Erase class for a general type list.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail // Type of the tail of the type list
+ , typename Type > // The type to be erased from the type list
+struct Erase< TypeList<Head,Tail>, Type >
+{
+ //**Type definitions****************************************************************************
+ typedef TypeList<Head,typename Erase<Tail,Type>::Result> Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::EraseAll
+// \brief Erasing all occurrences of a type from a type list.
+// \ingroup typelist
+//
+// The EraseAll class can be used to erase all occurrences of data type \a Type from a type list
+// \a TList. In order to erase all occurrences of a data type, the EraseAll class has to be
+// instantiated for a particular type list and another type. The following example gives an
+// impression of the use of the EraseAll class:
+
+ \code
+ // Defining a temporary type list containing the type int twice
+ typedef BLAZE_TYPELIST_4( float, int, double, int ) Tmp;
+
+ // Erasing the all occurrences of int from the type list
+ typedef blaze::EraseAll<Tmp,int>::Result NoInt;
+ \endcode
+*/
+template< typename TList // Type of the type list
+ , typename Type > // The type to be erased from the type list
+struct EraseAll;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the EraseAll class for the terminating NullType.
+// \ingroup typelist
+*/
+template< typename Type > // The type to be erased from the type list
+struct EraseAll< NullType, Type >
+{
+ //**Type definitions****************************************************************************
+ typedef NullType Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the EraseAll class for erasing an occurrence of T.
+// \ingroup typelist
+*/
+template< typename Type // The type to be erased from the type list
+ , typename Tail > // Type of the tail of the type list
+struct EraseAll< TypeList<Type,Tail>, Type >
+{
+ //**Type definitions****************************************************************************
+ typedef typename EraseAll<Tail,Type>::Result Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the EraseAll class for a general type list.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail // Type of the tail of the type list
+ , typename Type > // The type to be erased from the type list
+struct EraseAll< TypeList<Head,Tail>, Type >
+{
+ //**Type definitions****************************************************************************
+ typedef TypeList<Head,typename EraseAll<Tail,Type>::Result> Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// REMOVING DUPLICATES FROM TYPE LISTS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::Unique
+// \brief Erasing all duplicates from a type list.
+// \ingroup typelist
+//
+// The Unique class can be used to erase all duplicates from a type list \a TList. In order to
+// erase all duplicates, the Unique class has to be instantiated for a particular type list.
+// The following example gives an impression of the use of the Unique class:
+
+ \code
+ // Defining a temporary type list containing the types int and float twice
+ typedef BLAZE_TYPELIST_5( float, int, double, int, float ) Tmp;
+
+ // Removing all duplicates from the type list
+ typedef blaze::Unique<Tmp>::Result NoDuplicates;
+ \endcode
+*/
+template< typename TList > // Type of the type list
+struct Unique;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Unique class for the terminating NullType.
+// \ingroup typelist
+*/
+template<>
+struct Unique< NullType >
+{
+ //**Type definitions****************************************************************************
+ typedef NullType Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Spezialization of the Unique class for a general type list.
+// \ingroup typelist
+*/
+template< typename Head // Type of the head of the type list
+ , typename Tail > // Type of the tail of the type list
+struct Unique< TypeList<Head,Tail> >
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef typename Unique<Tail>::Result TL1;
+ typedef typename Erase<TL1,Head>::Result TL2;
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef TypeList<Head,TL2> Result; //!< The resulting data type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/TypeTraits.h b/src/cpu/blaze/util/TypeTraits.h
new file mode 100644
index 00000000..4b739188
--- /dev/null
+++ b/src/cpu/blaze/util/TypeTraits.h
@@ -0,0 +1,106 @@
+//=================================================================================================
+/*!
+// \file blaze/util/TypeTraits.h
+// \brief Header file for all type traits
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_H_
+#define _BLAZE_UTIL_TYPETRAITS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/AddConst.h>
+#include <blaze/util/typetraits/AddCV.h>
+#include <blaze/util/typetraits/AddPointer.h>
+#include <blaze/util/typetraits/AddReference.h>
+#include <blaze/util/typetraits/AddVolatile.h>
+#include <blaze/util/typetraits/AlignmentOf.h>
+#include <blaze/util/typetraits/All.h>
+#include <blaze/util/typetraits/Any.h>
+#include <blaze/util/typetraits/CommonType.h>
+#include <blaze/util/typetraits/Decay.h>
+#include <blaze/util/typetraits/Extent.h>
+#include <blaze/util/typetraits/GetMemberType.h>
+#include <blaze/util/typetraits/HasMember.h>
+#include <blaze/util/typetraits/HasSize.h>
+#include <blaze/util/typetraits/HaveSameSize.h>
+#include <blaze/util/typetraits/IsArithmetic.h>
+#include <blaze/util/typetraits/IsArray.h>
+#include <blaze/util/typetraits/IsAssignable.h>
+#include <blaze/util/typetraits/IsBaseOf.h>
+#include <blaze/util/typetraits/IsBoolean.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsCharacter.h>
+#include <blaze/util/typetraits/IsClass.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsComplexDouble.h>
+#include <blaze/util/typetraits/IsComplexFloat.h>
+#include <blaze/util/typetraits/IsConst.h>
+#include <blaze/util/typetraits/IsConstructible.h>
+#include <blaze/util/typetraits/IsConvertible.h>
+#include <blaze/util/typetraits/IsDestructible.h>
+#include <blaze/util/typetraits/IsDouble.h>
+#include <blaze/util/typetraits/IsEmpty.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+#include <blaze/util/typetraits/IsInteger.h>
+#include <blaze/util/typetraits/IsIntegral.h>
+#include <blaze/util/typetraits/IsLong.h>
+#include <blaze/util/typetraits/IsLongDouble.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/IsObject.h>
+#include <blaze/util/typetraits/IsPod.h>
+#include <blaze/util/typetraits/IsPointer.h>
+#include <blaze/util/typetraits/IsReference.h>
+#include <blaze/util/typetraits/IsSame.h>
+#include <blaze/util/typetraits/IsShort.h>
+#include <blaze/util/typetraits/IsSigned.h>
+#include <blaze/util/typetraits/IsUnion.h>
+#include <blaze/util/typetraits/IsUnsigned.h>
+#include <blaze/util/typetraits/IsValid.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+#include <blaze/util/typetraits/IsVoid.h>
+#include <blaze/util/typetraits/IsVolatile.h>
+#include <blaze/util/typetraits/MakeSigned.h>
+#include <blaze/util/typetraits/MakeUnsigned.h>
+#include <blaze/util/typetraits/Rank.h>
+#include <blaze/util/typetraits/RemoveAllExtents.h>
+#include <blaze/util/typetraits/RemoveConst.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+#include <blaze/util/typetraits/RemoveExtent.h>
+#include <blaze/util/typetraits/RemovePointer.h>
+#include <blaze/util/typetraits/RemoveReference.h>
+#include <blaze/util/typetraits/RemoveVolatile.h>
+
+#endif
diff --git a/src/cpu/blaze/util/Types.h b/src/cpu/blaze/util/Types.h
new file mode 100644
index 00000000..01f9c1ee
--- /dev/null
+++ b/src/cpu/blaze/util/Types.h
@@ -0,0 +1,180 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Types.h
+// \brief Header file for basic type definitions
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPES_H_
+#define _BLAZE_UTIL_TYPES_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <cstddef>
+#include <cstdint>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// TYPE DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\class blaze::size_t
+// \brief Size type of the Blaze library.
+// \ingroup util
+*/
+using std::size_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::ptrdiff_t
+// \brief Pointer difference type of the Blaze library.
+// \ingroup util
+*/
+using std::ptrdiff_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Byte data type of the Blaze library.
+// \ingroup util
+//
+// The \a byte data type is guaranteed to be an integral data type of size 1.
+*/
+using byte_t = unsigned char;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::int8_t
+// \brief 8-bit signed integer type of the Blaze library.
+// \ingroup util
+*/
+using std::int8_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::uint8_t
+// \brief 8-bit unsigned integer type of the Blaze library.
+// \ingroup util
+*/
+using std::uint8_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::int16_t
+// \brief 16-bit signed integer type of the Blaze library.
+// \ingroup util
+*/
+using std::int16_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::uint16_t
+// \brief 16-bit unsigned integer type of the Blaze library.
+// \ingroup util
+*/
+using std::uint16_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::int32_t
+// \brief 32-bit signed integer type of the Blaze library.
+// \ingroup util
+*/
+using std::int32_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::uint32_t
+// \brief 32-bit unsigned integer type of the Blaze library.
+// \ingroup util
+*/
+using std::uint32_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::int64_t
+// \brief 64-bit signed integer type of the Blaze library.
+// \ingroup util
+*/
+using std::int64_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\class blaze::uint64_t
+// \brief 64-bit unsigned integer type of the Blaze library.
+// \ingroup util
+*/
+using std::uint64_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The largest available signed integer data type.
+// \ingroup util
+*/
+using large_t = int64_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief The largest available unsigned integer data type.
+// \ingroup util
+*/
+using ularge_t = uint64_t;
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Unsigned integer data type for integral IDs.
+// \ingroup util
+*/
+using id_t = ularge_t;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/UnsignedValue.h b/src/cpu/blaze/util/UnsignedValue.h
new file mode 100644
index 00000000..24605df8
--- /dev/null
+++ b/src/cpu/blaze/util/UnsignedValue.h
@@ -0,0 +1,391 @@
+//=================================================================================================
+/*!
+// \file blaze/util/UnsignedValue.h
+// \brief Header file for the UnsignedValue class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_UNSIGNEDVALUE_H_
+#define _BLAZE_UTIL_UNSIGNEDVALUE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <istream>
+#include <ostream>
+#include <blaze/util/constraints/Unsigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of a wrapper for built-in unsigned integral values.
+// \ingroup util
+//
+// This class wraps a value of built-in unsigned integral type in order to be able to extract
+// non-negative unsigned integral values from an input stream.
+*/
+template< typename T > // Type of the unsigned value
+class UnsignedValue
+{
+ public:
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit inline UnsignedValue( T value=0 );
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Assignment operator*************************************************************************
+ /*!\name Assignment operator */
+ //@{
+ inline UnsignedValue& operator=( T value );
+ // No explicitly declared copy assignment operator.
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operator*************************************************************************
+ /*!\name Conversion operator */
+ //@{
+ inline operator T() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Access function*****************************************************************************
+ /*!\name Access functions */
+ //@{
+ inline T get() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ T value_; //!< The wrapped built-in unsigned integral value.
+ //@}
+ //**********************************************************************************************
+
+ //**Compile time checks*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_CONSTRAINT_MUST_BE_UNSIGNED_TYPE( T );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The default constructor for UnsignedInt.
+//
+// \param value The initial value for the unsigned integer.
+*/
+template< typename T > // Type of the unsigned value
+inline UnsignedValue<T>::UnsignedValue( T value )
+ : value_( value ) // The wrapped built-in unsigned integral value
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ASSIGNMENT OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Assignment of a built-in unsigned integral value.
+//
+// \param value The unsigned integral value.
+// \return Reference to the assigned UnsignedValue object.
+*/
+template< typename T > // Type of the unsigned value
+inline UnsignedValue<T>& UnsignedValue<T>::operator=( T value )
+{
+ value_ = value;
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion to the built-in unsigned integral type.
+//
+// \return The wrapped built-in unsigned integral value.
+*/
+template< typename T > // Type of the unsigned value
+inline UnsignedValue<T>::operator T() const
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ACCESS FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Access to the wrapped built-in unsigned integral value.
+//
+// \return The wrapped built-in unsigned integral value.
+*/
+template< typename T > // Type of the unsigned value
+inline T UnsignedValue<T>::get() const
+{
+ return value_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name UnsignedValue operators */
+//@{
+template< typename T1, typename T2 >
+inline bool operator==( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs );
+
+template< typename T1, typename T2 >
+inline bool operator!=( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs );
+
+template< typename T1, typename T2 >
+inline bool operator< ( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs );
+
+template< typename T1, typename T2 >
+inline bool operator> ( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs );
+
+template< typename T1, typename T2 >
+inline bool operator<=( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs );
+
+template< typename T1, typename T2 >
+inline bool operator>=( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs );
+
+template< typename T >
+inline std::ostream& operator<<( std::ostream& os, const UnsignedValue<T>& uv );
+
+template< typename T >
+std::istream& operator>>( std::istream& is, UnsignedValue<T>& uv );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between two UnsignedValue objects.
+//
+// \param lhs The left-hand side UnsignedValue wrapper.
+// \param rhs The right-hand side UnsignedValue wrapper.
+// \return \a true if the two values are equal, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side unsigned value
+ , typename T2 > // Type of the right-hand side unsigned value
+inline bool operator==( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs )
+{
+ return lhs.get() == rhs.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Inequality comparison between two UnsignedValue objects.
+//
+// \param lhs The left-hand side UnsignedValue wrapper.
+// \param rhs The right-hand side UnsignedValue wrapper.
+// \return \a true if the two values are not equal, \a true if they are equal.
+*/
+template< typename T1 // Type of the left-hand side unsigned value
+ , typename T2 > // Type of the right-hand side unsigned value
+inline bool operator!=( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs )
+{
+ return lhs.get() != rhs.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-than comparison between two UnsignedValue objects.
+//
+// \param lhs The left-hand side UnsignedValue wrapper.
+// \param rhs The right-hand side UnsignedValue wrapper.
+// \return \a true if the left value is less than the right value, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side unsigned value
+ , typename T2 > // Type of the right-hand side unsigned value
+inline bool operator<( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs )
+{
+ return lhs.get() < rhs.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-than comparison between two UnsignedValue objects.
+//
+// \param lhs The left-hand side UnsignedValue wrapper.
+// \param rhs The right-hand side UnsignedValue wrapper.
+// \return \a true if the left value if greater than the right value, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side unsigned value
+ , typename T2 > // Type of the right-hand side unsigned value
+inline bool operator>( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs )
+{
+ return lhs.get() > rhs.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Less-or-equal-than comparison between two UnsignedValue objects.
+//
+// \param lhs The left-hand side UnsignedValue wrapper.
+// \param rhs The right-hand side UnsignedValue wrapper.
+// \return \a true if the left value is less or equal than the right value, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side unsigned value
+ , typename T2 > // Type of the right-hand side unsigned value
+inline bool operator<=( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs )
+{
+ return lhs.get() <= rhs.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Greater-or-equal-than comparison between two UnsignedValue objects.
+//
+// \param lhs The left-hand side UnsignedValue wrapper.
+// \param rhs The right-hand side UnsignedValue wrapper.
+// \return \a true if the left value is greater or equal than the right value, \a false if not.
+*/
+template< typename T1 // Type of the left-hand side unsigned value
+ , typename T2 > // Type of the right-hand side unsigned value
+inline bool operator>=( const UnsignedValue<T1>& lhs, const UnsignedValue<T2>& rhs )
+{
+ return lhs.get() >= rhs.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Global output operator for the UnsignedValue wrapper.
+//
+// \param os Reference to the output stream.
+// \param uv Reference to a UnsignedValue object.
+// \return The output stream.
+*/
+template< typename T > // Type of the unsigned value
+inline std::ostream& operator<<( std::ostream& os, const UnsignedValue<T>& uv )
+{
+ return os << uv.get();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Global input operator for the UnsignedValue wrapper.
+//
+// \param is Reference to the input stream.
+// \param uv Reference to a UnsignedValue object.
+// \return The input stream.
+//
+// The input operator guarantees that this object is not changed in the case of an input error.
+// Only values suitable for the according built-in unsigned integral data type \a T are allowed.
+// Otherwise, the input stream's position is returned to its previous position and the
+// \a std::istream::failbit is set.
+*/
+template< typename T > // Type of the unsigned value
+std::istream& operator>>( std::istream& is, UnsignedValue<T>& uv )
+{
+ T tmp;
+ const std::istream::pos_type pos( is.tellg() );
+
+ // Skipping any leading whitespaces
+ is >> std::ws;
+
+ // Extracting the value
+ if( is.peek() == '-' || !(is >> tmp) )
+ {
+ is.clear();
+ is.seekg( pos );
+ is.setstate( std::istream::failbit );
+ return is;
+ }
+
+ // Transfering the input to the unsigned integer value
+ uv = tmp;
+
+ return is;
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Unused.h b/src/cpu/blaze/util/Unused.h
new file mode 100644
index 00000000..a44d70f2
--- /dev/null
+++ b/src/cpu/blaze/util/Unused.h
@@ -0,0 +1,157 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Unused.h
+// \brief Header file for the UNUSED_PARAMETER function template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_UNUSED_H_
+#define _BLAZE_UTIL_UNUSED_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// UNUSED_PARAMETER FUNCTION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Suppression of unused parameter warnings.
+// \ingroup util
+//
+// \return void
+//
+// The UNUSED_PARAMETER function provides the functionality to suppress warnings about up to
+// six unused parameters. Usually this problem occurs in case a parameter is given a name but
+// is not used within the function:
+
+ \code
+ void f( int x )
+ {} // x is not used within f. This may result in an unused parameter warning.
+ \endcode
+
+// A possible solution is to keep the parameter unnamed:
+
+ \code
+ void f( int )
+ {} // No warning about unused parameter is issued
+ \endcode
+
+// However, there are situations where is approach is not possible, as for instance in case the
+// variable must be documented via Doxygen. For these cases, the UNUSED_PARAMETER class can be
+// used to suppress the warnings:
+
+ \code
+ void f( int x )
+ {
+ UNUSED_PARAMETER( x ); // Suppresses the unused parameter warnings
+ }
+ \endcode
+*/
+template< typename T1 >
+inline void UNUSED_PARAMETER( const T1& )
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the UNUSED_PARAMETER function for two parameters.
+// \ingroup util
+//
+// \return void
+*/
+template< typename T1, typename T2 >
+inline void UNUSED_PARAMETER( const T1&, const T2& )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the UNUSED_PARAMETER function for three parameters.
+// \ingroup util
+//
+// \return void
+*/
+template< typename T1, typename T2, typename T3 >
+inline void UNUSED_PARAMETER( const T1&, const T2&, const T3& )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the UNUSED_PARAMETER function for four parameters.
+// \ingroup util
+//
+// \return void
+*/
+template< typename T1, typename T2, typename T3, typename T4 >
+inline void UNUSED_PARAMETER( const T1&, const T2&, const T3&, const T4& )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the UNUSED_PARAMETER function for five parameters.
+// \ingroup util
+//
+// \return void
+*/
+template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+inline void UNUSED_PARAMETER( const T1&, const T2&, const T3&, const T4&, const T5& )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the UNUSED_PARAMETER function for six parameters.
+// \ingroup util
+//
+// \return void
+*/
+template< typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 >
+inline void UNUSED_PARAMETER( const T1&, const T2&, const T3&, const T4&, const T5&, const T6& )
+{}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/Util.h b/src/cpu/blaze/util/Util.h
new file mode 100644
index 00000000..6c18b79e
--- /dev/null
+++ b/src/cpu/blaze/util/Util.h
@@ -0,0 +1,49 @@
+//=================================================================================================
+/*!
+// \file blaze/util/Util.h
+// \brief Utility module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_UTIL_H_
+#define _BLAZE_UTIL_UTIL_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup util Utility module */
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/ValueTraits.h b/src/cpu/blaze/util/ValueTraits.h
new file mode 100644
index 00000000..0bb5f496
--- /dev/null
+++ b/src/cpu/blaze/util/ValueTraits.h
@@ -0,0 +1,48 @@
+//=================================================================================================
+/*!
+// \file blaze/util/ValueTraits.h
+// \brief Header file for all value traits
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_VALUETRAITS_H_
+#define _BLAZE_UTIL_VALUETRAITS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/valuetraits/IsEven.h>
+#include <blaze/util/valuetraits/IsMultipleOf.h>
+#include <blaze/util/valuetraits/IsOdd.h>
+#include <blaze/util/valuetraits/IsPowerOf.h>
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Arithmetic.h b/src/cpu/blaze/util/constraints/Arithmetic.h
new file mode 100644
index 00000000..194d31e0
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Arithmetic.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Arithmetic.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_ARITHMETIC_H_
+#define _BLAZE_UTIL_CONSTRAINTS_ARITHMETIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsArithmetic.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_ARITHMETIC_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not an arithmetic data type, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_ARITHMETIC_TYPE(T) \
+ static_assert( ::blaze::IsArithmetic<T>::value, "Non-arithmetic type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_ARITHMETIC_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is an arithmetic data type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_ARITHMETIC_TYPE(T) \
+ static_assert( !::blaze::IsArithmetic<T>::value, "Arithmetic type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Array.h b/src/cpu/blaze/util/constraints/Array.h
new file mode 100644
index 00000000..d2173685
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Array.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Array.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_ARRAY_H_
+#define _BLAZE_UTIL_CONSTRAINTS_ARRAY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsArray.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_ARRAY_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is no array type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_ARRAY_TYPE(T) \
+ static_assert( ::blaze::IsArray<T>::value, "Non-array type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_ARRAY_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is an array type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_ARRAY_TYPE(T) \
+ static_assert( !::blaze::IsArray<T>::value, "Array type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Assignable.h b/src/cpu/blaze/util/constraints/Assignable.h
new file mode 100644
index 00000000..e2946aeb
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Assignable.h
@@ -0,0 +1,207 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Assignable.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_ASSIGNABLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_ASSIGNABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsAssignable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_COPY_ASSIGNABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a copy constructor, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COPY_ASSIGNABLE_TYPE(T) \
+ static_assert( ::blaze::IsCopyAssignable<T>::value, "Non-copy assignable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COPY_ASSIGNABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a copy constructor, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COPY_ASSIGNABLE_TYPE(T) \
+ static_assert( !::blaze::IsCopyAssignable<T>::value, "Copy assignable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_NOTHROW_COPY_ASSIGNABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a noexcept copy constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NOTHROW_COPY_ASSIGNABLE_TYPE(T) \
+ static_assert( ::blaze::IsNothrowCopyAssignable<T>::value, "Non-noexcept copy assignable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NOTHROW_COPY_ASSIGNABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a noexcept copy constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NOTHROW_COPY_ASSIGNABLE_TYPE(T) \
+ static_assert( !::blaze::IsNothrowCopyAssignable<T>::value, "Noexcept copy assignable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_MOVE_ASSIGNABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a move constructor, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MOVE_ASSIGNABLE_TYPE(T) \
+ static_assert( ::blaze::IsMoveAssignable<T>::value, "Non-move assignable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MOVE_ASSIGNABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a move constructor, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MOVE_ASSIGNABLE_TYPE(T) \
+ static_assert( !::blaze::IsMoveAssignable<T>::value, "Move assignable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_NOTHROW_MOVE_ASSIGNABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a noexcept move constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NOTHROW_MOVE_ASSIGNABLE_TYPE(T) \
+ static_assert( ::blaze::IsNothrowMoveAssignable<T>::value, "Non-noexcept move assignable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NOTHROW_MOVE_ASSIGNABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a noexcept move constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NOTHROW_MOVE_ASSIGNABLE_TYPE(T) \
+ static_assert( !::blaze::IsNothrowMoveAssignable<T>::value, "Noexcept move assignable type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/BaseOf.h b/src/cpu/blaze/util/constraints/BaseOf.h
new file mode 100644
index 00000000..07178375
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/BaseOf.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/BaseOf.h
+// \brief Constraint on the inheritance relationship of a data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_BASEOF_H_
+#define _BLAZE_UTIL_CONSTRAINTS_BASEOF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_BASE_OF CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the inheritance relationship.
+// \ingroup constraints
+//
+// In case \a B is not a base class of \a D, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_BASE_OF(B,D) \
+ static_assert( ::blaze::IsBaseOf<B,D>::value, "Broken inheritance relationship detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_BASE_OF CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the inheritance relationship.
+// \ingroup constraints
+//
+// In case \a B is a base class of \a D or in case \a B is the same type as \a D, a
+// compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_BASE_OF(B,D) \
+ static_assert( !::blaze::IsBaseOf<B,D>::value, "Unexpected inheritance relationship detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_STRICTLY_BASE_OF CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the inheritance relationship.
+// \ingroup constraints
+//
+// In case \a B is not a base class of \a D, a compilation error is created. In contrast to
+// the BLAZE_CONSTRAINT_MUST_BE_BASE_OF constraint, a compilation error is also created in case
+// \a B and \a D are the same type.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_STRICTLY_BASE_OF(B,D) \
+ static_assert( ::blaze::IsBaseOf<B,D>::value && !::blaze::IsBaseOf<D,B>::value , "Broken inheritance relationship detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_STRICTLY_BASE_OF CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the inheritance relationship.
+// \ingroup constraints
+//
+// In case \a B is a base class of \a D, a compilation error is created. In contrast to the
+// BLAZE_CONSTRAINT_MUST_NOT_BE_BASE_OF constraint, no compilation error is created in case \a B
+// and \a D are the same type.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_BASE_OF(B,D) \
+ static_assert( !::blaze::IsBaseOf<B,D>::value || ::blaze::IsBaseOf<D,B>::value , "Unexpected inheritance relationship detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Boolean.h b/src/cpu/blaze/util/constraints/Boolean.h
new file mode 100644
index 00000000..1189d8c7
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Boolean.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Boolean.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_BOOLEAN_H_
+#define _BLAZE_UTIL_CONSTRAINTS_BOOLEAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsBoolean.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_BOOLEAN_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a boolean, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_BOOLEAN_TYPE(T) \
+ static_assert( ::blaze::IsBoolean<T>::value, "Non-boolean type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_BOOLEAN_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is a boolean, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_BOOLEAN_TYPE(T) \
+ static_assert( !::blaze::IsBoolean<T>::value, "Boolean type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Builtin.h b/src/cpu/blaze/util/constraints/Builtin.h
new file mode 100644
index 00000000..2bf678c3
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Builtin.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Builtin.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_BUILTIN_H_
+#define _BLAZE_UTIL_CONSTRAINTS_BUILTIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsBuiltin.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_BUILTIN_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a built-in data type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE(T) \
+ static_assert( ::blaze::IsBuiltin<T>::value, "Non-built-in type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_BUILTIN_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is a built-in data type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_BUILTIN_TYPE(T) \
+ static_assert( !::blaze::IsBuiltin<T>::value, "Built-in type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Class.h b/src/cpu/blaze/util/constraints/Class.h
new file mode 100644
index 00000000..32f6ba0f
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Class.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Class.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_CLASS_H_
+#define _BLAZE_UTIL_CONSTRAINTS_CLASS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsClass.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_CLASS_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a user-defined, non-built-in class type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_CLASS_TYPE(T) \
+ static_assert( ::blaze::IsClass<T>::value, "Non-class type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_CLASS_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is a user-defined, non-built-in class type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_CLASS_TYPE(T) \
+ static_assert( !::blaze::IsClass<T>::value, "Class type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Comparable.h b/src/cpu/blaze/util/constraints/Comparable.h
new file mode 100644
index 00000000..25535e17
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Comparable.h
@@ -0,0 +1,66 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Comparable.h
+// \brief Constraint on the pointer relationship
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_COMPARABLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_COMPARABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsConvertible.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// POINTER_MUST_BE_COMPARABLE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the pointer relationship.
+// \ingroup constraints
+//
+// In case \a P1 is not comparable with \a P2, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_POINTER_MUST_BE_COMPARABLE(P1,P2) \
+ static_assert( ::blaze::IsConvertible<P1,P2>::value || ::blaze::IsConvertible<P2,P1>::value, "Incomparable pointer types detected" );
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Complex.h b/src/cpu/blaze/util/constraints/Complex.h
new file mode 100644
index 00000000..61f84f15
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Complex.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Complex.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_COMPLEX_H_
+#define _BLAZE_UTIL_CONSTRAINTS_COMPLEX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsComplex.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_COMPLEX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is a complex data type
+// (i.e. an instantiation of \a complex, ignoring the cv-qualifiers). In case \a T is not a
+// complex data type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE(T) \
+ static_assert( ::blaze::IsComplex<T>::value, "Non-complex type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COMPLEX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is not a complex data type
+// (i.e. an instantiation of \a complex, ignoring the cv-qualifiers). In case \a T is a complex
+// data type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPLEX_TYPE(T) \
+ static_assert( !::blaze::IsComplex<T>::value, "Complex type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/ComplexDouble.h b/src/cpu/blaze/util/constraints/ComplexDouble.h
new file mode 100644
index 00000000..62e99019
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/ComplexDouble.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/ComplexDouble.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_COMPLEXDOUBLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_COMPLEXDOUBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsComplexDouble.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_COMPLEX_DOUBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is a double precision
+// complex data type (i.e. \a complex<double>, ignoring the cv-qualifiers). In case \a T is
+// not of type \a complex<double> a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_DOUBLE_TYPE(T) \
+ static_assert( ::blaze::IsComplexDouble<T>::value, "Non-double precision complex type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COMPLEX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is not a double precision
+// complex data type (i.e. \a complex<double>, ignoring the cv-qualifiers). In case \a T is of
+// type \a complex<double> a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPLEX_DOUBLE_TYPE(T) \
+ static_assert( !::blaze::IsComplexDouble<T>::value, "Double precision complex type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/ComplexFloat.h b/src/cpu/blaze/util/constraints/ComplexFloat.h
new file mode 100644
index 00000000..ebbbde8e
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/ComplexFloat.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/ComplexFloat.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_COMPLEXFLOAT_H_
+#define _BLAZE_UTIL_CONSTRAINTS_COMPLEXFLOAT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsComplexFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_COMPLEX_FLOAT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is a single precision
+// complex data type (i.e. \a complex<float>, ignoring the cv-qualifiers). In case \a T is
+// not of type \a complex<float> a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_FLOAT_TYPE(T) \
+ static_assert( ::blaze::IsComplexFloat<T>::value, "Non-single precision complex type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COMPLEX_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is not a single precision
+// complex data type (i.e. \a complex<float>, ignoring the cv-qualifiers). In case \a T is of
+// type \a complex<float> a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPLEX_FLOAT_TYPE(T) \
+ static_assert( !::blaze::IsComplexFloat<T>::value, "Single precision complex type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Const.h b/src/cpu/blaze/util/constraints/Const.h
new file mode 100644
index 00000000..c12e5990
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Const.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Const.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_CONST_H_
+#define _BLAZE_UTIL_CONSTRAINTS_CONST_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsConst.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_CONST CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not a const-qualified type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_CONST(T) \
+ static_assert( ::blaze::IsConst<T>::value, "Non-const-qualified type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_CONST CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is a const-qualified type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_CONST(T) \
+ static_assert( !::blaze::IsConst<T>::value, "Const-qualified type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Constraints.h b/src/cpu/blaze/util/constraints/Constraints.h
new file mode 100644
index 00000000..7c786b1c
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Constraints.h
@@ -0,0 +1,115 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Constraints.h
+// \brief Header file for compile time constraints
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_CONSTRAINTS_H_
+#define _BLAZE_UTIL_CONSTRAINTS_CONSTRAINTS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup constraints Compile time constraints
+// \ingroup util
+//
+// Compile time constraints offer the possibility to stop the compilation process if a constraint
+// that can be checked at compile time is not met. These constraints are especially useful for
+// generic code, where the type of the involved objects is not known beforehands.\n
+// Since C++11 the C++ standard provides the \c static_assert functionality to check compile time
+// constant expressions:
+
+ \code
+ template <class T>
+ class RotationMatrix
+ {
+ // ...
+ static_assert( std::is_floating_point<T>::value, "Non-floating point type detected" );
+ // ...
+ };
+ \endcode
+
+// The Blaze library extends this functionality in the form of compile time constraint macros:
+
+ \code
+ template <class T>
+ class RotationMatrix
+ {
+ // ...
+ BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T );
+ // ...
+ };
+ \endcode
+
+// The compile time constraints provided by the Blaze library built on \c static_assert, but offer
+// the additional advantages ...
+//
+// - ... of a more convenient and easier usage since details are abstracted;
+// - ... of a more obvious and more explicit way to express compile time constraints;
+// - ... of encapsulation of complex compile time conditions.
+//
+// The following example demonstrates the \c BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM time constraint
+// and shows a possible error message:
+
+ \code
+ //----- Test.cpp -----
+ #include <blaze/Util.h>
+
+ class A {};
+ class B : public A {};
+ class C {};
+
+ int main()
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( B, A ); // No compile time error, B is derived from A
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( C, A ); // Compile time error, C is not derived from A
+ }
+ \endcode
+
+// The resulting error message generated by the GNU g++ compiler contains the name of the
+// constraint, a descriptive error message and the source code line of the constraint violation:
+
+ \code
+ ~/blaze/blaze/util/constraints/DerivedFrom.h:61:4: static assertion failed: Broken inheritance hierarchy detected
+ static_assert( ::blaze::IsBaseOf<B,D>::value, "Broken inheritance hierarchy detected" )
+ ^
+ Test.cpp:11:4: note: in expansion of macro 'BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM'
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( C, A ); // Compile time error, C is not derived from A
+ \endcode
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Constructible.h b/src/cpu/blaze/util/constraints/Constructible.h
new file mode 100644
index 00000000..a7f2cd50
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Constructible.h
@@ -0,0 +1,287 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Constructible.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_CONSTRUCTIBLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_CONSTRUCTIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsConstructible.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_DEFAULT_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a default constructor, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_DEFAULT_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsDefaultConstructible<T>::value, "Non-default constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_DEFAULT_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a default constructor, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_DEFAULT_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( !::blaze::IsDefaultConstructible<T>::value, "Default constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_NOTHROW_DEFAULT_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a noexcept default constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NOTHROW_DEFAULT_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsNothrowDefaultConstructible<T>::value, "Non-noexcept default constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NOTHROW_DEFAULT_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a noexcept default constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NOTHROW_DEFAULT_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( !::blaze::IsNothrowDefaultConstructible<T>::value, "Noexcept default constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_COPY_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a copy constructor, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_COPY_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsCopyConstructible<T>::value, "Non-copy constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_COPY_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a copy constructor, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_COPY_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( !::blaze::IsCopyConstructible<T>::value, "Copy constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_NOTHROW_COPY_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a noexcept copy constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NOTHROW_COPY_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsNothrowCopyConstructible<T>::value, "Non-noexcept copy constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NOTHROW_COPY_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a noexcept copy constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NOTHROW_COPY_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( !::blaze::IsNothrowCopyConstructible<T>::value, "Noexcept copy constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_MOVE_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a move constructor, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_MOVE_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsMoveConstructible<T>::value, "Non-move constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_MOVE_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a move constructor, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_MOVE_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( !::blaze::IsMoveConstructible<T>::value, "Move constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_NOTHROW_MOVE_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does not provide a noexcept move constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NOTHROW_MOVE_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsNothrowMoveConstructible<T>::value, "Non-noexcept move constructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NOTHROW_MOVE_CONSTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T does provide a noexcept move constructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NOTHROW_MOVE_CONSTRUCTIBLE_TYPE(T) \
+ static_assert( !::blaze::IsNothrowMoveConstructible<T>::value, "Noexcept move constructible type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Convertible.h b/src/cpu/blaze/util/constraints/Convertible.h
new file mode 100644
index 00000000..9105743f
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Convertible.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Convertible.h
+// \brief Constraint on the pointer relationship
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_CONVERTIBLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_CONVERTIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsConvertible.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_CONVERTIBLE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the pointer relationship.
+// \ingroup constraints
+//
+// In case \a FROM is not convertible to \a TO, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_CONVERTIBLE(FROM,TO) \
+ static_assert( ::blaze::IsConvertible<FROM,TO>::value, "Inconvertible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_CONVERTIBLE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the pointer relationship.
+// \ingroup constraints
+//
+// In case \a FROM is convertible to \a TO, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_CONVERTIBLE(FROM,TO) \
+ static_assert( !::blaze::IsConvertible<FROM,TO>::value, "Convertible type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/DerivedFrom.h b/src/cpu/blaze/util/constraints/DerivedFrom.h
new file mode 100644
index 00000000..77092ae3
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/DerivedFrom.h
@@ -0,0 +1,128 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/DerivedFrom.h
+// \brief Constraint on the inheritance relationship of a data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_DERIVEDFROM_H_
+#define _BLAZE_UTIL_CONSTRAINTS_DERIVEDFROM_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsBaseOf.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_DERIVED_FROM CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the inheritance relationship of a data type.
+// \ingroup constraints
+//
+// In case \a D is not derived from \a B, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM(D,B) \
+ static_assert( ( ::blaze::IsBaseOf<B,D>::value ), "Broken inheritance relationship detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_DERIVED_FROM CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the inheritance relationship of a data type.
+// \ingroup constraints
+//
+// In case \a D is derived from \a B or in case \a D is the same type as \a B, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_DERIVED_FROM(D,B) \
+ static_assert( ( !::blaze::IsBaseOf<B,D>::value ), "Unexpected inheritance relationship detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_STRICTLY_DERIVED_FROM CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the inheritance relationship of a data type.
+// \ingroup constraints
+//
+// In case \a D is not derived from \a B, a compilation error is created. In contrast to the
+// BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM constraint, a compilation error is also created in
+// case \a D and \a B are the same type.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_STRICTLY_DERIVED_FROM(D,B) \
+ static_assert( ( ::blaze::IsBaseOf<B,D>::value && !::blaze::IsBaseOf<D,B>::value ), "Broken inheritance relationship detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_STRICTLY_DERIVED_FROM CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the inheritance relationship of a data type.
+// \ingroup constraints
+//
+// In case \a D is derived from \a B, a compilation error is created. In contrast to the
+// BLAZE_CONSTRAINT_MUST_NOT_BE_DERIVED_FROM constraint, no compilation error is created
+// in case \a D and \a B are the same type.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_DERIVED_FROM(D,B) \
+ static_assert( ( !::blaze::IsBaseOf<B,D>::value || ::blaze::IsBaseOf<D,B>::value ), "Unexpected inheritance relationship detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Destructible.h b/src/cpu/blaze/util/constraints/Destructible.h
new file mode 100644
index 00000000..aa8ed1a2
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Destructible.h
@@ -0,0 +1,127 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Destructible.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_DESTRUCTIBLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_DESTRUCTIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsDestructible.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_DESTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T cannot be destroyed via its destructor, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_DESTRUCTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsDestructible<T>::value, "Non-destructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_DESTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T can be destroyed via its destructor, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_DESTRUCTIBLE_TYPE(T) \
+ static_assert( !::blaze::IsDestructible<T>::value, "Destructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_NOTHROW_DESTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T cannot be destroyed via a noexcept destructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NOTHROW_DESTRUCTIBLE_TYPE(T) \
+ static_assert( ::blaze::IsNothrowDestructible<T>::value, "Non-noexcept destructible type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NOTHROW_DESTRUCTIBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T can be destroyed via a noexcept destructor, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NOTHROW_DESTRUCTIBLE_TYPE(T) \
+ static_assert( !::blaze::IsNothrowDestructible<T>::value, "Noexcept destructible type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Double.h b/src/cpu/blaze/util/constraints/Double.h
new file mode 100644
index 00000000..8a3fbfc6
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Double.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Double.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_DOUBLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_DOUBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsDouble.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_DOUBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is of type double
+// (ignoring the cv-qualifiers). In case \a T is not of type double, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE(T) \
+ static_assert( ::blaze::IsDouble<T>::value, "Non-double type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_DOUBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is not of type double
+// (ignoring the cv-qualifiers). In case \a T is of type double, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_DOUBLE_TYPE(T) \
+ static_assert( !::blaze::IsDouble<T>::value, "Double type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Empty.h b/src/cpu/blaze/util/constraints/Empty.h
new file mode 100644
index 00000000..53596018
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Empty.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Empty.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_EMPTY_H_
+#define _BLAZE_UTIL_CONSTRAINTS_EMPTY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsEmpty.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_EMPTY CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not an empty type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_EMPTY(T) \
+ static_assert( ::blaze::IsEmpty<T>::value, "Non-empty type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_EMPTY CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is an empty type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_EMPTY(T) \
+ static_assert( !::blaze::IsEmpty<T>::value, "Empty type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Float.h b/src/cpu/blaze/util/constraints/Float.h
new file mode 100644
index 00000000..0ad971ca
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Float.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Float.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_FLOAT_H_
+#define _BLAZE_UTIL_CONSTRAINTS_FLOAT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsFloat.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_FLOAT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is of type float
+// (ignoring the cv-qualifiers). In case \a T is not of type float, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE(T) \
+ static_assert( ::blaze::IsFloat<T>::value, "Non-float type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_FLOAT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is not of type float
+// (ignoring the cv-qualifiers). In case \a T is of type float, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_FLOAT_TYPE(T) \
+ static_assert( !::blaze::IsFloat<T>::value, "Float type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/FloatingPoint.h b/src/cpu/blaze/util/constraints/FloatingPoint.h
new file mode 100644
index 00000000..34c27cf6
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/FloatingPoint.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/FloatingPoint.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_FLOATINGPOINT_H_
+#define _BLAZE_UTIL_CONSTRAINTS_FLOATINGPOINT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsFloatingPoint.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_FLOATING_POINT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a floating point data type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE(T) \
+ static_assert( ::blaze::IsFloatingPoint<T>::value, "Non-floating point type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_FLOATING_POINT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is a floating point data type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE(T) \
+ static_assert( !::blaze::IsFloatingPoint<T>::value, "Floating point type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Integer.h b/src/cpu/blaze/util/constraints/Integer.h
new file mode 100644
index 00000000..9ddb9c67
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Integer.h
@@ -0,0 +1,88 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Integer.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_INTEGER_H_
+#define _BLAZE_UTIL_CONSTRAINTS_INTEGER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsInteger.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_INTEGER_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is of type \c int (ignoring
+// the cv-qualifiers). In case \a T is not of type \c int, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_INTEGER_TYPE(T) \
+ static_assert( ::blaze::IsInteger<T>::value, "Non-integer type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_INTEGER_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is not of type \c int
+// (ignoring the cv-qualifiers). In case \a T is of type \c int, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_INTEGER_TYPE(T) \
+ static_assert( !::blaze::IsInteger<T>::value, "Integer type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Integral.h b/src/cpu/blaze/util/constraints/Integral.h
new file mode 100644
index 00000000..99c4a16e
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Integral.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Integral.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_INTEGRAL_H_
+#define _BLAZE_UTIL_CONSTRAINTS_INTEGRAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsIntegral.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_INTEGRAL_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not an integral data type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_INTEGRAL_TYPE(T) \
+ static_assert( ::blaze::IsIntegral<T>::value, "Non-integral type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_INTEGRAL_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is an integral data type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_INTEGRAL_TYPE(T) \
+ static_assert( !::blaze::IsIntegral<T>::value, "Integral type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/LongDouble.h b/src/cpu/blaze/util/constraints/LongDouble.h
new file mode 100644
index 00000000..070f037c
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/LongDouble.h
@@ -0,0 +1,89 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/LongDouble.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_LONGDOUBLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_LONGDOUBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsLongDouble.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_LONGDOUBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is of type long double
+// (ignoring the cv-qualifiers). In case \a T is not of type long double, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_LONGDOUBLE_TYPE(T) \
+ static_assert( ::blaze::IsLongDouble<T>::value, "Non-long double type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_LONGDOUBLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// This compile time constraint checks that the given data type \a T is not of type long double
+// (ignoring the cv-qualifiers). In case \a T is of type long double, a compilation error is
+// created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_LONGDOUBLE_TYPE(T) \
+ static_assert( !::blaze::IsLongDouble<T>::value, "Long double type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Numeric.h b/src/cpu/blaze/util/constraints/Numeric.h
new file mode 100644
index 00000000..b3068118
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Numeric.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Numeric.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_NUMERIC_H_
+#define _BLAZE_UTIL_CONSTRAINTS_NUMERIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_NUMERIC_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a numeric (integral or floating point) data type,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE(T) \
+ static_assert( ::blaze::IsNumeric<T>::value, "Non-numeric type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_NUMERIC_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is a numeric (integral or floating point) data type,
+// a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_NUMERIC_TYPE(T) \
+ static_assert( !::blaze::IsNumeric<T>::value, "Numeric type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Object.h b/src/cpu/blaze/util/constraints/Object.h
new file mode 100644
index 00000000..2199d727
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Object.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Object.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_OBJECT_H_
+#define _BLAZE_UTIL_CONSTRAINTS_OBJECT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsObject.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_OBJECT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not an object type (i.e., everything except references,
+// \a void, and function types), a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_OBJECT_TYPE(T) \
+ static_assert( ::blaze::IsObject<T>::value, "Non-object type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_OBJECT_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a object type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_OBJECT_TYPE(T) \
+ static_assert( !::blaze::IsObject<T>::value, "Object type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Pod.h b/src/cpu/blaze/util/constraints/Pod.h
new file mode 100644
index 00000000..71ad12d0
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Pod.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Pod.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_POD_H_
+#define _BLAZE_UTIL_CONSTRAINTS_POD_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsPod.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_POD CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not a POD type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_POD(T) \
+ static_assert( ::blaze::IsPod<T>::value, "Non-POD type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_POD CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is a POD type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_POD(T) \
+ static_assert( !::blaze::IsPod<T>::value, "POD type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Pointer.h b/src/cpu/blaze/util/constraints/Pointer.h
new file mode 100644
index 00000000..eb8815f4
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Pointer.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Pointer.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_POINTER_H_
+#define _BLAZE_UTIL_CONSTRAINTS_POINTER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsPointer.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_POINTER_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a pointer type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_POINTER_TYPE(T) \
+ static_assert( ::blaze::IsPointer<T>::value, "Non-pointer type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_POINTER_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a pointer type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE(T) \
+ static_assert( !::blaze::IsPointer<T>::value, "Pointer type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Rank.h b/src/cpu/blaze/util/constraints/Rank.h
new file mode 100644
index 00000000..6b397cc8
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Rank.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Rank.h
+// \brief Constraint on the rank of a data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_RANK_H_
+#define _BLAZE_UTIL_CONSTRAINTS_RANK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/Rank.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_HAVE_RANK CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the rank of a data type.
+// \ingroup constraints
+//
+// In case the type \a T doesn't have a rank of \a N, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_RANK(T,N) \
+ static_assert( ::blaze::Rank<T>::value == N, "Invalid rank detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_RANK CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the rank of a data type.
+// \ingroup constraints
+//
+// In case the type \a T has a rank of \a N, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_RANK(T,N) \
+ static_assert( ::blaze::Rank<T>::value != N, "Invalid rank detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Reference.h b/src/cpu/blaze/util/constraints/Reference.h
new file mode 100644
index 00000000..b23c2afa
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Reference.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Reference.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_REFERENCE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_REFERENCE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsReference.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_REFERENCE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a reference type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T) \
+ static_assert( ::blaze::IsReference<T>::value, "Non-reference type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_REFERENCE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a reference type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE(T) \
+ static_assert( !::blaze::IsReference<T>::value, "Reference type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/SameSize.h b/src/cpu/blaze/util/constraints/SameSize.h
new file mode 100644
index 00000000..64770c64
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/SameSize.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/SameSize.h
+// \brief Constraint on the size of two data types
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_SAMESIZE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_SAMESIZE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/HaveSameSize.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_HAVE_SAME_SIZE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of two data types.
+// \ingroup constraints
+//
+// In case the types \a T1 and \a T2 don't have the same size, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_SAME_SIZE(T1,T2) \
+ static_assert( ::blaze::HaveSameSize<T1,T2>::value, "Non-matching sizes detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_SAME_SIZE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of two data types.
+// \ingroup constraints
+//
+// In case the types \a T1 and \a T2 have the same size, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_SAME_SIZE(T1,T2) \
+ static_assert( !::blaze::HaveSameSize<T1,T2>::value, "Matching sizes detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/SameType.h b/src/cpu/blaze/util/constraints/SameType.h
new file mode 100644
index 00000000..9a51a277
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/SameType.h
@@ -0,0 +1,166 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/SameType.h
+// \brief Data type constraint
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_SAMETYPE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_SAMETYPE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsSame.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SAME_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Data type constraint.
+// \ingroup constraints
+//
+// In case the two types \a A and \a B are not the same (ignoring all cv-qualifiers of both data
+// types), a compilation error is created. The following example illustrates the behavior of this
+// constraint:
+
+ \code
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( double, double ); // No compilation error
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( double, const double ); // No compilation error (only cv-qualifiers differ)
+ BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( double, float ); // Compilation error, different data types!
+ \endcode
+
+// In case the cv-qualifiers should not be ignored (e.g. 'double' and 'const double' should be
+// considered to be unequal), use the blaze::BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE constraint.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE(A,B) \
+ static_assert( ::blaze::IsSame<A,B>::value, "Non-matching types detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SAME_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Data type constraint.
+// \ingroup constraints
+//
+// In case the two types \a A and \a B are the same (ignoring all cv-qualifiers of both data
+// types), a compilation error is created. The following example illustrates the behavior of
+// this constraint:
+
+ \code
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SAME_TYPE( double, float ); // No compilation error, different data types
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SAME_TYPE( double, const double ); // Compilation error (only cv-qualifiers differ)
+ BLAZE_CONSTRAINT_MUST_NOT_BE_SAME_TYPE( double, double ); // Compilation error, same data type!
+ \endcode
+
+// In case the cv-qualifiers should not be ignored (e.g. 'double' and 'const double' should
+// be considered to be unequal), use the blaze::BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_SAME_TYPE
+// constraint.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SAME_TYPE(A,B) \
+ static_assert( !::blaze::IsSame<A,B>::value, "Matching types detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_STRICTLY_SAME_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Data type constraint.
+// \ingroup constraints
+//
+// In case the two types \a A and \a B are not the same, a compilation error is created. Note
+// that this constraint even considers two types as unequal if the cv-qualifiers differ, e.g.
+
+ \code
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( double, double ); // No compilation error
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( double, const double ); // Compilation error, different cv-qualifiers!
+ BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE( double, float ); // Compilation error, different data types!
+ \endcode
+
+// In case the cv-qualifiers should be ignored (e.g. 'double' and 'const double' should be
+// considered to be equal), use the blaze::BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE constraint.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_STRICTLY_SAME_TYPE(A,B) \
+ static_assert( ::blaze::IsStrictlySame<A,B>::value, "Non-matching types detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_STRICTLY_SAME_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Data type constraint.
+// \ingroup constraints
+//
+// In case the two types \a A and \a B are the same, a compilation error is created. Note that
+// this constraint even considers two types as unequal if the cv-qualifiers differ, e.g.
+
+ \code
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_SAME_TYPE( double, float ); // No compilation error, different data types
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_SAME_TYPE( double, const double ); // No compilation error, different cv-qualifiers!
+ BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_SAME_TYPE( double, double ); // Compilation error, same data type!
+ \endcode
+
+// In case the cv-qualifiers should be ignored (e.g. 'double' and 'const double' should be
+// considered to be equal), use the blaze::BLAZE_CONSTRAINT_MUST_NOT_BE_SAME_TYPE constraint.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_SAME_TYPE(A,B) \
+ static_assert( !::blaze::IsStrictlySame<A,B>::value, "Matching types detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Signed.h b/src/cpu/blaze/util/constraints/Signed.h
new file mode 100644
index 00000000..06613782
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Signed.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Signed.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_SIGNED_H_
+#define _BLAZE_UTIL_CONSTRAINTS_SIGNED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsSigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SIGNED_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not an signed integral data type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SIGNED_TYPE(T) \
+ static_assert( ::blaze::IsSigned<T>::value, "Non-signed type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_SIGNED_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is an signed integral data type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_SIGNED_TYPE(T) \
+ static_assert( !::blaze::IsSigned<T>::value, "Signed type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Size.h b/src/cpu/blaze/util/constraints/Size.h
new file mode 100644
index 00000000..7e83c132
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Size.h
@@ -0,0 +1,238 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Size.h
+// \brief Constraint on the size of a data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_SIZE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_SIZE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/HasSize.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_HAVE_SIZE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T doesn't have a size of \a S bytes, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_SIZE(T,S) \
+ static_assert( ::blaze::HasSize<T,S>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_SIZE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T has a size of \a S bytes, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_SIZE(T,S) \
+ static_assert( !::blaze::HasSize<T,S>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_HAVE_1_BYTE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T doesn't have a size of exactly 1 byte, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_1_BYTE(T) \
+ static_assert( ::blaze::Has1Byte<T>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_1_BYTE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T has a size of exactly 1 byte, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_1_BYTE(T) \
+ static_assert( !::blaze::Has1Byte<T>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_HAVE_2_BYTES CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T doesn't have a size of exactly 2 bytes, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_2_BYTES(T) \
+ static_assert( ::blaze::Has2Byte<T>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_2_BYTES CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T has a size of exactly 2 bytes, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_2_BYTES(T) \
+ static_assert( !::blaze::Has2Byte<T>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_HAVE_4_BYTES CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T doesn't have a size of exactly 4 bytes, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_4_BYTES(T) \
+ static_assert( ::blaze::Has4Byte<T>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_4_BYTES CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T has a size of exactly 4 bytes, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_4_BYTES(T) \
+ static_assert( !::blaze::Has4Byte<T>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_HAVE_8_BYTES CONSTRAINT
+//
+//=================================================================================================
+
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T doesn't have a size of exactly 8 bytes, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_HAVE_8_BYTES(T) \
+ static_assert( ::blaze::Has8Byte<T>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_HAVE_8_BYTES CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the size of a data type.
+// \ingroup constraints
+//
+// In case the type \a T has a size of exactly 8 bytes, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_HAVE_8_BYTES(T) \
+ static_assert( !::blaze::Has8Byte<T>::value, "Invalid size detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Subscriptable.h b/src/cpu/blaze/util/constraints/Subscriptable.h
new file mode 100644
index 00000000..c2e1e732
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Subscriptable.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Subscriptable.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_SUBSCRIPTABLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_SUBSCRIPTABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <utility>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_SUBSCRIBTABLE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not subscriptable, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SUBSCRIPTABLE(T) \
+ static_assert( sizeof( std::declval<T>()[0] ) > 0UL, "Non-subscriptable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_BE_SUBSCRIBTABLE_AS_DECAYABLE_POINTER CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not a subscriptable pointer, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_SUBSCRIPTABLE_AS_DECAYABLE_POINTER(T) \
+ static_assert( sizeof( 0[std::declval<T>()] ) > 0UL, "Non-subscriptable pointer detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/TypeRestriction.h b/src/cpu/blaze/util/constraints/TypeRestriction.h
new file mode 100644
index 00000000..61b52a6d
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/TypeRestriction.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/TypeRestriction.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_TYPERESTRICTION_H_
+#define _BLAZE_UTIL_CONSTRAINTS_TYPERESTRICTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/TypeList.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// SOFT_TYPE_RESTRICTION CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given type list \a TYPELIST does not contain a type related to \a T, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_SOFT_TYPE_RESTRICTION(T,TYPELIST) \
+ static_assert( ::blaze::ContainsRelated<TYPELIST,T>::value, "Unapproved type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TYPE_RESTRICTION CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given type list \a TYPELIST does not contain the data type \a T, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_TYPE_RESTRICTION(T,TYPELIST) \
+ static_assert( ::blaze::Contains<TYPELIST,T>::value, "Unapproved type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Union.h b/src/cpu/blaze/util/constraints/Union.h
new file mode 100644
index 00000000..c360b176
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Union.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Union.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_UNION_H_
+#define _BLAZE_UTIL_CONSTRAINTS_UNION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsUnion.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_UNION CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not a union type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_UNION(T) \
+ static_assert( ::blaze::IsUnion<T>::value, "Non-union type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_UNION CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is a union type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_UNION(T) \
+ static_assert( !::blaze::IsUnion<T>::value, "Union type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Unsigned.h b/src/cpu/blaze/util/constraints/Unsigned.h
new file mode 100644
index 00000000..0c1b3824
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Unsigned.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Unsigned.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_UNSIGNED_H_
+#define _BLAZE_UTIL_CONSTRAINTS_UNSIGNED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsUnsigned.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_UNSIGNED_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not an unsigned integral data type, a compilation
+// error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_UNSIGNED_TYPE(T) \
+ static_assert( ::blaze::IsUnsigned<T>::value, "Non-unsigned type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_UNSIGNED_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is an unsigned integral data type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_UNSIGNED_TYPE(T) \
+ static_assert( !::blaze::IsUnsigned<T>::value, "Unsigned type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Valid.h b/src/cpu/blaze/util/constraints/Valid.h
new file mode 100644
index 00000000..2832c433
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Valid.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Valid.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_VALID_H_
+#define _BLAZE_UTIL_CONSTRAINTS_VALID_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsValid.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VALID CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not a valid type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VALID_TYPE(T) \
+ static_assert( blaze::IsValid<T>::value, "Invalid type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VALID CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is a valid type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VALID_TYPE(T) \
+ static_assert( !blaze::IsValid<T>::value, "Valid type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Vectorizable.h b/src/cpu/blaze/util/constraints/Vectorizable.h
new file mode 100644
index 00000000..5666df70
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Vectorizable.h
@@ -0,0 +1,87 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Vectorizable.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_VECTORIZABLE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_VECTORIZABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsVectorizable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VECTORIZABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is not a vectorizable data type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE(T) \
+ static_assert( blaze::IsVectorizable<T>::value, "Non-vectorizable type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VECTORIZABLE_TYPE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type \a T is a vectorizable data type, a compilation error
+// is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VECTORIZABLE_TYPE(T) \
+ static_assert( !blaze::IsVectorizable<T>::value, "Vectorizable type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Void.h b/src/cpu/blaze/util/constraints/Void.h
new file mode 100644
index 00000000..50e126b5
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Void.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Void.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_VOID_H_
+#define _BLAZE_UTIL_CONSTRAINTS_VOID_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsVoid.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VOID CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not \a void, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VOID(T) \
+ static_assert( ::blaze::IsVoid<T>::value, "Non-void type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VOID CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is \a void, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VOID(T) \
+ static_assert( !::blaze::IsVoid<T>::value, "Void type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/constraints/Volatile.h b/src/cpu/blaze/util/constraints/Volatile.h
new file mode 100644
index 00000000..fb74634f
--- /dev/null
+++ b/src/cpu/blaze/util/constraints/Volatile.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/constraints/Volatile.h
+// \brief Constraint on the data type
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_CONSTRAINTS_VOLATILE_H_
+#define _BLAZE_UTIL_CONSTRAINTS_VOLATILE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/typetraits/IsVolatile.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MUST_BE_VOLATILE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is not a volatile-qualified type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_BE_VOLATILE(T) \
+ static_assert( ::blaze::IsVolatile<T>::value, "Non-volatile-qualified type detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// MUST_NOT_BE_VOLATILE CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup constraints
+//
+// In case the given data type is a volatile-qualified type, a compilation error is created.
+*/
+#define BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE(T) \
+ static_assert( !::blaze::IsVolatile<T>::value, "Volatile-qualified type detected" )
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/DebugSection.h b/src/cpu/blaze/util/logging/DebugSection.h
new file mode 100644
index 00000000..ecfe6f7e
--- /dev/null
+++ b/src/cpu/blaze/util/logging/DebugSection.h
@@ -0,0 +1,105 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/DebugSection.h
+// \brief Header file for the log debug section
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_DEBUGSECTION_H_
+#define _BLAZE_UTIL_LOGGING_DEBUGSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/logging/LogSection.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// BLAZE_LOG_DEBUG_SECTION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logging section for debug information.
+// \ingroup logging
+//
+// This macro starts a log section for debug information. These messages are written to the
+// log file(s) in case the blaze::loglevel has been set to \a debug or higher. The following
+// example demonstrates how this log section is used:
+
+ \code
+ int main( int argc, char** argv )
+ {
+ // Initialization of the MPI system (for MPI parallel simulations)
+ // The MPI system must be initialized before any logging functionality may be used. In
+ // case it was not called before the first log section it is assumed that the simulation
+ // does not run in parallel. Thus in MPI-parallel simulations it is strongly recommended
+ // to make MPI_Init() the very first call of the main function.
+ MPI_Init( &argc, &argv );
+
+ // ...
+
+ // Log section for debug information
+ // This section is only executed in case the logging level is at least 'debug'. The
+ // macro parameter specifies the name of the log handle (in this example 'log') that
+ // can be used as a stream to log any kind of streamable information.
+ BLAZE_LOG_DEBUG_SECTION( log ) {
+ log << " Only printed within an active BLAZE_LOG_DEBUG_SECTION!\n";
+ }
+
+ // ...
+
+ // Finalizing the MPI system (for MPI parallel simulations)
+ // The MPI system must be finalized after the last pe functionality has been used. It
+ // is recommended to make MPI_Finalize() the very last call of the main function.
+ MPI_Finalize();
+ }
+ \endcode
+
+// Note that uncaught exceptions emitted from the blaze::BLAZE_LOG_DEBUG_SECTION might result
+// in lost and/or unlogged information!
+*/
+#define BLAZE_LOG_DEBUG_SECTION( NAME ) \
+ if( blaze::logging::loglevel >= blaze::logging::debug ) \
+ if( blaze::logging::LogSection NAME = blaze::logging::debug )
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/DetailSection.h b/src/cpu/blaze/util/logging/DetailSection.h
new file mode 100644
index 00000000..da857bc0
--- /dev/null
+++ b/src/cpu/blaze/util/logging/DetailSection.h
@@ -0,0 +1,105 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/DetailSection.h
+// \brief Header file for the log detail section
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_DETAILSECTION_H_
+#define _BLAZE_UTIL_LOGGING_DETAILSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/logging/LogSection.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// BLAZE_LOG_DETAIL_SECTION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logging section for debug information.
+// \ingroup logging
+//
+// This macro starts a log section for detail information. These messages are written to the
+// log file(s) in case the blaze::loglevel has been set to \a detail or higher. The following
+// example demonstrates how this log section is used:
+
+ \code
+ int main( int argc, char** argv )
+ {
+ // Initialization of the MPI system (for MPI parallel simulations)
+ // The MPI system must be initialized before any logging functionality may be used. In
+ // case it was not called before the first log section it is assumed that the simulation
+ // does not run in parallel. Thus in MPI-parallel simulations it is strongly recommended
+ // to make MPI_Init() the very first call of the main function.
+ MPI_Init( &argc, &argv );
+
+ // ...
+
+ // Log section for detail information
+ // This section is only executed in case the logging level is at least 'detail'. The
+ // macro parameter specifies the name of the log handle (in this example 'log') that
+ // can be used as a stream to log any kind of streamable information.
+ BLAZE_LOG_DETAIL_SECTION( log ) {
+ log << " Only printed within an active BLAZE_LOG_DETAIL_SECTION!\n";
+ }
+
+ // ...
+
+ // Finalizing the MPI system (for MPI parallel simulations)
+ // The MPI system must be finalized after the last pe functionality has been used. It
+ // is recommended to make MPI_Finalize() the very last call of the main function.
+ MPI_Finalize();
+ }
+ \endcode
+
+// Note that uncaught exceptions emitted from the blaze::BLAZE_LOG_DETAIL_SECTION might result
+// in lost and/or unlogged information!
+*/
+#define BLAZE_LOG_DETAIL_SECTION( NAME ) \
+ if( blaze::logging::loglevel >= blaze::logging::detail ) \
+ if( blaze::logging::LogSection NAME = blaze::logging::detail )
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/ErrorSection.h b/src/cpu/blaze/util/logging/ErrorSection.h
new file mode 100644
index 00000000..1b4f6b34
--- /dev/null
+++ b/src/cpu/blaze/util/logging/ErrorSection.h
@@ -0,0 +1,105 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/ErrorSection.h
+// \brief Header file for the log error section
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_ERRORSECTION_H_
+#define _BLAZE_UTIL_LOGGING_ERRORSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/logging/LogSection.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// BLAZE_LOG_ERROR_SECTION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logging section for (severe) error messages.
+// \ingroup logging
+//
+// This macro starts a log section for (severe) error messages. These messages are written to
+// the log file(s) in case the blaze::loglevel has been set to \a error or higher. The following
+// example demonstrates how this log section is used:
+
+ \code
+ int main( int argc, char** argv )
+ {
+ // Initialization of the MPI system (for MPI parallel simulations)
+ // The MPI system must be initialized before any logging functionality may be used. In
+ // case it was not called before the first log section it is assumed that the simulation
+ // does not run in parallel. Thus in MPI-parallel simulations it is strongly recommended
+ // to make MPI_Init() the very first call of the main function.
+ MPI_Init( &argc, &argv );
+
+ // ...
+
+ // Log section for error messages
+ // This section is only executed in case the logging level is at least 'error'. The
+ // macro parameter specifies the name of the log handle (in this example 'log') that
+ // can be used as a stream to log any kind of streamable information.
+ BLAZE_LOG_ERROR_SECTION( log ) {
+ log << " Only printed within an active BLAZE_LOG_ERROR_SECTION!\n";
+ }
+
+ // ...
+
+ // Finalizing the MPI system (for MPI parallel simulations)
+ // The MPI system must be finalized after the last pe functionality has been used. It
+ // is recommended to make MPI_Finalize() the very last call of the main function.
+ MPI_Finalize();
+ }
+ \endcode
+
+// Note that uncaught exceptions emitted from the blaze::BLAZE_LOG_ERROR_SECTION might result
+// in lost and/or unlogged information!
+*/
+#define BLAZE_LOG_ERROR_SECTION( NAME ) \
+ if( blaze::logging::loglevel >= blaze::logging::error ) \
+ if( blaze::logging::LogSection NAME = blaze::logging::error )
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/FunctionTrace.h b/src/cpu/blaze/util/logging/FunctionTrace.h
new file mode 100644
index 00000000..647ce5cd
--- /dev/null
+++ b/src/cpu/blaze/util/logging/FunctionTrace.h
@@ -0,0 +1,165 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/FunctionTrace.h
+// \brief Header file for the FunctionTrace class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_FUNCTIONTRACE_H_
+#define _BLAZE_UTIL_LOGGING_FUNCTIONTRACE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <new>
+#include <string>
+#include <blaze/system/Logging.h>
+#include <blaze/system/Signature.h>
+#include <blaze/util/NonCopyable.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief RAII object for function tracing.
+// \ingroup logging
+//
+// The FunctionTrace class is an auxiliary helper class for the tracing of function calls. It
+// is implemented as a wrapper around the Logger class and is responsible for the atomicity of
+// the logging operations of trace information.
+*/
+class FunctionTrace : private NonCopyable
+{
+ public:
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ FunctionTrace( const std::string& file, const std::string& function );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ ~FunctionTrace();
+ //@}
+ //**********************************************************************************************
+
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ void* operator new ( std::size_t ) = delete;
+ void* operator new[]( std::size_t ) = delete;
+ void* operator new ( std::size_t, const std::nothrow_t& ) noexcept = delete;
+ void* operator new[]( std::size_t, const std::nothrow_t& ) noexcept = delete;
+
+ void operator delete ( void* ) noexcept = delete;
+ void operator delete[]( void* ) noexcept = delete;
+ void operator delete ( void*, const std::nothrow_t& ) noexcept = delete;
+ void operator delete[]( void*, const std::nothrow_t& ) noexcept = delete;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::string file_; //!< The file name the traced function is contained in.
+ std::string function_; //!< The name of the traced function.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// BLAZE_FUNCTION_TRACE MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Function trace macro.
+// \ingroup logging
+//
+// This macro can be used to reliably trace function calls. In case function tracing is
+// activated, the traces are logged via the Logger class. The following, short example
+// demonstrates how the function trace macro is used:
+
+ \code
+ int main( int argc, char** argv )
+ {
+ BLAZE_FUNCTION_TRACE;
+
+ // ...
+ }
+ \endcode
+
+// The macro should be used as the very first statement inside the function in order to
+// guarantee that logging the function trace is the very first and last action of the
+// function call.\n
+// Function tracing can be enabled or disabled via the BLAZE_USE_FUNCTION_TRACES macro.
+// If function tracing is activated, the resulting log will contain trace information of
+// the following form:
+
+ \code
+ [TRACE ][000:00:00] + Entering function 'int main()' in file 'TraceDemo.cpp'
+ [TRACE ][000:00:10] - Leaving function 'int main()' in file 'TraceDemo.cpp'
+ \endcode
+
+// In case function tracing is deactivated, all function trace functionality is completely
+// removed from the code, i.e. no function traces are logged and no overhead results from
+// the BLAZE_FUNCTION_TRACE macro.
+*/
+#if BLAZE_USE_FUNCTION_TRACES
+# define BLAZE_FUNCTION_TRACE \
+ blaze::logging::FunctionTrace BLAZE_FUNCTION_TRACE_OBJECT( __FILE__, BLAZE_SIGNATURE )
+#else
+# define BLAZE_FUNCTION_TRACE
+#endif
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/InfoSection.h b/src/cpu/blaze/util/logging/InfoSection.h
new file mode 100644
index 00000000..c1fafd6e
--- /dev/null
+++ b/src/cpu/blaze/util/logging/InfoSection.h
@@ -0,0 +1,105 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/InfoSection.h
+// \brief Header file for the log info section
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_INFOSECTION_H_
+#define _BLAZE_UTIL_LOGGING_INFOSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/logging/LogSection.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// BLAZE_LOG_INFO_SECTION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logging section for information messages.
+// \ingroup logging
+//
+// This macro starts a log section for information messages. These messages are written to the
+// log file(s) in case the blaze::loglevel has been set to \a info or higher. The following example
+// demonstrates how this log section is used:
+
+ \code
+ int main( int argc, char** argv )
+ {
+ // Initialization of the MPI system (for MPI parallel simulations)
+ // The MPI system must be initialized before any logging functionality may be used. In
+ // case it was not called before the first log section it is assumed that the simulation
+ // does not run in parallel. Thus in MPI-parallel simulations it is strongly recommended
+ // to make MPI_Init() the very first call of the main function.
+ MPI_Init( &argc, &argv );
+
+ // ...
+
+ // Log section for information messages
+ // This section is only executed in case the logging level is at least 'info'. The
+ // macro parameter specifies the name of the log handle (in this example 'log') that
+ // can be used as a stream to log any kind of streamable information.
+ BLAZE_LOG_INFO_SECTION( log ) {
+ log << " Only printed within an active BLAZE_LOG_INFO_SECTION!\n";
+ }
+
+ // ...
+
+ // Finalizing the MPI system (for MPI parallel simulations)
+ // The MPI system must be finalized after the last pe functionality has been used. It
+ // is recommended to make MPI_Finalize() the very last call of the main function.
+ MPI_Finalize();
+ }
+ \endcode
+
+// Note that uncaught exceptions emitted from the blaze::BLAZE_LOG_INFO_SECTION might result
+// in lost and/or unlogged information!
+*/
+#define BLAZE_LOG_INFO_SECTION( NAME ) \
+ if( blaze::logging::loglevel >= blaze::logging::info ) \
+ if( blaze::logging::LogSection NAME = blaze::logging::info )
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/LogLevel.h b/src/cpu/blaze/util/logging/LogLevel.h
new file mode 100644
index 00000000..6ad3213e
--- /dev/null
+++ b/src/cpu/blaze/util/logging/LogLevel.h
@@ -0,0 +1,91 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/LogLevel.h
+// \brief Header file for the logging levels
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_LOGLEVEL_H_
+#define _BLAZE_UTIL_LOGGING_LOGLEVEL_H_
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// LOGGING LEVELS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logging levels.
+// \ingroup logging
+//
+// The LogLevel type enumeration represents the type of the global logging level. It defines
+// all possible levels for the logging functionality. Depending on the setting of the global
+// logging level (see blaze::logLevel), more or less information will be written to the log
+// file(s). The following logging levels are available:
+//
+// - \a inactive: Completely deactivates the logging functionality, i.e., no log file(s) will
+// be written. Since this setting can immensely complicate error correction, it
+// is not recommended to use this setting!
+// - \a error : Only (severe) errors are written to the log file(s).
+// - \a warning : Extends the \a error setting by warning messages (default).
+// - \a info : Extends the \a warning setting by additional informative messages.
+// - \a progress: Extends the \a info setting by progress information.
+// - \a debug : Extends the \a progress setting by debug information.
+// - \a detail : Extends the \a debug setting by very fine grained detail information.
+//
+// \a inactive plays a special role in the way that it switches off the logging functionality
+// completely, i.e., no log file(s) will be created. The highest logging level is \a error,
+// which exclusively writes severe errors to the log file(s). The lowest logging level is
+// \a detail, which can create a tremendous amount of logging information. Note that each
+// logging level comprises all higher logging levels. For instance, \a progress will also
+// print all errors and warning to the log file(s).
+*/
+enum LogLevel
+{
+ inactive = 0, //!< Log level for no logging.
+ error = 1, //!< Log level for (sever) errors.
+ warning = 2, //!< Log level for warnings.
+ info = 3, //!< Log level for high-level information.
+ progress = 4, //!< Log level for progress information.
+ debug = 5, //!< Log level for debug information.
+ detail = 6 //!< Log level for detail information.
+};
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/LogSection.h b/src/cpu/blaze/util/logging/LogSection.h
new file mode 100644
index 00000000..a6afb51f
--- /dev/null
+++ b/src/cpu/blaze/util/logging/LogSection.h
@@ -0,0 +1,230 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/LogSection.h
+// \brief Header file for the LogSection class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_LOGSECTION_H_
+#define _BLAZE_UTIL_LOGGING_LOGSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <new>
+#include <sstream>
+#include <blaze/system/Logging.h>
+#include <blaze/util/logging/LogLevel.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logging section for (non-)MPI-parallel environments.
+// \ingroup logging
+//
+// The LogSection class is an auxiliary helper class for all logging section macros. It is
+// implemented as a wrapper around the Logger class and is responsible for the atomicity of
+// the logging operations and for formatting any message that is written into the log file(s).
+*/
+class LogSection
+{
+ public:
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ LogSection( LogLevel level );
+ inline LogSection( const LogSection& ls );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ ~LogSection();
+ //@}
+ //**********************************************************************************************
+
+ //**Conversion operators************************************************************************
+ /*!\name Conversion operators */
+ //@{
+ inline operator bool() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Logging functions***************************************************************************
+ /*!\name Logging functions */
+ //@{
+ template< typename Type > inline void log ( const Type& message );
+ void commit();
+ //@}
+ //**********************************************************************************************
+
+ //**Forbidden operations************************************************************************
+ /*!\name Forbidden operations */
+ //@{
+ LogSection& operator=( const LogSection& ) = delete;
+
+ void* operator new ( std::size_t ) = delete;
+ void* operator new[]( std::size_t ) = delete;
+ void* operator new ( std::size_t, const std::nothrow_t& ) noexcept = delete;
+ void* operator new[]( std::size_t, const std::nothrow_t& ) noexcept = delete;
+
+ void operator delete ( void* ) noexcept = delete;
+ void operator delete[]( void* ) noexcept = delete;
+ void operator delete ( void*, const std::nothrow_t& ) noexcept = delete;
+ void operator delete[]( void*, const std::nothrow_t& ) noexcept = delete;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ LogLevel level_; //!< The logging level of the log section.
+ std::stringstream message_; //!< Intermediate buffer for log messages.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief The copy constructor for LogSection.
+//
+// \param ls The log section to be copied.
+//
+// The copy constructor is explicitly defined in order to enable its use in the log sections
+// despite the non-copyable stringstream member variable.
+*/
+inline LogSection::LogSection( const LogSection& ls )
+ : level_( ls.level_ ) // The logging level of the log section
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONVERSION OPERATOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Conversion operator to \a bool.
+//
+// The conversion operator returns \a true to indicate that the logging section is active.
+*/
+inline LogSection::operator bool() const
+{
+ return true;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logs the given message to the log file.
+//
+// \param message The log message to be logged.
+// \return void
+*/
+template< typename Type > // Type of the log message
+inline void LogSection::log( const Type& message )
+{
+ message_ << message;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name LogSection operators */
+//@{
+template< typename Type >
+inline LogSection& operator<<( LogSection& logsection, const Type& message );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Global output operator for the LogSection class.
+// \ingroup logging
+//
+// \param logsection Reference to the log section.
+// \param message Reference to the log message.
+// \return Reference to the log section.
+*/
+template< typename Type > // Type of the log message
+inline LogSection& operator<<( LogSection& logsection, const Type& message )
+{
+ logsection.log( message );
+ return logsection;
+}
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/Logger.h b/src/cpu/blaze/util/logging/Logger.h
new file mode 100644
index 00000000..e1778dad
--- /dev/null
+++ b/src/cpu/blaze/util/logging/Logger.h
@@ -0,0 +1,161 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/Logger.h
+// \brief Header file for the Logger class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_LOGGER_H_
+#define _BLAZE_UTIL_LOGGING_LOGGER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <fstream>
+#include <mutex>
+#include <blaze/util/singleton/Singleton.h>
+#include <blaze/util/SystemClock.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of a logger class.
+// \ingroup logging
+//
+// The Logger class represents the core of the logging functionality. It is responsible for
+// commiting logging messages immediately to the according log file(s). The logger works for
+// both serial as well as MPI parallel environments. In case of a non-MPI-parallel simulation
+// the Logger creates the log file 'blaze.log', which contains all logging information from all
+// logging levels. In case of a MPI parallel simulation, each process creates his own individual
+// log file called 'blazeX.log', where 'X' is replaced by the according rank the process has in
+// the MPI_COMM_WORLD communicator.\n
+// Note that the log file(s) are only created in case any logging information is created. This
+// might for instance result in only a small number of log file(s) in MPI parallel simulations
+// when only some of the processes encounter errors/warnings/etc.\n
+// Note that the logging functionality may not be used before MPI_Init() has been finished. In
+// consequence, this means that no global data that is initialized before the main() function
+// may contain any use of the logging functionality!
+*/
+class Logger : private Singleton<Logger,SystemClock>
+{
+ private:
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ explicit Logger();
+ //@}
+ //**********************************************************************************************
+
+ public:
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ ~Logger();
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Logging functions***************************************************************************
+ /*!\name Logging functions */
+ //@{
+ template< typename Type > void log( const Type& message );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ void openLogFile();
+ //@}
+ //**********************************************************************************************
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::mutex mutex_; //!< Synchronization mutex for thread-parallel logging.
+ std::ofstream log_; //!< The log file.
+ //@}
+ //**********************************************************************************************
+
+ //**Friend declarations*************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ friend class FunctionTrace;
+ friend class LogSection;
+ BLAZE_BEFRIEND_SINGLETON;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// LOGGING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Writes the log message to the log file.
+//
+// \param message The log message to be logged.
+// \return void
+//
+// This function immediately commits the log message to the log file. The first call to this
+// function will create the log file.
+*/
+template< typename Type > // Type of the log message
+void Logger::log( const Type& message )
+{
+ std::lock_guard<std::mutex> lock( mutex_ );
+ if( !log_.is_open() )
+ openLogFile();
+ log_ << message;
+ log_.flush();
+}
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/Logging.h b/src/cpu/blaze/util/logging/Logging.h
new file mode 100644
index 00000000..2ce8ce0d
--- /dev/null
+++ b/src/cpu/blaze/util/logging/Logging.h
@@ -0,0 +1,224 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/Logging.h
+// \brief Logging module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_LOGGING_H_
+#define _BLAZE_UTIL_LOGGING_LOGGING_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+//! Namespace for the logging module.
+namespace logging {}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\defgroup logging Logging
+// \ingroup util
+//
+// The logging submodule offers the functionality for the creation of log information in both
+// non-parallel and MPI-/thread-parallel environments. The logging functionality is implemented
+// such that in case no logging is required no runtime and memory overhead occur. However, in
+// case it is necessary to log information, this is done as efficiently and reliably as possible.
+// In non-parallel environments, a single log file named 'blaze.log' is created, containing all
+// the information of the single process. In MPI-parallel environments, each process creates
+// his own log file named 'blazeX.log', where 'X' is replaced by his according process rank in
+// the MPI_COMM_WORLD communicator. Depending on the selected logging level information about
+// (severe) errors, warnings, important information, progress reports, debug information, and
+// detailed output is written to the log file(s). The global log level is specified via the
+// blaze::loglevel variable in the configuration file "blaze/config/Logging.h". The following
+// logging level's are available:
+//
+// - \a inactive: Completely deactivates the logging functionality, i.e., no log file(s) will
+// be written. Since this setting can immensely complicate error correction, it
+// is not recommended to use this setting!
+// - \a error : Only (severe) errors are written to the log file(s).
+// - \a warning : Extends the \a error setting by warning messages.
+// - \a info : Extends the \a warning setting by additional informative messages (default).
+// - \a progress: Extends the \a info setting by progress information.
+// - \a debug : Extends the \a progress setting by debug information.
+// - \a detail : Extends the \a debug setting by very fine grained detail information.
+//
+// Logging is done via one of the six following log sections:
+//
+// - blaze::BLAZE_LOG_ERROR_SECTION : Section for (severe) error messages; blaze::loglevel >= \a error
+// - blaze::BLAZE_LOG_WARNING_SECTION : Section for warning messages; blaze::loglevel >= \a warning
+// - blaze::BLAZE_LOG_INFO_SECTION : Section for important information; blaze::loglevel >= \a info
+// - blaze::BLAZE_LOG_PROGRESS_SECTION: Section for progress information; blaze::loglevel >= \a progress
+// - blaze::BLAZE_LOG_DEBUG_SECTION : Section for debug information; blaze::loglevel >= \a debug
+// - blaze::BLAZE_LOG_DETAIL_SECTION : Section for detail information; blaze::loglevel >= \a detail
+//
+// The following example demonstrates the use of the log sections:
+
+ \code
+ int main( int argc, char** argv )
+ {
+ // Initialization of the MPI system (for MPI parallel simulations only)
+ // The MPI system must be initialized before any logging functionality may be used. In
+ // case it was not called before the first log section it is assumed that the simulation
+ // does not run in parallel. Thus in MPI-parallel simulations it is strongly recommended
+ // to make MPI_Init() the very first call of the main function.
+ MPI_Init( &argc, &argv );
+
+ // ...
+
+ // Log section for error messages
+ // This section is only executed in case the logging level is at least 'error'. The
+ // macro parameter specifies the name of the log handle (in this example 'log') that
+ // can be used as a stream to log any kind of streamable information.
+ BLAZE_LOG_ERROR_SECTION( log ) {
+ log << " Only printed within an active BLAZE_LOG_ERROR_SECTION\n"
+ << " for demonstration purposes!\n";
+ }
+
+ // Log section for warning messages
+ // This section is only executed in case the logging level is at least 'warning'. Again,
+ // the macro parameter specifies the name of the log handle that can be used as a stream
+ // to any kind of streamable information.
+ BLAZE_LOG_WARNING_SECTION( log ) {
+ log << " Only printed within an active BLAZE_LOG_WARNING_SECTION!\n";
+ }
+
+ // ...
+
+ // Finalizing the MPI system (for MPI parallel simulations only)
+ // The MPI system must be finalized after the last pe functionality has been used. It
+ // is recommended to make MPI_Finalize() the very last call of the main function.
+ MPI_Finalize();
+ }
+ \endcode
+
+// Executing this main() function results in the following log file (provided the logging level
+// is set accordingly):
+
+ \code
+ --LOG BEGIN, Thursday, 14.January 2010, 08:31--------------------------------------------
+
+
+ [ERROR ] Only printed within an active BLAZE_LOG_ERROR_SECTION
+ for demonstration purposes!
+
+ [WARNING ] Only printed within an active BLAZE_LOG_WARNING_SECTION!
+
+
+ --LOG END, Thursday, 14.January 2010, 08:31----------------------------------------------
+ \endcode
+
+// The next example shows to nested log sections. Please note that this combination only makes
+// sense in case the outer log section has a lower log level:
+
+ \code
+ // ...
+
+ BLAZE_LOG_ERROR_SECTION( error )
+ {
+ error << " Only printed within an active BLAZE_LOG_ERROR_SECTION\n";
+
+ BLAZE_LOG_WARNING_SECTION( warning ) {
+ warning << " Only printed within an active BLAZE_LOG_WARNING_SECTION\n";
+ }
+
+ error << " Again only printed within an active BLAZE_LOG_ERROR_SECTION\n";
+ }
+
+ // ...
+ \endcode
+
+// Although the BLAZE_LOG_ERROR_SECTION is the outer section, the BLAZE_LOG_WARNING_SECTION
+// appears first in the log file:
+
+ \code
+ --LOG BEGIN, Thursday, 14.January 2010, 08:31--------------------------------------------
+
+
+ [WARNING ] Only printed within an active BLAZE_LOG_WARNING_SECTION
+
+ [ERROR ] Only printed within an active BLAZE_LOG_ERROR_SECTION
+ Again only printed within an active BLAZE_LOG_ERROR_SECTION
+
+
+ --LOG END, Thursday, 14.January 2010, 08:31----------------------------------------------
+ \endcode
+
+// In order to commit the messages in the correct order, it is necessary to manually call the
+// commit function:
+
+ \code
+ // ...
+
+ BLAZE_LOG_ERROR_SECTION( error )
+ {
+ error << " Only printed within an active BLAZE_LOG_ERROR_SECTION\n";
+
+ // Manual call of the commit function
+ error.commit();
+
+ BLAZE_LOG_WARNING_SECTION( warning ) {
+ warning << " Only printed within an active BLAZE_LOG_WARNING_SECTION\n";
+ }
+
+ error << " Again only printed within an active BLAZE_LOG_ERROR_SECTION\n";
+ }
+
+ // ...
+ \endcode
+
+// This results in the following log file:
+
+ \code
+ --LOG BEGIN, Thursday, 14.January 2010, 08:31--------------------------------------------
+
+
+ [ERROR ] Only printed within an active BLAZE_LOG_ERROR_SECTION
+
+ [WARNING ] Only printed within an active BLAZE_LOG_WARNING_SECTION
+
+ [ERROR ] Again only printed within an active BLAZE_LOG_ERROR_SECTION
+
+
+ --LOG END, Thursday, 14.January 2010, 08:31----------------------------------------------
+ \endcode
+*/
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/ProgressSection.h b/src/cpu/blaze/util/logging/ProgressSection.h
new file mode 100644
index 00000000..6908faa6
--- /dev/null
+++ b/src/cpu/blaze/util/logging/ProgressSection.h
@@ -0,0 +1,105 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/ProgressSection.h
+// \brief Header file for the log progress section
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_PROGRESSSECTION_H_
+#define _BLAZE_UTIL_LOGGING_PROGRESSSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/logging/LogSection.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// BLAZE_LOG_PROGRESS_SECTION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logging section for progress information.
+// \ingroup logging
+//
+// This macro starts a log section for information messages. These messages are written to the
+// log file(s) in case the blaze::loglevel has been set to \a progress or higher. The following
+// example demonstrates how this log section is used:
+
+ \code
+ int main( int argc, char** argv )
+ {
+ // Initialization of the MPI system (for MPI parallel simulations)
+ // The MPI system must be initialized before any logging functionality may be used. In
+ // case it was not called before the first log section it is assumed that the simulation
+ // does not run in parallel. Thus in MPI-parallel simulations it is strongly recommended
+ // to make MPI_Init() the very first call of the main function.
+ MPI_Init( &argc, &argv );
+
+ // ...
+
+ // Log section for progress information
+ // This section is only executed in case the logging level is at least 'progress'. The
+ // macro parameter specifies the name of the log handle (in this example 'log') that
+ // can be used as a stream to log any kind of streamable information.
+ BLAZE_LOG_PROGRESS_SECTION( log ) {
+ log << " Only printed within an active BLAZE_LOG_PROGRESS_SECTION!\n";
+ }
+
+ // ...
+
+ // Finalizing the MPI system (for MPI parallel simulations)
+ // The MPI system must be finalized after the last pe functionality has been used. It
+ // is recommended to make MPI_Finalize() the very last call of the main function.
+ MPI_Finalize();
+ }
+ \endcode
+
+// Note that uncaught exceptions emitted from the blaze::BLAZE_LOG_PROGRESS_SECTION might result in
+// lost and/or unlogged information!
+*/
+#define BLAZE_LOG_PROGRESS_SECTION( NAME ) \
+ if( blaze::logging::loglevel >= blaze::logging::progress ) \
+ if( blaze::logging::LogSection NAME = blaze::logging::progress )
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/logging/WarningSection.h b/src/cpu/blaze/util/logging/WarningSection.h
new file mode 100644
index 00000000..248b1406
--- /dev/null
+++ b/src/cpu/blaze/util/logging/WarningSection.h
@@ -0,0 +1,105 @@
+//=================================================================================================
+/*!
+// \file blaze/util/logging/WarningSection.h
+// \brief Header file for the log warning section
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_LOGGING_WARNINGSECTION_H_
+#define _BLAZE_UTIL_LOGGING_WARNINGSECTION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/logging/LogSection.h>
+
+
+namespace blaze {
+
+namespace logging {
+
+//=================================================================================================
+//
+// BLAZE_LOG_WARNING_SECTION MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Logging section for warning messages.
+// \ingroup logging
+//
+// This macro starts a log section for warning messages. These messages are written to the log
+// file(s) in case the blaze::loglevel has been set to \a warning or higher. The following example
+// demonstrates how this log section is used:
+
+ \code
+ int main( int argc, char** argv )
+ {
+ // Initialization of the MPI system (for MPI parallel simulations)
+ // The MPI system must be initialized before any logging functionality may be used. In
+ // case it was not called before the first log section it is assumed that the simulation
+ // does not run in parallel. Thus in MPI-parallel simulations it is strongly recommended
+ // to make MPI_Init() the very first call of the main function.
+ MPI_Init( &argc, &argv );
+
+ // ...
+
+ // Log section for warning messages
+ // This section is only executed in case the logging level is at least 'warning'. The
+ // macro parameter specifies the name of the log handle (in this example 'log') that
+ // can be used as a stream to log any kind of streamable information.
+ BLAZE_LOG_WARNING_SECTION( log ) {
+ log << " Only printed within an active BLAZE_LOG_WARNING_SECTION!\n";
+ }
+
+ // ...
+
+ // Finalizing the MPI system (for MPI parallel simulations)
+ // The MPI system must be finalized after the last pe functionality has been used. It
+ // is recommended to make MPI_Finalize() the very last call of the main function.
+ MPI_Finalize();
+ }
+ \endcode
+
+// Note that uncaught exceptions emitted from the blaze::BLAZE_LOG_WARNING_SECTION might result
+// in lost and/or unlogged information!
+*/
+#define BLAZE_LOG_WARNING_SECTION( NAME ) \
+ if( blaze::logging::loglevel >= blaze::logging::warning ) \
+ if( blaze::logging::LogSection NAME = blaze::logging::warning )
+//*************************************************************************************************
+
+} // namespace logging
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/And.h b/src/cpu/blaze/util/mpl/And.h
new file mode 100644
index 00000000..11dece3e
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/And.h
@@ -0,0 +1,108 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/And.h
+// \brief Header file for the And class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_AND_H_
+#define _BLAZE_UTIL_MPL_AND_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/Bool.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*! Auxiliary helper struct for the And class template.
+// \ingroup mpl
+*/
+template< typename T // Type of the mandatory argument
+ , typename... Ts > // Types of the optional operands
+struct AndHelper
+ : public Bool< T::value && AndHelper<Ts...>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*! Specialization of the AndHelper class template for a single template argument.
+// \ingroup mpl
+*/
+template< typename T > // Type of the mandatory argument
+struct AndHelper<T>
+ : public Bool< T::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time logical and evaluation.
+// \ingroup mpl
+//
+// The And class template performs at compile time a logical and ('&&') evaluation of at least
+// two compile time conditions:
+
+ \code
+ using namespace blaze;
+
+ typedef int Type;
+
+ And< IsIntegral<Type>, IsSigned<Type> >::value // Evaluates to 1
+ And< IsIntegral<Type>, IsFloatingPoint<Type> >::value // Evaluates to 0
+ And< IsFloat<Type> , IsDouble<Type> >::value // Evaluates to 0
+ \endcode
+*/
+template< typename T1 // Type of the first mandatory operand
+ , typename T2 // Type of the second mandatory operand
+ , typename... Ts > // Types of the optional operands
+struct And
+ : public Bool< AndHelper<T1,T2,Ts...>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Bool.h b/src/cpu/blaze/util/mpl/Bool.h
new file mode 100644
index 00000000..45af491f
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Bool.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Bool.h
+// \brief Header file for the Bool class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_BOOL_H_
+#define _BLAZE_UTIL_MPL_BOOL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral constant wrapper for \a bool.
+// \ingroup mpl
+//
+// The Bool class template represents an integral wrapper for a compile time constant expression
+// of type \a bool. The value of a Bool can be accessed via the nested \a value (which is guaranteed
+// to be of type \a bool), the type can be accessed via the nested type definition \a ValueType.
+
+ \code
+ using namespace blaze;
+
+ Bool<true>::value // Evaluates to true
+ Bool<false>::ValueType // Results in bool
+ \endcode
+*/
+template< bool C >
+struct Bool : public IntegralConstant<bool,C>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Char.h b/src/cpu/blaze/util/mpl/Char.h
new file mode 100644
index 00000000..4cd49c98
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Char.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Char.h
+// \brief Header file for the Char class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_CHAR_H_
+#define _BLAZE_UTIL_MPL_CHAR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral constant wrapper for \a char.
+// \ingroup mpl
+//
+// The Char class template represents an integral wrapper for a compile time constant expression
+// of type \a char. The value of an Char can be accessed via the nested \a value (which is guaranteed
+// to be of type \a char), the type can be accessed via the nested type definition \a ValueType.
+
+ \code
+ using namespace blaze;
+
+ Char<3>::value // Evaluates to 3
+ Char<5>::ValueType // Results in char
+ \endcode
+*/
+template< char N >
+struct Char : IntegralConstant<char,N>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Equal.h b/src/cpu/blaze/util/mpl/Equal.h
new file mode 100644
index 00000000..50ba379e
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Equal.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Equal.h
+// \brief Header file for the Equal class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_EQUAL_H_
+#define _BLAZE_UTIL_MPL_EQUAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/Bool.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type comparison.
+// \ingroup mpl
+//
+// The Equal class template compares the two given types using the equality operator ('==').
+// In case \a T1::value is equal to \a T2::value, the nested \a value member is set to \a true.
+// Otherwise it is set to \a false.
+
+ \code
+ using namespace blaze;
+
+ Equal< Int<3>, Int<3> >::value // Evaluates to true
+ Equal< Int<5>, Long<5> >::value // Evaluates to true
+ Equal< Long<0>, Int<4> >::value // Evaluates to false
+ Equal< Int<1>, Int<2>::ValueType // Results in bool
+ \endcode
+*/
+template< typename T1 // The type of the left-hand side operand
+ , typename T2 > // The type of the right-hand side operand
+struct Equal : public Bool< ( T1::value == T2::value ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Greater.h b/src/cpu/blaze/util/mpl/Greater.h
new file mode 100644
index 00000000..6125f320
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Greater.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Greater.h
+// \brief Header file for the Greater class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_GREATER_H_
+#define _BLAZE_UTIL_MPL_GREATER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/Bool.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type comparison.
+// \ingroup mpl
+//
+// The Greater class template compares the two given types using the greater-than operator ('>').
+// In case \a T1::value is greater than \a T2::value, the nested \a value member is set to 1.
+// Otherwise it is set to 0.
+
+ \code
+ using namespace blaze;
+
+ Greater< Int<5> , Int<2> >::value // Evaluates to true
+ Greater< Int<5> , Long<2> >::value // Evaluates to true
+ Greater< Long<2>, Int<2> >::value // Evaluates to false
+ Greater< Int<2> , Long<5> >::value // Evaluates to false
+ Greater< Int<5> , Int<2> >::ValueType // Results in bool
+ \endcode
+*/
+template< typename T1 // The type of the left-hand side operand
+ , typename T2 > // The type of the right-hand side operand
+struct Greater : public Bool< ( T1::value > T2::value ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/If.h b/src/cpu/blaze/util/mpl/If.h
new file mode 100644
index 00000000..feedfc3a
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/If.h
@@ -0,0 +1,165 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/If.h
+// \brief Header file for the If class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_IF_H_
+#define _BLAZE_UTIL_MPL_IF_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type selection.
+// \ingroup mpl
+//
+// The IfTrue class template selects one of the two given types \a T1 and \a T2 depending
+// on the \a Condition template argument. In case the \a Condition compile time constant
+// expression evaluates to \a true, the member type definition \a Type is set to \a T1.
+// In case \a Condition evaluates to \a false, \a Type is set to \a T2.
+*/
+template< bool Condition // Compile time selection
+ , typename T1 // Type to be selected if Condition=true
+ , typename T2 > // Type to be selected if Condition=false
+struct IfTrue
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef T1 Type; //!< The selected type.
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IfTrue class template.
+// \ingroup mpl
+//
+// This specialization of the IfTrue template is selected in case the \a Condition compile time
+// constant expression evaluates to \a false. The member type definition is set to the second
+// given type \a T2.
+*/
+template< typename T1 // Type not to be selected
+ , typename T2 > // Type to be selected
+struct IfTrue<false,T1,T2>
+{
+ public:
+ //**********************************************************************************************
+ typedef T2 Type; //!< The selected type.
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the IfTrue class template.
+// \ingroup util
+//
+// The IfTrue_ alias declaration provides a convenient shortcut to access the nested \a Type of
+// the IfTrue class template. For instance, given the types \a C, \a T1, and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename IfTrue< IsBuiltin<C>::value, T1, T2 >::Type;
+ using Type2 = IfTrue_< IsBuiltin<C>::value, T1, T2 >;
+ \endcode
+*/
+template< bool Condition // Compile time selection
+ , typename T1 // Type to be selected if Condition=true
+ , typename T2 > // Type to be selected if Condition=false
+using IfTrue_ = typename IfTrue<Condition,T1,T2>::Type;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type selection.
+// \ingroup mpl
+//
+// The If class template selects one of the two given types \a T2 and \a T3 depending on \a T1.
+// In case \a T1::value evaluates to \a true, the member type definition \a Type is set to \a T2.
+// In case \a T1::value evaluates to \a false, \a Type is set to \a T3.
+*/
+template< typename T1 // Type of the condition
+ , typename T2 // Type to be selected if T1::value=true
+ , typename T3 > // Type to be selected if T1::value=false
+struct If
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename IfTrue< T1::value, T2, T3 >::Type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the If class template.
+// \ingroup util
+//
+// The If_ alias declaration provides a convenient shortcut to access the nested \a Type of the
+// If class template. For instance, given the types \a T1, \a T2, and \a T3 the following two
+// type definitions are identical:
+
+ \code
+ using Type1 = typename If< IsBuiltin<T1>, T2, T3 >::Type;
+ using Type2 = If_< IsBuiltin<T1>, T2, T3 >;
+ \endcode
+*/
+template< typename T1 // Type of the condition
+ , typename T2 // Type to be selected if T1::value=true
+ , typename T3 > // Type to be selected if T1::value=false
+using If_ = typename If<T1,T2,T3>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Int.h b/src/cpu/blaze/util/mpl/Int.h
new file mode 100644
index 00000000..9ea2f65e
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Int.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Int.h
+// \brief Header file for the Int class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_INT_H_
+#define _BLAZE_UTIL_MPL_INT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral constant wrapper for \a int.
+// \ingroup mpl
+//
+// The Int class template represents an integral wrapper for a compile time constant expression
+// of type \a int. The value of an Int can be accessed via the nested \a value (which is guaranteed
+// to be of type \a int), the type can be accessed via the nested type definition \a ValueType.
+
+ \code
+ using namespace blaze;
+
+ Int<3>::value // Evaluates to 3
+ Int<5>::ValueType // Results in int
+ \endcode
+*/
+template< int N >
+struct Int : public IntegralConstant<int,N>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Less.h b/src/cpu/blaze/util/mpl/Less.h
new file mode 100644
index 00000000..73aa88a0
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Less.h
@@ -0,0 +1,84 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Less.h
+// \brief Header file for the Less class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_LESS_H_
+#define _BLAZE_UTIL_MPL_LESS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/Bool.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type comparison.
+// \ingroup mpl
+//
+// The Less class template compares the two given types using the less-than operator ('<'). In
+// case \a T1::value is less than \a T2::value, the nested \a value member is set to 1. Otherwise
+// it is set to 0.
+
+ \code
+ using namespace blaze;
+
+ Less< Int<2> , Int<5> >::value // Evaluates to true
+ Less< Long<2>, Int<5> >::value // Evaluates to true
+ Less< Int<2> , Long<2> >::value // Evaluates to false
+ Less< Long<5>, Int<2> >::value // Evaluates to false
+ Less< Int<2>, Int<5> >::ValueType // Results in bool
+ \endcode
+*/
+template< typename T1 // The type of the left-hand side operand
+ , typename T2 > // The type of the right-hand side operand
+#if (defined _MSC_VER)
+struct Less : public Bool< ( T2::value > T1::value ) >
+#else
+struct Less : public Bool< ( T1::value < T2::value ) >
+#endif
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Long.h b/src/cpu/blaze/util/mpl/Long.h
new file mode 100644
index 00000000..793378d7
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Long.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Long.h
+// \brief Header file for the Long class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_LONG_H_
+#define _BLAZE_UTIL_MPL_LONG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral constant wrapper for \a long.
+// \ingroup mpl
+//
+// The Long class template represents an integral wrapper for a compile time constant expression
+// of type \a long. The value of an Long can be accessed via the nested \a value (which is guaranteed
+// to be of type \a long), the type can be accessed via the nested type definition \a ValueType.
+
+ \code
+ using namespace blaze;
+
+ Long<3>::value // Evaluates to 3
+ Long<5>::ValueType // Results in long
+ \endcode
+*/
+template< long N >
+struct Long : public IntegralConstant<long,N>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/MPL.h b/src/cpu/blaze/util/mpl/MPL.h
new file mode 100644
index 00000000..a230e034
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/MPL.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/MPL.h
+// \brief Meta-Programming Language (MPL) module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_MPL_H_
+#define _BLAZE_UTIL_MPL_MPL_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup mpl Meta-Programming Language
+// \ingroup util
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Max.h b/src/cpu/blaze/util/mpl/Max.h
new file mode 100644
index 00000000..a610f355
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Max.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Max.h
+// \brief Header file for the Max class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_MAX_H_
+#define _BLAZE_UTIL_MPL_MAX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Less.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time value evaluation.
+// \ingroup mpl
+//
+// The Max class template selects the larger of the two given template arguments \a T1 and \a T2.
+// In order for Max to be able to determine the larger type, both arguments are required to have
+// a nested member \a value. In case \a T1::value is larger than \a T2::value, the nested type
+// definition \a Type is set to \a T1, otherwise it is set to \a T2.
+
+ \code
+ blaze::Max< Int<3> , Int<2> >::Type // Results in Int<3>
+ blaze::Max< Long<3>, Int<2> >::Type // Results in Long<3>
+ blaze::Max< Int<3> , Long<2> >::Type // Results in Int<3>
+ \endcode
+*/
+template< typename T1 // Type of the first compile time value
+ , typename T2 > // Type of the second compile time value
+struct Max : public If_< Less<T1,T2>, T2, T1 >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Min.h b/src/cpu/blaze/util/mpl/Min.h
new file mode 100644
index 00000000..a3ec21e2
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Min.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Min.h
+// \brief Header file for the Min class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_MIN_H_
+#define _BLAZE_UTIL_MPL_MIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/mpl/Less.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time value evaluation.
+// \ingroup mpl
+//
+// The Min class template selects the smaller of the two given template arguments \a T1 and \a T2.
+// In order for Min to be able to determine the smaller type, both arguments are required to have
+// a nested member \a value. In case \a T1::value is smaller than \a T2::value, the nested type
+// definition \a Type is set to \a T1, otherwise it is set to \a T2.
+
+ \code
+ blaze::Min< Int<3> , Int<2> >::Type // Results in Int<2>
+ blaze::Min< Long<3>, Int<2> >::Type // Results in Int<2>
+ blaze::Min< Int<3> , Long<2> >::Type // Results in Long<2>
+ \endcode
+*/
+template< typename T1 // Type of the first compile time value
+ , typename T2 > // Type of the second compile time value
+struct Min : public If_< Less<T1,T2>, T1, T2 >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Minus.h b/src/cpu/blaze/util/mpl/Minus.h
new file mode 100644
index 00000000..08c36fd2
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Minus.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Minus.h
+// \brief Header file for the Minus class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_MINUS_H_
+#define _BLAZE_UTIL_MPL_MINUS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/CommonType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral subtraction.
+// \ingroup mpl
+//
+// The Minus class template returns the difference of the two given template arguments \a T1 and
+// \a T2. In order for Minus to be able to subtract the two types, both arguments are required to
+// have a nested member \a value. The result of the subtraction can be accessed via the nested
+// member \a value, the resulting type is available via the nested type \a ValueType.
+
+ \code
+ blaze::Minus< Int<3> , Int<2> >::value // Results in 5
+ blaze::Minus< Long<3>, Int<2> >::ValueType // Results in long
+ blaze::Minus< Int<3> , Long<2> >::ValueType // Results in long
+ \endcode
+*/
+template< typename T1 // Type of the first compile time value
+ , typename T2 > // Type of the second compile time value
+struct Minus
+ : public IntegralConstant< CommonType_< typename T1::ValueType, typename T2::ValueType >
+ , ( T1::value - T2::value ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Modulus.h b/src/cpu/blaze/util/mpl/Modulus.h
new file mode 100644
index 00000000..9fbbee1b
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Modulus.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Modulus.h
+// \brief Header file for the Modulus class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_MODULUS_H_
+#define _BLAZE_UTIL_MPL_MODULUS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/CommonType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral modulus operation.
+// \ingroup mpl
+//
+// The Modulus class template returns the result of a modulus operation between the two given
+// template arguments \a T1 and \a T2. In order for Modulus to be able to perform the operation
+// with the given two types, both arguments are required to have a nested member \a value. The
+// result of the modulus operation can be accessed via the nested member \a value, the resulting
+// type is available via the nested type \a ValueType.
+
+ \code
+ blaze::Modulus< Int<3> , Int<2> >::value // Results in 1
+ blaze::Modulus< Long<3>, Int<2> >::ValueType // Results in long
+ blaze::Modulus< Int<3> , Long<2> >::ValueType // Results in long
+ \endcode
+*/
+template< typename T1 // Type of the first compile time value
+ , typename T2 > // Type of the second compile time value
+struct Modulus
+ : public IntegralConstant< CommonType_< typename T1::ValueType, typename T2::ValueType >
+ , ( T1::value % T2::value ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/NextMultiple.h b/src/cpu/blaze/util/mpl/NextMultiple.h
new file mode 100644
index 00000000..073bdb9e
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/NextMultiple.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/NextMultiple.h
+// \brief Header file for the NextMultiple class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_NEXTMULTIPLE_H_
+#define _BLAZE_UTIL_MPL_NEXTMULTIPLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Minus.h>
+#include <blaze/util/mpl/Modulus.h>
+#include <blaze/util/mpl/Plus.h>
+#include <blaze/util/StaticAssert.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral round up operation.
+// \ingroup mpl
+//
+// The NextMultiple class template rounds up the given template argument of type \a T1 to the
+// next multiple of the given template argument of type \a T2. In case \a T1 already represents
+// a multiple of \a T2, the result is \a T1. In order for NextMultiple to be able to perform the
+// round up operation, both arguments are required to have a nested member \a value. The result
+// of the operation can be accessed via the nested member \a value, the resulting type is
+// available via the nested type \a ValueType.
+
+ \code
+ blaze::NextMultiple< Int<3> , Int<2> >::value // Results in 4
+ blaze::NextMultiple< Long<3>, Int<2> >::ValueType // Results in long
+ blaze::NextMultiple< Int<3> , Long<2> >::ValueType // Results in long
+ \endcode
+
+// Note that both \a T1 and \a T2 are expected to represent positive integrals. The attempt to
+// use NextMultiple with a negative or zero integral results in a compilation error!
+*/
+template< typename T1 // Type of the first compile time value
+ , typename T2 > // Type of the second compile time value
+struct NextMultiple
+ : public Plus< T1, Modulus< Minus< T2, Modulus< T1, T2 > >, T2 > >
+{
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ BLAZE_STATIC_ASSERT( T1::value > 0 && T2::value > 0 );
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Not.h b/src/cpu/blaze/util/mpl/Not.h
new file mode 100644
index 00000000..b54fa70b
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Not.h
@@ -0,0 +1,76 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Not.h
+// \brief Header file for the Not class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_NOT_H_
+#define _BLAZE_UTIL_MPL_NOT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/Bool.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type negation.
+// \ingroup mpl
+//
+// The Not class template negates the given compile time condition. In case the given condition
+// would evaluate to \a true, the nested member enumeration is set to \a false and vice versa:
+
+ \code
+ using namespace blaze;
+
+ Not< IsIntegral<int> >::value // Evaluates to false
+ Not< IsDouble<int> >::value // Evaluates to true
+ Not< IsSigned<int> >::ValueType // Results in bool
+ \endcode
+*/
+template< typename C > // Condition to be negated
+struct Not : public Bool< !C::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Or.h b/src/cpu/blaze/util/mpl/Or.h
new file mode 100644
index 00000000..a8127e7a
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Or.h
@@ -0,0 +1,108 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Or.h
+// \brief Header file for the Or class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_OR_H_
+#define _BLAZE_UTIL_MPL_OR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/Bool.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*! Auxiliary helper struct for the Or class template.
+// \ingroup mpl
+*/
+template< typename T // Type of the mandatory argument
+ , typename... Ts > // Types of the optional operands
+struct OrHelper
+ : public Bool< T::value || OrHelper<Ts...>::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*! Specialization of the OrHelper class template for a single template argument.
+// \ingroup mpl
+*/
+template< typename T > // Type of the mandatory argument
+struct OrHelper<T>
+ : public Bool< T::value >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time logical or evaluation.
+// \ingroup mpl
+//
+// The Or class template performs at compile time a logical or ('&&') evaluation of at least
+// two compile time conditions:
+
+ \code
+ using namespace blaze;
+
+ typedef int Type;
+
+ Or< IsIntegral<Type>, IsSigned<Type> >::value // Evaluates to 1
+ Or< IsIntegral<Type>, IsFloatingPoint<Type> >::value // Evaluates to 1
+ Or< IsFloat<Type> , IsDouble<Type> >::value // Evaluates to 0
+ \endcode
+*/
+template< typename T1 // Type of the first mandatory operand
+ , typename T2 // Type of the second mandatory operand
+ , typename... Ts > // Types of the optional operands
+struct Or
+ : public Bool< OrHelper<T1,T2,Ts...>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Plus.h b/src/cpu/blaze/util/mpl/Plus.h
new file mode 100644
index 00000000..765a7bbd
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Plus.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Plus.h
+// \brief Header file for the Plus class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_PLUS_H_
+#define _BLAZE_UTIL_MPL_PLUS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/CommonType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral addition.
+// \ingroup mpl
+//
+// The Plus class template returns the sum of the two given template arguments \a T1 and \a T2.
+// In order for Plus to be able to add the two types, both arguments are required to have a nested
+// member \a value. The result of the addition can be accessed via the nested member \a value, the
+// resulting type is available via the nested type \a ValueType.
+
+ \code
+ blaze::Plus< Int<3> , Int<2> >::value // Results in 5
+ blaze::Plus< Long<3>, Int<2> >::ValueType // Results in long
+ blaze::Plus< Int<3> , Long<2> >::ValueType // Results in long
+ \endcode
+*/
+template< typename T1 // Type of the first compile time value
+ , typename T2 > // Type of the second compile time value
+struct Plus
+ : public IntegralConstant< CommonType_< typename T1::ValueType, typename T2::ValueType >
+ , ( T1::value + T2::value ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/SizeT.h b/src/cpu/blaze/util/mpl/SizeT.h
new file mode 100644
index 00000000..13cc7f08
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/SizeT.h
@@ -0,0 +1,78 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/SizeT.h
+// \brief Header file for the SizeT class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_SIZET_H_
+#define _BLAZE_UTIL_MPL_SIZET_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral constant wrapper for \a size_t.
+// \ingroup mpl
+//
+// The SizeT class template represents an integral wrapper for a compile time constant expression
+// of type \a size_t. The value of an SizeT can be accessed via the nested \a value (which is
+// guaranteed to be of type \a size_t), the type can be accessed via the nested type definition
+// \a ValueType.
+
+ \code
+ using namespace blaze;
+
+ SizeT<3>::value // Evaluates to 3
+ SizeT<5>::ValueType // Results in size_t
+ \endcode
+*/
+template< size_t N >
+struct SizeT : public IntegralConstant<size_t,N>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Times.h b/src/cpu/blaze/util/mpl/Times.h
new file mode 100644
index 00000000..a57c7438
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Times.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Times.h
+// \brief Header file for the Times class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_TIMES_H_
+#define _BLAZE_UTIL_MPL_TIMES_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/CommonType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time integral multiplication.
+// \ingroup mpl
+//
+// The Times class template returns the product of the two given template arguments \a T1 and
+// \a T2. In order for Times to be able to multiply the two types, both arguments are required
+// to have a nested member \a value. The result of the multiplication can be accessed via the
+// nested member \a value, the resulting type is available via the nested type \a ValueType.
+
+ \code
+ blaze::Times< Int<3> , Int<2> >::value // Results in 6
+ blaze::Times< Long<3>, Int<2> >::ValueType // Results in long
+ blaze::Times< Int<3> , Long<2> >::ValueType // Results in long
+ \endcode
+*/
+template< typename T1 // Type of the first compile time value
+ , typename T2 > // Type of the second compile time value
+struct Times
+ : public IntegralConstant< CommonType_< typename T1::ValueType, typename T2::ValueType >
+ , ( T1::value * T2::value ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/mpl/Xor.h b/src/cpu/blaze/util/mpl/Xor.h
new file mode 100644
index 00000000..d598a8ee
--- /dev/null
+++ b/src/cpu/blaze/util/mpl/Xor.h
@@ -0,0 +1,80 @@
+//=================================================================================================
+/*!
+// \file blaze/util/mpl/Xor.h
+// \brief Header file for the Xor class template
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_MPL_XOR_H_
+#define _BLAZE_UTIL_MPL_XOR_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/Bool.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time logical xor evaluation.
+// \ingroup mpl
+//
+// The Xor class template performs at compile time a logical xor evaluation of the two given
+// compile time conditions:
+
+ \code
+ using namespace blaze;
+
+ typedef int Type;
+
+ Xor< IsSigned<Type> , IsUnsigned<Type> >::value // Evaluates to 1
+ Xor< IsIntegral<Type>, IsFloatingPoint<Type> >::value // Evaluates to 1
+ Xor< IsSigned<Type> , IsIntegral<Type> >::value // Evaluates to 0
+ Xor< IsUnsigned<Type>, IsFloatingPoint<Type> >::value // Evaluates to 0
+ \endcode
+*/
+template< typename T1 // Type of the first operand
+ , typename T2 > // Type of the second operand
+struct Xor : public Bool< ( T1::value ^ T2::value ) >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/policies/ArrayDelete.h b/src/cpu/blaze/util/policies/ArrayDelete.h
new file mode 100644
index 00000000..6af3ef26
--- /dev/null
+++ b/src/cpu/blaze/util/policies/ArrayDelete.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/util/policies/ArrayDelete.h
+// \brief Header file for the ArrayDelete policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_ARRAYDELETE_H_
+#define _BLAZE_UTIL_POLICIES_ARRAYDELETE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/checked_delete.hpp>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Array-delete policy class.
+// \ingroup util
+//
+// The ArrayDelete policy functor class applies an array delete operation to the given argument.
+// Note that the array delete operation is NOT permitted for inclomplete types (i.e. declared
+// but undefined data types). The attempt to apply an ArrayDelete functor to a pointer to an
+// array of objects of incomplete type results in a compile time error!
+*/
+struct ArrayDelete
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ template< typename Type >
+ inline void operator()( Type ptr ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of the array-delete policy.
+//
+// \param ptr The pointer to the array to be deleted.
+// \return void
+//
+// This function applies an array delete operation to the given argument. Note that the array
+// delete operation is NOT permitted for inclomplete types (i.e. declared but undefined data
+// types). The attempt to use this function for a pointer to an array of objects of incomplete
+// type results in a compile time error!
+*/
+template< typename Type >
+inline void ArrayDelete::operator()( Type ptr ) const
+{
+ boost::checked_array_delete( ptr );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/policies/ConstantGrowth.h b/src/cpu/blaze/util/policies/ConstantGrowth.h
new file mode 100644
index 00000000..b1e5d606
--- /dev/null
+++ b/src/cpu/blaze/util/policies/ConstantGrowth.h
@@ -0,0 +1,112 @@
+//=================================================================================================
+/*!
+// \file blaze/util/policies/ConstantGrowth.h
+// \brief Header file for the ConstantGrowth policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_CONSTANTGROWTH_H_
+#define _BLAZE_UTIL_POLICIES_CONSTANTGROWTH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Functions.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constant growth policy class.
+// \ingroup util
+//
+// The ConstantGrowth policy class implements a constant growth strategy. It can be customized
+// for any purpose: the \a Growth template argument specifies the constant increase of the given
+// size.
+*/
+template< size_t Growth >
+struct ConstantGrowth
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t operator()( size_t oldSize, size_t minSize ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the constant growth policy for 0 growth.
+// \ingroup util
+*/
+template<>
+struct ConstantGrowth<0>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns a new size depending on the given old size and the required minimum size.
+//
+// \param old The old size.
+// \param minimum The required minimum size.
+// \return The new size (at least the required minimum size).
+*/
+template< size_t Growth >
+inline size_t ConstantGrowth<Growth>::operator()( size_t old, size_t minimum ) const
+{
+ const size_t needed( max<size_t>( old+Growth, minimum ) );
+ return ( ( needed )?( 4 * ( (needed-1)/4+1 ) ):( 0 ) );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/policies/Deallocate.h b/src/cpu/blaze/util/policies/Deallocate.h
new file mode 100644
index 00000000..9a92a3fb
--- /dev/null
+++ b/src/cpu/blaze/util/policies/Deallocate.h
@@ -0,0 +1,105 @@
+//=================================================================================================
+/*!
+// \file blaze/util/policies/Deallocate.h
+// \brief Header file for the Deallocate policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_DEALLOCATE_H_
+#define _BLAZE_UTIL_POLICIES_DEALLOCATE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Memory.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Deallocate policy class.
+// \ingroup util
+//
+// The Deallocate deletion policy is the according deletion policy for arrays allocated via
+// the blaze::allocate function. It uses deallocate to free the resource. Note that the delete
+// operation is NOT permitted for inclomplete types (i.e. declared but undefined data types).
+// The attempt to apply a PtrDelete functor to a pointer to an object of incomplete type
+// results in a compile time error!
+*/
+struct Deallocate
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ template< typename Type >
+ inline void operator()( Type ptr ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of the deallocate deletion policy.
+//
+// \param ptr The pointer to delete.
+// \return void
+//
+// This function frees the given pointer resource via the blaze::deallocate function. Note that
+// the delete operation is NOT permitted for incomplete types (i.e. declared but undefined data
+// types). The attempt to use this function for a pointer to an object of incomplete type results
+// in a compile time error!
+*/
+template< typename Type >
+inline void Deallocate::operator()( Type ptr ) const
+{
+ deallocate( ptr );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/policies/DefaultDelete.h b/src/cpu/blaze/util/policies/DefaultDelete.h
new file mode 100644
index 00000000..d612cd06
--- /dev/null
+++ b/src/cpu/blaze/util/policies/DefaultDelete.h
@@ -0,0 +1,158 @@
+//=================================================================================================
+/*!
+// \file blaze/util/policies/DefaultDelete.h
+// \brief Header file for the DefaultDelete policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_DEFAULTDELETE_H_
+#define _BLAZE_UTIL_POLICIES_DEFAULTDELETE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/checked_delete.hpp>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default C++ deletion policy class.
+// \ingroup util
+//
+// The DefaultDelete deletion policy is the standard delete for resources allocated via the new
+// operator. It uses delete or array delete (depending on the template argument) to free the
+// resource:
+
+ \code
+ class Resource { ... };
+
+ DefaultDelete<Resource> ptrDelete // Uses delete to free resources
+ DefaultDelete<Resource[]> arrayDelete; // Uses array delete to free resources
+ \endcode
+
+// Note the explicit use of empty array bounds to configure DefaultDelete to use array delete
+// instead of delete. Also note that the delete operation is NOT permitted for incomplete types
+// (i.e. declared but undefined data types). The attempt to apply a DefaultDelete functor to a
+// pointer or array to an object of incomplete type results in a compile time error!
+*/
+template< typename Type >
+struct DefaultDelete
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void operator()( Type* ptr ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Implementation of the default delete policy.
+//
+// \param ptr The pointer to delete.
+// \return void
+//
+// This function frees the given pointer resource via delete. Note that the delete operation
+// is NOT permitted for incomplete types (i.e. declared but undefined data types). The attempt
+// to use this function for a pointer to an object of incomplete type results in a compile time
+// error!
+*/
+template< typename Type >
+inline void DefaultDelete<Type>::operator()( Type* ptr ) const
+{
+ boost::checked_delete( ptr );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SPECIALIZATION FOR ARRAYS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the DefaultDelete class template for arrays.
+// \ingroup util
+//
+// This specialization of the DefaultDelete class template uses array delete to free the
+// allocated resource.
+*/
+template< typename Type >
+struct DefaultDelete<Type[]>
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void operator()( Type* ptr ) const;
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Implementation of the default array delete policy.
+//
+// \param ptr The pointer to delete.
+// \return void
+//
+// This function frees the given array resource via array delete. Note that the delete operation
+// is NOT permitted for incomplete types (i.e. declared but undefined data types). The attempt
+// to use this function for a pointer to an object of incomplete type results in a compile time
+// error!
+*/
+template< typename Type >
+inline void DefaultDelete<Type[]>::operator()( Type* ptr ) const
+{
+ boost::checked_array_delete( ptr );
+}
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/policies/LinearGrowth.h b/src/cpu/blaze/util/policies/LinearGrowth.h
new file mode 100644
index 00000000..b25485f0
--- /dev/null
+++ b/src/cpu/blaze/util/policies/LinearGrowth.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/util/policies/LinearGrowth.h
+// \brief Header file for the LinearGrowth policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_LINEARGROWTH_H_
+#define _BLAZE_UTIL_POLICIES_LINEARGROWTH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Functions.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Linear growth policy class.
+// \ingroup util
+//
+// The LinearGrowth policy class implements a linear growth strategy. It can be customized for
+// any purpose: the \a Growth template argument specifies the factor of the size growth.
+*/
+template< size_t Growth >
+struct LinearGrowth
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t operator()( size_t oldSize, size_t minSize ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the linear growth policy for 0 growth.
+// \ingroup util
+*/
+template<>
+struct LinearGrowth<0>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the linear growth policy for 1 growth.
+// \ingroup util
+*/
+template<>
+struct LinearGrowth<1>;
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns a new size depending on the given old size and the required minimum size.
+//
+// \param old The old size.
+// \param minimum The required minimum size.
+// \return The new size (at least the required minimum size).
+*/
+template< size_t Growth >
+inline size_t LinearGrowth<Growth>::operator()( size_t old, size_t minimum ) const
+{
+ const size_t needed( max<size_t>( old*Growth, minimum ) );
+ return ( ( needed )?( 4 * ( (needed-1)/4+1 ) ):( 0 ) );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/policies/NoDelete.h b/src/cpu/blaze/util/policies/NoDelete.h
new file mode 100644
index 00000000..97bde1c7
--- /dev/null
+++ b/src/cpu/blaze/util/policies/NoDelete.h
@@ -0,0 +1,85 @@
+//=================================================================================================
+/*!
+// \file blaze/util/policies/NoDelete.h
+// \brief Header file for the NoDelete policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_NODELETE_H_
+#define _BLAZE_UTIL_POLICIES_NODELETE_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief No-delete policy class.
+// \ingroup util
+*/
+struct NoDelete
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ template< typename Type >
+ inline void operator()( const Type& ptr ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of the no-delete policy.
+//
+// \param ptr The pointer to delete.
+// \return void
+*/
+template< typename Type >
+inline void NoDelete::operator()( const Type& /*ptr*/ ) const
+{}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/policies/OptimalGrowth.h b/src/cpu/blaze/util/policies/OptimalGrowth.h
new file mode 100644
index 00000000..9da8c7cf
--- /dev/null
+++ b/src/cpu/blaze/util/policies/OptimalGrowth.h
@@ -0,0 +1,101 @@
+//=================================================================================================
+/*!
+// \file blaze/util/policies/OptimalGrowth.h
+// \brief Header file for the OptimalGrowth policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_OPTIMALGROWTH_H_
+#define _BLAZE_UTIL_POLICIES_OPTIMALGROWTH_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/math/Functions.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Optimal growth policy class.
+// \ingroup util
+//
+// The OptimalGrowth policy class implements the optimal growth strategy suggested by Andrew
+// Koenig for the std::vector class (see Andrew Koenig's column in the September 1998 issue of
+// JOOP (Journal of Object-Oriented Programming), or the Dr. Dobb's article 'C++ Made Easier:
+// How Vectors Grow', 2001). It applies an exponential growth strategy using a factor of 1.5
+// and additionally ensures that the sizes returns are always multiples of four.
+*/
+struct OptimalGrowth
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline size_t operator()( size_t oldSize, size_t minSize ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns a new size depending on the given old size and the required minimum size.
+//
+// \param old The old size.
+// \param minimum The required minimum size.
+// \return The new size (at least the required minimum size).
+*/
+inline size_t OptimalGrowth::operator()( size_t old, size_t minimum ) const
+{
+ const size_t needed( max( static_cast<size_t>( old*1.5 ), minimum ) );
+ return ( ( needed )?( 4 * ( (needed-1)/4 + 1 ) ):( 0 ) );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/policies/PtrDelete.h b/src/cpu/blaze/util/policies/PtrDelete.h
new file mode 100644
index 00000000..6391d0ef
--- /dev/null
+++ b/src/cpu/blaze/util/policies/PtrDelete.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/util/policies/PtrDelete.h
+// \brief Header file for the PtrDelete policy classes.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_POLICIES_PTRDELETE_H_
+#define _BLAZE_UTIL_POLICIES_PTRDELETE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <boost/checked_delete.hpp>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Pointer-delete policy class.
+// \ingroup util
+//
+// The PtrDelete policy functor class applies a delete operation to the given argument. Note that
+// the delete operation is NOT permitted for inclomplete types (i.e. declared but undefined data
+// types). The attempt to apply a PtrDelete functor to a pointer to an object of incomplete type
+// results in a compile time error!
+*/
+struct PtrDelete
+{
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ template< typename Type >
+ inline void operator()( Type ptr ) const;
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Implementation of the pointer-delete policy.
+//
+// \param ptr The pointer to delete.
+// \return void
+//
+// This function applies a standard delete operation to the given argument. Note that the delete
+// operation is NOT permitted for inclomplete types (i.e. declared but undefined data types). The
+// attempt to use this function for a pointer to an object of incomplete type results in a compile
+// time error!
+*/
+template< typename Type >
+inline void PtrDelete::operator()( Type ptr ) const
+{
+ boost::checked_delete( ptr );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/serialization/Archive.h b/src/cpu/blaze/util/serialization/Archive.h
new file mode 100644
index 00000000..7dec6e58
--- /dev/null
+++ b/src/cpu/blaze/util/serialization/Archive.h
@@ -0,0 +1,537 @@
+//=================================================================================================
+/*!
+// \file blaze/util/serialization/Archive.h
+// \brief Header file for the Archive class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_SERIALIZATION_ARCHIVE_H_
+#define _BLAZE_UTIL_SERIALIZATION_ARCHIVE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <blaze/util/DisableIf.h>
+#include <blaze/util/EnableIf.h>
+#include <blaze/util/NonCopyable.h>
+#include <blaze/util/Types.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+
+
+namespace blaze {
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Binary archive for the portable serialization of data.
+// \ingroup serialization
+//
+// The Archive class implements the functionality to create platform independent, portable,
+// representations of arbitrary C++ data structures. The resulting binary data structures can
+// be used to reconstitute the data structures in a different context, on another platform,
+// etc.
+//
+// The following example demonstrates the Archive class by means of a C-style POD data structure:
+
+ \code
+ struct POD {
+ int i;
+ unsigned int u;
+ float f;
+ double d;
+ };
+ \endcode
+
+// The archive already supports the (de-)serialization of built-in data types. In order to be able
+// to serialize the POD data structure, i.e. to convert it into a binary representation that can
+// stored or transfered to other machines, the according \c serialize and \c deserialize function
+// have to be implemented:
+
+ \code
+ template< typename Archive >
+ void serialize( Archive& archive, const POD& pod )
+ {
+ archive << pod.i << pod.u << pod.f << pod.d;
+ }
+
+ template< typename Archive >
+ void deserialize( Archive& archive, POD& pod )
+ {
+ archive >> pod.i >> pod.u >> pod.f >> pod.d;
+ }
+ \endcode
+
+// The \c serialize function implements the conversion from the POD to a binary representation,
+// the \c deserialize function implements the reverse conversion from a binary representation to
+// a POD. Note that it is important to write the values to the archive in exactly the same order
+// as the values are read from the archive!
+//
+// With these two functions it is already possible to serialize a POD object:
+
+ \code
+ int main()
+ {
+ // Creating a binary representation of a POD in the file 'filename'
+ {
+ POD pod;
+ // ... Initialize the POD with values
+ Archive<std::ofstream> archive( "filename", std::ofstream::trunc );
+ archive << pod;
+ }
+
+ // Reconstituting the POD from the binary representation
+ {
+ POD pod;
+ Archive<std::ifstream> archive( "filename" );
+ archive >> pod;
+ }
+ }
+ \endcode
+
+// Each archive has to be bound to either an output or input stream. In the example, the
+// archive is bound to a file output stream that is created by passing the file name and
+// the according flags to the archive. Subsequently, the archive can be used like an output
+// stream to write the POD data structure to the file called 'filename'.
+//
+// The reverse conversion from the binary representation contained in the file to the POD
+// data structure can be achieved by binding an archive to a file input stream. Subsequently,
+// the archive can be used as an input stream to read the POD from file.
+//
+// Note that the Archive class can be bound to any kind of input or output stream (or also
+// iostream) that supports the standard write or read functions, respectively. Therefore
+// the serialization of a C++ data structure is not restricted to binary files, but allows
+// for any possible destination.
+*/
+template< typename Stream > // Type of the bound stream
+class Archive : private NonCopyable
+{
+ public:
+ //**Constructors********************************************************************************
+ /*!\name Constructors */
+ //@{
+ template< typename... Args >
+ explicit inline Archive( Args&&... args );
+
+ explicit inline Archive( Stream& stream );
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Operators***********************************************************************************
+ /*!\name Operators */
+ //@{
+ inline operator bool() const;
+ inline bool operator!() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Serialization functions*********************************************************************
+ /*!\name Serialization functions */
+ //@{
+ template< typename T >
+ EnableIf_< IsNumeric<T>, Archive& > operator<<( const T& value );
+
+ template< typename T >
+ DisableIf_< IsNumeric<T>, Archive& > operator<<( const T& value );
+
+ template< typename T >
+ EnableIf_< IsNumeric<T>, Archive& > operator>>( T& value );
+
+ template< typename T >
+ DisableIf_< IsNumeric<T>, Archive& > operator>>( T& value );
+
+ template< typename Type >
+ inline EnableIf_< IsNumeric<Type>, Archive& > write( const Type* array, size_t count );
+
+ template< typename Type >
+ inline EnableIf_< IsNumeric<Type>, Archive& > read ( Type* array, size_t count );
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline typename Stream::int_type peek() const;
+
+ inline bool good() const;
+ inline bool eof () const;
+ inline bool fail() const;
+ inline bool bad () const;
+
+ inline std::ios_base::iostate rdstate () const;
+ inline void setstate( std::ios_base::iostate state );
+ inline void clear ( std::ios_base::iostate state = std::ios_base::goodbit );
+ //@}
+ //**********************************************************************************************
+
+ private:
+
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::unique_ptr<Stream> ptr_; //!< The dynamically allocated stream resource.
+ /*!< In case no stream is bound to the archive from the outside,
+ this smart pointer handles the internally allocated stream
+ resource. */
+ Stream& stream_; //!< Reference to the bound stream.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Creating an archive with an internal stream resource.
+//
+// \param args The stream arguments.
+//
+// This function creates a new archive with an internal stream resource, which is created based
+// on the given arguments \a args.
+*/
+template< typename Stream > // Type of the bound stream
+template< typename... Args > // Types of the optional arguments
+inline Archive<Stream>::Archive( Args&&... args )
+ : ptr_ ( new Stream( std::forward<Args>( args )... ) ) // The dynamically allocated stream resource
+ , stream_( *ptr_.get() ) // Reference to the bound stream
+{}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Creating an archive with an external stream resource.
+//
+// \param stream The stream to be bound to the archive.
+//
+// This function creates a new archive with an external stream resource, which is bound to the
+// archive. Note that the stream is NOT automatically closed when the archive is destroyed.
+*/
+template< typename Stream > // Type of the bound stream
+inline Archive<Stream>::Archive( Stream& stream )
+ : ptr_ () // The dynamically allocated stream resource
+ , stream_( stream ) // Reference to the bound stream
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the current state of the archive.
+//
+// \return \a false in case an input/output error has occurred, \a true otherwise.
+//
+// This operator returns the current state of the Archive based on the state of the bound stream.
+// In case an input/output error has occurred, the operator returns \a false, otherwise it returns
+// \a true.
+*/
+template< typename Stream > // Type of the bound stream
+inline Archive<Stream>::operator bool() const
+{
+ return !stream_.fail();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the negated state of the archive.
+//
+// \return \a true in case an input/output error has occurred, \a false otherwise.
+//
+// This operator returns the negated state of the Archive based on the state of the bound stream.
+// In case an input/output error has occurred, the operator returns \a true, otherwise it returns
+// \a false.
+*/
+template< typename Stream > // Type of the bound stream
+inline bool Archive<Stream>::operator!() const
+{
+ return stream_.fail();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SERIALIZATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Serializes the given built-in data value and writes it to the archive.
+//
+// \param value The built-in data value to be serialized.
+// \return Reference to the archive.
+*/
+template< typename Stream > // Type of the bound stream
+template< typename T > // Type of the value to be serialized
+EnableIf_< IsNumeric<T>, Archive<Stream>& > Archive<Stream>::operator<<( const T& value )
+{
+ typedef typename Stream::char_type CharType;
+ stream_.write( reinterpret_cast<const CharType*>( &value ), sizeof( T ) );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Serializes the user-defined object and writes it to the archive.
+//
+// \param value The user-defined object to be serialized.
+// \return Reference to the archive.
+*/
+template< typename Stream > // Type of the bound stream
+template< typename T > // Type of the object to be serialized
+DisableIf_< IsNumeric<T>, Archive<Stream>& > Archive<Stream>::operator<<( const T& value )
+{
+ serialize( *this, value );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes a value of built-in data type and reads it from the archive.
+//
+// \param value The built-in data value to be read from the archive.
+// \return Reference to the archive.
+*/
+template< typename Stream > // Type of the bound stream
+template< typename T > // Type of the value to be deserialized
+EnableIf_< IsNumeric<T>, Archive<Stream>& > Archive<Stream>::operator>>( T& value )
+{
+ typedef typename Stream::char_type CharType;
+ stream_.read( reinterpret_cast<CharType*>( &value ), sizeof( T ) );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Deserializes an object of user-defined data type and reads it from the archive.
+//
+// \param value The user-defined object to be read from the archive.
+// \return Reference to the archive.
+*/
+template< typename Stream > // Type of the bound stream
+template< typename T > // Type of the value to be deserialized
+DisableIf_< IsNumeric<T>, Archive<Stream>& > Archive<Stream>::operator>>( T& value )
+{
+ deserialize( *this, value );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Writing an array of values to the stream.
+//
+// \param array Pointer to the first element of the array.
+// \param count The number of elements in the array.
+//
+// This function writes \a count elements of the numeric type \a Type from the given \a array
+// to the archive. Note that the function can only be used for arrays of numeric type!
+*/
+template< typename Stream > // Type of the bound stream
+template< typename Type > // Type of the array elements
+inline EnableIf_< IsNumeric<Type>, Archive<Stream>& >
+ Archive<Stream>::write( const Type* array, size_t count )
+{
+ typedef typename Stream::char_type CharType;
+ stream_.write( reinterpret_cast<const CharType*>( array ), count*sizeof(Type) );
+ return *this;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Reading an array of values from the stream.
+//
+// \param array Pointer to the first element of the array.
+// \param count The number of elements in the array.
+//
+// This function reads \a count elements of the numeric type \a Type from the archive and
+// writes them to the \a array. Note that the function can only be used for arrays of numeric
+// type. Also note that the read function does not allocate memory, but expects that \a array
+// provides storage for at least \a count elements of type \a Type!
+*/
+template< typename Stream > // Type of the bound stream
+template< typename Type > // Type of the array elements
+inline EnableIf_< IsNumeric<Type>, Archive<Stream>& >
+ Archive<Stream>::read( Type* array, size_t count )
+{
+ typedef typename Stream::char_type CharType;
+ stream_.read( reinterpret_cast<CharType*>( array ), count*sizeof(Type) );
+ return *this;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Reads the next character from the input stream without extracting it.
+//
+// \return The next character contained in the input stream.
+*/
+template< typename Stream > // Type of the bound stream
+inline typename Stream::int_type Archive<Stream>::peek() const
+{
+ return stream_.peek();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if no error has occurred, i.e. I/O operations are available.
+//
+// \return \a true in case no error has occurred, \a false otherwise.
+*/
+template< typename Stream > // Type of the bound stream
+inline bool Archive<Stream>::good() const
+{
+ return stream_.good();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if end-of-file (EOF) has been reached
+//
+// \return \a true in case end-of-file has been reached, \a false otherwise.
+*/
+template< typename Stream > // Type of the bound stream
+inline bool Archive<Stream>::eof() const
+{
+ return stream_.eof();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if a recoverable error has occurred.
+//
+// \return \a true in case a recoverable error has occurred, \a false otherwise.
+*/
+template< typename Stream > // Type of the bound stream
+inline bool Archive<Stream>::fail() const
+{
+ return stream_.fail();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Checks if a non-recoverable error has occurred.
+//
+// \return \a true in case a non-recoverable error has occurred, \a false otherwise.
+*/
+template< typename Stream > // Type of the bound stream
+inline bool Archive<Stream>::bad() const
+{
+ return stream_.bad();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current state flags settings.
+//
+// \return The current state flags settings.
+*/
+template< typename Stream > // Type of the bound stream
+inline std::ios_base::iostate Archive<Stream>::rdstate() const
+{
+ return stream_.rdstate();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Sets the state flags to a specific value.
+//
+// \param state The new error state flags setting.
+// \return void
+*/
+template< typename Stream > // Type of the bound stream
+inline void Archive<Stream>::setstate( std::ios_base::iostate state )
+{
+ stream_.setstate( state );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Clears error and eof flags.
+//
+// \param state The new error state flags setting.
+// \return void
+*/
+template< typename Stream > // Type of the bound stream
+inline void Archive<Stream>::clear( std::ios_base::iostate state )
+{
+ return stream_.clear( state );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/serialization/Serialization.h b/src/cpu/blaze/util/serialization/Serialization.h
new file mode 100644
index 00000000..8740d377
--- /dev/null
+++ b/src/cpu/blaze/util/serialization/Serialization.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/util/serialization/Serialization.h
+// \brief Serialization module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_SERIALIZATION_SERIALIZATION_H_
+#define _BLAZE_UTIL_SERIALIZATION_SERIALIZATION_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup serialization Serialization
+// \ingroup util
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/singleton/Dependency.h b/src/cpu/blaze/util/singleton/Dependency.h
new file mode 100644
index 00000000..c4d5b829
--- /dev/null
+++ b/src/cpu/blaze/util/singleton/Dependency.h
@@ -0,0 +1,135 @@
+//=================================================================================================
+/*!
+// \file blaze/util/singleton/Dependency.h
+// \brief Header file for the Dependency class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_SINGLETON_DEPENDENCY_H_
+#define _BLAZE_UTIL_SINGLETON_DEPENDENCY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <blaze/util/constraints/DerivedFrom.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Lifetime dependency on a singleton object.
+// \ingroup singleton
+//
+// The Dependency template class represents a lifetime dependency on a singleton object based
+// on the Blaze Singleton functionality. By use of the Dependency template, any class can by
+// either public or non-public inheritance or composition define a single or multiple lifetime
+// dependencies on one or several singletons, which guarantees that the singleton instance(s)
+// will be destroyed after the dependent object. The following example demonstrates both the
+// inheritance as well as the composition approach:
+
+ \code
+ // Definition of the Viewer class, which is depending on the Logger singleton instance
+
+ // #1: Approach by non-public inheritance
+ class Viewer : private Dependency<Logger>
+ {
+ ...
+ };
+
+ // #2: Approach by composition
+ class Viewer
+ {
+ private:
+ Dependency<Logger> dependency_;
+ };
+ \endcode
+*/
+template< typename T > // Type of the lifetime dependency
+class Dependency
+{
+ public:
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ inline Dependency();
+ // No explicitly declared copy constructor.
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Copy assignment operator********************************************************************
+ // No explicitly declared copy assignment operator.
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<T> dependency_; //!< Handle to the lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default constructor for Dependency.
+*/
+template< typename T > // Type of the lifetime dependency
+inline Dependency<T>::Dependency()
+ : dependency_( T::instance() ) // Handle to the lifetime dependency
+{
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, typename T::SingletonType );
+}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/singleton/Singleton.h b/src/cpu/blaze/util/singleton/Singleton.h
new file mode 100644
index 00000000..70ffe2f2
--- /dev/null
+++ b/src/cpu/blaze/util/singleton/Singleton.h
@@ -0,0 +1,1341 @@
+//=================================================================================================
+/*!
+// \file blaze/util/singleton/Singleton.h
+// \brief Header file for the Singleton class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+// //=================================================================================================
+
+#ifndef _BLAZE_UTIL_SINGLETON_SINGLETON_H_
+#define _BLAZE_UTIL_SINGLETON_SINGLETON_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <memory>
+#include <mutex>
+#include <blaze/util/constraints/DerivedFrom.h>
+#include <blaze/util/NonCopyable.h>
+#include <blaze/util/NullType.h>
+#include <blaze/util/Suffix.h>
+#include <blaze/util/TypeList.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// ::blaze NAMESPACE FORWARD DECLARATIONS
+//
+//=================================================================================================
+
+template< typename > class Dependency;
+template< typename T, typename TL, bool C > struct HasCyclicDependency;
+
+
+
+
+//=================================================================================================
+//
+// CLASS HASCYCLICDEPENDENCYHELPER
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the HasCyclicDependency class template.
+// \ingroup singleton
+//
+// Helper template class for the HasCyclicDependency template class to resolve all lifetime
+// dependencies represented by means of a dependency type list.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D // Type list of lifetime dependencies to check
+ , size_t N = Length<D>::value > // Length of the dependency type list
+struct HasCyclicDependencyHelper;
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the given
+// dependency type list is empty. In this case no cyclic lifetime dependency could be detected.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , size_t N > // Length of the dependency type list
+struct HasCyclicDependencyHelper<TL,NullType,N>
+{
+ enum : bool { value = 0 };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the length
+// of the given type list is 1.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D > // Type list of lifetime dependencies to check
+struct HasCyclicDependencyHelper<TL,D,1>
+{
+ typedef typename TypeAt<D,0>::Result D1;
+
+ enum : bool { value = HasCyclicDependency<D1,TL,Contains<TL,D1>::value>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the length
+// of the given type list is 2.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D > // Type list of lifetime dependencies to check
+struct HasCyclicDependencyHelper<TL,D,2>
+{
+ typedef typename TypeAt<D,0>::Result D1;
+ typedef typename TypeAt<D,1>::Result D2;
+
+ enum : bool { value = HasCyclicDependency<D1,TL,Contains<TL,D1>::value>::value ||
+ HasCyclicDependency<D2,TL,Contains<TL,D2>::value>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the length
+// of the given type list is 3.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D > // Type list of lifetime dependencies to check
+struct HasCyclicDependencyHelper<TL,D,3>
+{
+ typedef typename TypeAt<D,0>::Result D1;
+ typedef typename TypeAt<D,1>::Result D2;
+ typedef typename TypeAt<D,2>::Result D3;
+
+ enum : bool { value = HasCyclicDependency<D1,TL,Contains<TL,D1>::value>::value ||
+ HasCyclicDependency<D2,TL,Contains<TL,D2>::value>::value ||
+ HasCyclicDependency<D3,TL,Contains<TL,D3>::value>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the length
+// of the given type list is 4.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D > // Type list of lifetime dependencies to check
+struct HasCyclicDependencyHelper<TL,D,4>
+{
+ typedef typename TypeAt<D,0>::Result D1;
+ typedef typename TypeAt<D,1>::Result D2;
+ typedef typename TypeAt<D,2>::Result D3;
+ typedef typename TypeAt<D,3>::Result D4;
+
+ enum : bool { value = HasCyclicDependency<D1,TL,Contains<TL,D1>::value>::value ||
+ HasCyclicDependency<D2,TL,Contains<TL,D2>::value>::value ||
+ HasCyclicDependency<D3,TL,Contains<TL,D3>::value>::value ||
+ HasCyclicDependency<D4,TL,Contains<TL,D4>::value>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the length
+// of the given type list is 5.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D > // Type list of lifetime dependencies to check
+struct HasCyclicDependencyHelper<TL,D,5>
+{
+ typedef typename TypeAt<D,0>::Result D1;
+ typedef typename TypeAt<D,1>::Result D2;
+ typedef typename TypeAt<D,2>::Result D3;
+ typedef typename TypeAt<D,3>::Result D4;
+ typedef typename TypeAt<D,4>::Result D5;
+
+ enum : bool { value = HasCyclicDependency<D1,TL,Contains<TL,D1>::value>::value ||
+ HasCyclicDependency<D2,TL,Contains<TL,D2>::value>::value ||
+ HasCyclicDependency<D3,TL,Contains<TL,D3>::value>::value ||
+ HasCyclicDependency<D4,TL,Contains<TL,D4>::value>::value ||
+ HasCyclicDependency<D5,TL,Contains<TL,D5>::value>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the length
+// of the given type list is 6.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D > // Type list of lifetime dependencies to check
+struct HasCyclicDependencyHelper<TL,D,6>
+{
+ typedef typename TypeAt<D,0>::Result D1;
+ typedef typename TypeAt<D,1>::Result D2;
+ typedef typename TypeAt<D,2>::Result D3;
+ typedef typename TypeAt<D,3>::Result D4;
+ typedef typename TypeAt<D,4>::Result D5;
+ typedef typename TypeAt<D,5>::Result D6;
+
+ enum : bool { value = HasCyclicDependency<D1,TL,Contains<TL,D1>::value>::value ||
+ HasCyclicDependency<D2,TL,Contains<TL,D2>::value>::value ||
+ HasCyclicDependency<D3,TL,Contains<TL,D3>::value>::value ||
+ HasCyclicDependency<D4,TL,Contains<TL,D4>::value>::value ||
+ HasCyclicDependency<D5,TL,Contains<TL,D5>::value>::value ||
+ HasCyclicDependency<D6,TL,Contains<TL,D6>::value>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the length
+// of the given type list is 7.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D > // Type list of lifetime dependencies to check
+struct HasCyclicDependencyHelper<TL,D,7>
+{
+ typedef typename TypeAt<D,0>::Result D1;
+ typedef typename TypeAt<D,1>::Result D2;
+ typedef typename TypeAt<D,2>::Result D3;
+ typedef typename TypeAt<D,3>::Result D4;
+ typedef typename TypeAt<D,4>::Result D5;
+ typedef typename TypeAt<D,5>::Result D6;
+ typedef typename TypeAt<D,6>::Result D7;
+
+ enum : bool { value = HasCyclicDependency<D1,TL,Contains<TL,D1>::value>::value ||
+ HasCyclicDependency<D2,TL,Contains<TL,D2>::value>::value ||
+ HasCyclicDependency<D3,TL,Contains<TL,D3>::value>::value ||
+ HasCyclicDependency<D4,TL,Contains<TL,D4>::value>::value ||
+ HasCyclicDependency<D5,TL,Contains<TL,D5>::value>::value ||
+ HasCyclicDependency<D6,TL,Contains<TL,D6>::value>::value ||
+ HasCyclicDependency<D7,TL,Contains<TL,D7>::value>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependencyHelper class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependencyHelper class is selected in case the length
+// of the given type list is 8.
+*/
+template< typename TL // Type list of checked lifetime dependencies
+ , typename D > // Type list of lifetime dependencies to check
+struct HasCyclicDependencyHelper<TL,D,8>
+{
+ typedef typename TypeAt<D,0>::Result D1;
+ typedef typename TypeAt<D,1>::Result D2;
+ typedef typename TypeAt<D,2>::Result D3;
+ typedef typename TypeAt<D,3>::Result D4;
+ typedef typename TypeAt<D,4>::Result D5;
+ typedef typename TypeAt<D,5>::Result D6;
+ typedef typename TypeAt<D,6>::Result D7;
+ typedef typename TypeAt<D,7>::Result D8;
+
+ enum : bool { value = HasCyclicDependency<D1,TL,Contains<TL,D1>::value>::value ||
+ HasCyclicDependency<D2,TL,Contains<TL,D2>::value>::value ||
+ HasCyclicDependency<D3,TL,Contains<TL,D3>::value>::value ||
+ HasCyclicDependency<D4,TL,Contains<TL,D4>::value>::value ||
+ HasCyclicDependency<D5,TL,Contains<TL,D5>::value>::value ||
+ HasCyclicDependency<D6,TL,Contains<TL,D6>::value>::value ||
+ HasCyclicDependency<D7,TL,Contains<TL,D7>::value>::value ||
+ HasCyclicDependency<D8,TL,Contains<TL,D8>::value>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS HASCYCLICDEPENDENCY
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Class template for the detection of cyclic lifetime dependencies.
+// \ingroup singleton
+//
+// This class template checks the given type \a T for cyclic lifetime dependencies. In case a
+// cyclic lifetime dependency is detected, the \a value member enumeration is set to 1. Otherwise
+// it is set to 0.
+*/
+template< typename T // The type to be checked for cyclic lifetime dependencies
+ , typename TL // Type list of checked lifetime dependencies
+ , bool C=Contains<TL,T>::value > // Flag to indicate whether T is contained in TL
+struct HasCyclicDependency
+{
+ typedef typename Append<TL,T>::Result ETL;
+ enum : bool { value = HasCyclicDependencyHelper<ETL,typename T::Dependencies>::value };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the HasCyclicDependency class template.
+// \ingroup singleton
+//
+// This specialization of the HasCyclicDependency class is selected in case the given type \a T
+// is contained in the given lifetime dependency type list \a TL. In this case a cyclic lifetime
+// dependency was detected and the \a value member enumeration is set to 1.
+*/
+template< typename T // The type to be checked for cyclic lifetime dependencies
+ , typename TL > // Type list of checked lifetime dependencies
+struct HasCyclicDependency<T,TL,true>
+{
+ enum : bool { value = 1 };
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DETECT_CYCLIC_LIFETIME_DEPENDENCY CONSTRAINT
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constraint on the data type.
+// \ingroup singleton
+//
+// In case the given data type \a T is not an integral data type, a compilation error is created.
+*/
+#define BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY(T) \
+ static_assert( ( !blaze::HasCyclicDependency<T,blaze::NullType>::value ), "Cyclic dependency detected" )
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// BEFRIEND_SINGLETON MACRO
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Friendship declaration for the Singleton class template.
+// \ingroup singleton
+//
+// This macro has to be used in order to declare the Singleton functionality as friend of the
+// class deriving from Singleton.
+*/
+#define BLAZE_BEFRIEND_SINGLETON \
+ template< typename, typename, typename, typename, typename, typename, typename, typename, typename > friend class blaze::Singleton; \
+ template< typename, typename, bool > friend struct blaze::HasCyclicDependency; \
+ template< typename > friend class blaze::Dependency;
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS SINGLETON
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup singleton Singleton
+// \ingroup util
+//
+// \section motivation Motivation
+//
+// The singleton design pattern is one of the most popular and most important design patterns
+// available. It can be used to ensures that a specific class has only exactly one instance,
+// and provides a global access point to this instance [1,2]. Additionally, via the singleton
+// pattern it is posssible to manage the lifetime of objects, and especially the lifetime
+// dependencies between several objects.\n
+//
+// In the Blaze library the singleton pattern is realized by the Singleton class template.
+// Classes that are supposed to be implemented in terms of the singleton pattern only have
+// to derive from this class in order to gain all necessary characteristics of a singleton:
+//
+// - non-copyability via the NonCopyable base class
+// - a single point of access via the thread-safe [3,4] instance() member function
+// - explicit specification of lifetime dependencies; this feature provides a controlled
+// order of destruction of all singleton objects depending on a non-cyclic dependency
+// tree [4,5]
+// - compile time detection of cyclic lifetime dependencies
+//
+// The only precondition on classes deriving from the Singleton class is the availability of
+// a default constructor. In case it is not possible to instantiate the class via a default
+// constructor, i.e., in case the class has only constructors that require at least a single
+// argument, the Blaze Singleton implementation cannot be used!
+//
+//
+// \section usage Usage of the Singleton
+//
+// In order to make a specific class a singleton, two modifications have to be applied to this
+// class:
+// -# The class has to derive (publicly or non-publicly) from the Singleton class. In case the
+// class derives publicly the instance() member function, which the class inherits from the
+// Singleton class, is publicly accessible and provides a point of access to the singleton
+// instance. In case the class derives non-publicly, the instance() function is not publicly
+// accessible and therefore the class has to provide another point of access to the singleton
+// instance.\n
+// The first template parameter has to be the class itself. The following template parameters
+// define lifetime dependencies of this class, i.e., specify on which singleton instances the
+// class depends. It is possible to specify up to 8 lifetime dependencies. The example below
+// demonstrates this for the MySingleton class, which is solely depending on the Logger class,
+// which represents the core of the Blaze logging functionality.
+// -# The class needs to befriend the Singleton via the blaze::BLAZE_BEFRIEND_SINGLETON macro.
+// This macro provides a convenient way to express this friendship relation and works both in
+// case the class derives publicly or non-publicly from the Singleton class. This friendship
+// is necessary since in order to guarantee the uniqueness of the singleton instance the
+// constructor of the deriving class must be declared in a non-public section of the class
+// definition. However, in order for the Singleton class to provide the instance() function,
+// the constructor must be accessible. This is achieved by the blaze::BLAZE_BEFRIEND_SINGLETON
+// macro. The following example demonstrates this by means of the MySingleton class:
+
+ \code
+ class MySingleton : private Singleton<MySingleton,Logger>
+ {
+ private:
+ MySingleton();
+
+ ...
+ BLAZE_BEFRIEND_SINGLETON;
+ ...
+ };
+ \endcode
+
+// \section references References
+//
+// [1] E. Gamma, R. Helm, R.E. Johnson, J.M. Vlissides: Design Patterns, Addison-Wesley
+// Professional Computing Series, 2008, ISBN: 978-0-201-63361-0\n
+// [2] S. Meyers: Effective C++, Third Edition, Addison-Wesley Professional Computing Series,
+// 2008, ISBN: 978-0-321-33487-9\n
+// [3] J. Ringle: Singleton Creation the Thread-safe Way, Dr. Dobb's (www.drdobbs.com), 1999\n
+// [4] A. Alexandrescu: Modern C++ Design, Generic Programming and Design Patterns Applied,
+// Addison-Wesley, 2001, ISBN: 978-0201704310\n
+// [5] E. Gabrilovich: Controlling the Destruction Order of Singleton Objects, Dr. Dobbs
+// (www.drdobbs.com), 1999\n
+*/
+/*!\brief Base class for all lifetime managed singletons.
+// \ingroup singleton
+//
+// The Singleton class represents the base class for all lifetime managed singletons of the
+// Blaze library. Classes, which are supposed to be implemented in terms of the singleton
+// pattern, only have to derive from this class in order to gain all basic characteristics
+// of a singleton:
+//
+// - non-copyability via the NonCopyable base class
+// - a single point of access via the thread-safe instance() member function
+// - explicit specification of lifetime dependencies; this feature provides a controlled
+// order of destruction of all singleton objects depending on a non-cyclic dependency
+// tree
+// - compile time detection of cyclic lifetime dependencies
+//
+// The only prerequisite for classes deriving from the Singleton class template is the existance
+// of a default constructor. In case no default constructor is available, the Blaze singleton
+// functionality cannot be used!\n
+// When using the Singleton base class, lifetime dependencies between classes can be expressed
+// very conveniently. The following example demonstrates this by means of the MySingleton class,
+// which defines a lifetime dependency on the Logger class, which represents the core of the
+// \b Blaze logging functionality:
+
+ \code
+ // Definition of the MySingleton class
+ class MySingleton : private Singleton<MySingleton,Logger>
+ {
+ private:
+ MySingleton();
+
+ ...
+ BLAZE_BEFRIEND_SINGLETON;
+ ...
+ };
+ \endcode
+
+// In order to make a specific class a singleton, two modifications have to be applied to this
+// class:
+// -# The class has to derive (publicly or non-publicly) from the Singleton class. In case the
+// class derives publicly the instance() member function, which the class inherits from the
+// Singleton class, is publicly accessible and provides a point of access to the singleton
+// instance. In case the class derives non-publicly, the instance() function is not publicly
+// accessible and therefore the class has to provide another point of access to the singleton
+// instance.\n
+// The first template parameter has to be the class itself. The following template parameters
+// define lifetime dependencies of this class, i.e., specify on which singleton instances the
+// class depends. It is possible to specify up to 8 lifetime dependencies. The example above
+// demonstrates this for the MySingleton class, which is solely depending on the Logger class,
+// which represents the core of the Blaze logging functionality.
+// -# The class needs to befriend the Singleton via the blaze::BLAZE_BEFRIEND_SINGLETON macro.
+// This macro provides a convenient way to express this friendship relation and works both in
+// case the class derives publicly or non-publicly from the Singleton class. This friendship
+// is necessary since in order to guarantee the uniqueness of the singleton instance the
+// constructor of the deriving class must be declared in a non-public section of the class
+// definition. However, in order for the Singleton class to provide the instance() function,
+// the constructor must be accessible. This is achieved by the blaze::BLAZE_BEFRIEND_SINGLETON
+// macro.
+*/
+template< typename T // Type of the singleton (CRTP pattern)
+ , typename D1 = NullType // Type of the first lifetime dependency
+ , typename D2 = NullType // Type of the second lifetime dependency
+ , typename D3 = NullType // Type of the third lifetime dependency
+ , typename D4 = NullType // Type of the fourth lifetime dependency
+ , typename D5 = NullType // Type of the fifth lifetime dependency
+ , typename D6 = NullType // Type of the sixth lifetime dependency
+ , typename D7 = NullType // Type of the seventh lifetime dependency
+ , typename D8 = NullType > // Type of the eighth lifetime dependency
+class Singleton : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,D1,D2,D3,D4,D5,D6,D7,D8> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef BLAZE_TYPELIST_8( D1, D2, D3, D4, D5, D6, D7, D8 ) Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ : dependency1_( D1::instance() ) // Handle to the first lifetime dependency
+ , dependency2_( D2::instance() ) // Handle to the second lifetime dependency
+ , dependency3_( D3::instance() ) // Handle to the third lifetime dependency
+ , dependency4_( D4::instance() ) // Handle to the fourth lifetime dependency
+ , dependency5_( D5::instance() ) // Handle to the fifth lifetime dependency
+ , dependency6_( D6::instance() ) // Handle to the sixth lifetime dependency
+ , dependency7_( D7::instance() ) // Handle to the seventh lifetime dependency
+ , dependency8_( D8::instance() ) // Handle to the eighth lifetime dependency
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D1, typename D1::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D2, typename D2::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D3, typename D3::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D4, typename D4::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D5, typename D5::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D6, typename D6::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D7, typename D7::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D8, typename D8::SingletonType );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D1 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D2 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D3 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D4 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D5 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D6 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D7 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D8 );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<D1> dependency1_; //!< Handle to the first lifetime dependency.
+ std::shared_ptr<D2> dependency2_; //!< Handle to the second lifetime dependency.
+ std::shared_ptr<D3> dependency3_; //!< Handle to the third lifetime dependency.
+ std::shared_ptr<D4> dependency4_; //!< Handle to the fourth lifetime dependency.
+ std::shared_ptr<D5> dependency5_; //!< Handle to the fifth lifetime dependency.
+ std::shared_ptr<D6> dependency6_; //!< Handle to the sixth lifetime dependency.
+ std::shared_ptr<D7> dependency7_; //!< Handle to the seventh lifetime dependency.
+ std::shared_ptr<D8> dependency8_; //!< Handle to the eighth lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLETON SPECIALIZATION (7 LIFETIME DEPENDENCIES)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Singleton class for 7 lifetime dependencies.
+// \ingroup singleton
+//
+// This specialization of the Singleton class template is used in case 7 lifetime dependencies
+// are specified.
+*/
+template< typename T // Type of the singleton (CRTP pattern)
+ , typename D1 // Type of the first lifetime dependency
+ , typename D2 // Type of the second lifetime dependency
+ , typename D3 // Type of the third lifetime dependency
+ , typename D4 // Type of the fourth lifetime dependency
+ , typename D5 // Type of the fifth lifetime dependency
+ , typename D6 // Type of the sixth lifetime dependency
+ , typename D7 > // Type of the eighth lifetime dependency
+class Singleton<T,D1,D2,D3,D4,D5,D6,D7,NullType> : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,D1,D2,D3,D4,D5,D6,D7,NullType> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef BLAZE_TYPELIST_7( D1, D2, D3, D4, D5, D6, D7 ) Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ : dependency1_( D1::instance() ) // Handle to the first lifetime dependency
+ , dependency2_( D2::instance() ) // Handle to the second lifetime dependency
+ , dependency3_( D3::instance() ) // Handle to the third lifetime dependency
+ , dependency4_( D4::instance() ) // Handle to the fourth lifetime dependency
+ , dependency5_( D5::instance() ) // Handle to the fifth lifetime dependency
+ , dependency6_( D6::instance() ) // Handle to the sixth lifetime dependency
+ , dependency7_( D7::instance() ) // Handle to the seventh lifetime dependency
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D1, typename D1::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D2, typename D2::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D3, typename D3::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D4, typename D4::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D5, typename D5::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D6, typename D6::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D7, typename D7::SingletonType );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D1 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D2 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D3 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D4 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D5 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D6 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D7 );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<D1> dependency1_; //!< Handle to the first lifetime dependency.
+ std::shared_ptr<D2> dependency2_; //!< Handle to the second lifetime dependency.
+ std::shared_ptr<D3> dependency3_; //!< Handle to the third lifetime dependency.
+ std::shared_ptr<D4> dependency4_; //!< Handle to the fourth lifetime dependency.
+ std::shared_ptr<D5> dependency5_; //!< Handle to the fifth lifetime dependency.
+ std::shared_ptr<D6> dependency6_; //!< Handle to the sixth lifetime dependency.
+ std::shared_ptr<D7> dependency7_; //!< Handle to the seventh lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLETON SPECIALIZATION (6 LIFETIME DEPENDENCIES)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Singleton class for 6 lifetime dependencies.
+// \ingroup singleton
+//
+// This specialization of the Singleton class template is used in case 6 lifetime dependencies
+// are specified.
+*/
+template< typename T // Type of the singleton (CRTP pattern)
+ , typename D1 // Type of the first lifetime dependency
+ , typename D2 // Type of the second lifetime dependency
+ , typename D3 // Type of the third lifetime dependency
+ , typename D4 // Type of the fourth lifetime dependency
+ , typename D5 // Type of the fifth lifetime dependency
+ , typename D6 > // Type of the eighth lifetime dependency
+class Singleton<T,D1,D2,D3,D4,D5,D6,NullType,NullType> : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,D1,D2,D3,D4,D5,D6,NullType,NullType> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef BLAZE_TYPELIST_6( D1, D2, D3, D4, D5, D6 ) Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ : dependency1_( D1::instance() ) // Handle to the first lifetime dependency
+ , dependency2_( D2::instance() ) // Handle to the second lifetime dependency
+ , dependency3_( D3::instance() ) // Handle to the third lifetime dependency
+ , dependency4_( D4::instance() ) // Handle to the fourth lifetime dependency
+ , dependency5_( D5::instance() ) // Handle to the fifth lifetime dependency
+ , dependency6_( D6::instance() ) // Handle to the sixth lifetime dependency
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D1, typename D1::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D2, typename D2::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D3, typename D3::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D4, typename D4::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D5, typename D5::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D6, typename D6::SingletonType );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D1 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D2 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D3 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D4 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D5 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D6 );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<D1> dependency1_; //!< Handle to the first lifetime dependency.
+ std::shared_ptr<D2> dependency2_; //!< Handle to the second lifetime dependency.
+ std::shared_ptr<D3> dependency3_; //!< Handle to the third lifetime dependency.
+ std::shared_ptr<D4> dependency4_; //!< Handle to the fourth lifetime dependency.
+ std::shared_ptr<D5> dependency5_; //!< Handle to the fifth lifetime dependency.
+ std::shared_ptr<D6> dependency6_; //!< Handle to the sixth lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLETON SPECIALIZATION (5 LIFETIME DEPENDENCIES)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Singleton class for 5 lifetime dependencies.
+// \ingroup singleton
+//
+// This specialization of the Singleton class template is used in case 5 lifetime dependencies
+// are specified.
+*/
+template< typename T // Type of the singleton (CRTP pattern)
+ , typename D1 // Type of the first lifetime dependency
+ , typename D2 // Type of the second lifetime dependency
+ , typename D3 // Type of the third lifetime dependency
+ , typename D4 // Type of the fourth lifetime dependency
+ , typename D5 > // Type of the fifth lifetime dependency
+class Singleton<T,D1,D2,D3,D4,D5,NullType,NullType,NullType> : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,D1,D2,D3,D4,D5,NullType,NullType,NullType> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef BLAZE_TYPELIST_5( D1, D2, D3, D4, D5 ) Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ : dependency1_( D1::instance() ) // Handle to the first lifetime dependency
+ , dependency2_( D2::instance() ) // Handle to the second lifetime dependency
+ , dependency3_( D3::instance() ) // Handle to the third lifetime dependency
+ , dependency4_( D4::instance() ) // Handle to the fourth lifetime dependency
+ , dependency5_( D5::instance() ) // Handle to the fifth lifetime dependency
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D1, typename D1::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D2, typename D2::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D3, typename D3::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D4, typename D4::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D5, typename D5::SingletonType );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D1 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D2 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D3 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D4 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D5 );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<D1> dependency1_; //!< Handle to the first lifetime dependency.
+ std::shared_ptr<D2> dependency2_; //!< Handle to the second lifetime dependency.
+ std::shared_ptr<D3> dependency3_; //!< Handle to the third lifetime dependency.
+ std::shared_ptr<D4> dependency4_; //!< Handle to the fourth lifetime dependency.
+ std::shared_ptr<D5> dependency5_; //!< Handle to the fifth lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLETON SPECIALIZATION (4 LIFETIME DEPENDENCIES)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Singleton class for 4 lifetime dependencies.
+// \ingroup singleton
+//
+// This specialization of the Singleton class template is used in case 4 lifetime dependencies
+// are specified.
+*/
+template< typename T // Type of the singleton (CRTP pattern)
+ , typename D1 // Type of the first lifetime dependency
+ , typename D2 // Type of the second lifetime dependency
+ , typename D3 // Type of the third lifetime dependency
+ , typename D4 > // Type of the fourth lifetime dependency
+class Singleton<T,D1,D2,D3,D4,NullType,NullType,NullType,NullType> : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,D1,D2,D3,D4,NullType,NullType,NullType,NullType> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef BLAZE_TYPELIST_4( D1, D2, D3, D4 ) Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ : dependency1_( D1::instance() ) // Handle to the first lifetime dependency
+ , dependency2_( D2::instance() ) // Handle to the second lifetime dependency
+ , dependency3_( D3::instance() ) // Handle to the third lifetime dependency
+ , dependency4_( D4::instance() ) // Handle to the fourth lifetime dependency
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D1, typename D1::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D2, typename D2::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D3, typename D3::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D4, typename D4::SingletonType );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D1 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D2 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D3 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D4 );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<D1> dependency1_; //!< Handle to the first lifetime dependency.
+ std::shared_ptr<D2> dependency2_; //!< Handle to the second lifetime dependency.
+ std::shared_ptr<D3> dependency3_; //!< Handle to the third lifetime dependency.
+ std::shared_ptr<D4> dependency4_; //!< Handle to the fourth lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLETON SPECIALIZATION (3 LIFETIME DEPENDENCIES)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Singleton class for 3 lifetime dependencies.
+// \ingroup singleton
+//
+// This specialization of the Singleton class template is used in case 3 lifetime dependencies
+// are specified.
+*/
+template< typename T // Type of the singleton (CRTP pattern)
+ , typename D1 // Type of the first lifetime dependency
+ , typename D2 // Type of the second lifetime dependency
+ , typename D3 > // Type of the third lifetime dependency
+class Singleton<T,D1,D2,D3,NullType,NullType,NullType,NullType,NullType> : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,D1,D2,D3,NullType,NullType,NullType,NullType,NullType> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef BLAZE_TYPELIST_3( D1, D2, D3 ) Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ : dependency1_( D1::instance() ) // Handle to the first lifetime dependency
+ , dependency2_( D2::instance() ) // Handle to the second lifetime dependency
+ , dependency3_( D3::instance() ) // Handle to the third lifetime dependency
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D1, typename D1::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D2, typename D2::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D3, typename D3::SingletonType );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D1 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D2 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D3 );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<D1> dependency1_; //!< Handle to the first lifetime dependency.
+ std::shared_ptr<D2> dependency2_; //!< Handle to the second lifetime dependency.
+ std::shared_ptr<D3> dependency3_; //!< Handle to the third lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLETON SPECIALIZATION (2 LIFETIME DEPENDENCIES)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Singleton class for 2 lifetime dependencies.
+// \ingroup singleton
+//
+// This specialization of the Singleton class template is used in case 2 lifetime dependencies
+// are specified.
+*/
+template< typename T // Type of the singleton (CRTP pattern)
+ , typename D1 // Type of the first lifetime dependency
+ , typename D2 > // Type of the second lifetime dependency
+class Singleton<T,D1,D2,NullType,NullType,NullType,NullType,NullType,NullType> : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,D1,D2,NullType,NullType,NullType,NullType,NullType,NullType> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef BLAZE_TYPELIST_2( D1, D2 ) Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ : dependency1_( D1::instance() ) // Handle to the first lifetime dependency
+ , dependency2_( D2::instance() ) // Handle to the second lifetime dependency
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D1, typename D1::SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D2, typename D2::SingletonType );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D1 );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D2 );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<D1> dependency1_; //!< Handle to the first lifetime dependency.
+ std::shared_ptr<D2> dependency2_; //!< Handle to the second lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLETON SPECIALIZATION (1 LIFETIME DEPENDENCY)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Singleton class for a single lifetime dependency.
+// \ingroup singleton
+//
+// This specialization of the Singleton class template is used in case a single lifetime
+// dependency is specified.
+*/
+template< typename T // Type of the singleton (CRTP pattern)
+ , typename D1 > // Type of the lifetime dependency
+class Singleton<T,D1,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,D1,NullType,NullType,NullType,NullType,NullType,NullType,NullType> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef BLAZE_TYPELIST_1( D1 ) Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ : dependency1_( D1::instance() ) // Handle to the lifetime dependency
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( D1, typename D1::SingletonType );
+ BLAZE_DETECT_CYCLIC_LIFETIME_DEPENDENCY( D1 );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ std::shared_ptr<D1> dependency1_; //!< Handle to the lifetime dependency.
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// SINGLETON SPECIALIZATION (0 LIFETIME DEPENDENCIES)
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the Singleton class for no lifetime dependencies.
+// \ingroup singleton
+//
+// This specialization of the Singleton class template is used in case no lifetime dependencies
+// are specified.
+*/
+template< typename T > // Type of the singleton (CRTP pattern)
+class Singleton<T,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : private NonCopyable
+{
+ public:
+ //**Type definitions****************************************************************************
+ //! Type of this Singleton instance.
+ typedef Singleton<T,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> SingletonType;
+
+ //! Type list of all lifetime dependencies.
+ typedef NullType Dependencies;
+ //**********************************************************************************************
+
+ protected:
+ //**Constructor*********************************************************************************
+ /*!\brief Constructor for the Singleton class.
+ //
+ // In case a cyclic lifetime dependency is detected, a compilation error is created.
+ */
+ explicit Singleton()
+ {
+ BLAZE_CONSTRAINT_MUST_BE_DERIVED_FROM( T, SingletonType );
+ }
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\brief Destructor for the Singleton class.
+ */
+ ~Singleton()
+ {}
+ //**********************************************************************************************
+
+ public:
+ //**Instance function***************************************************************************
+ /*!\name Instance function */
+ //@{
+ static std::shared_ptr<T> instance()
+ {
+ static std::shared_ptr<T> object( new T() );
+ return object;
+ }
+ //@}
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/threadpool/Task.h b/src/cpu/blaze/util/threadpool/Task.h
new file mode 100644
index 00000000..e8e0b223
--- /dev/null
+++ b/src/cpu/blaze/util/threadpool/Task.h
@@ -0,0 +1,67 @@
+//=================================================================================================
+/*!
+// \file blaze/util/threadpool/Task.h
+// \brief Header file for the Task base class
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_THREADPOOL_TASK_H_
+#define _BLAZE_UTIL_THREADPOOL_TASK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <functional>
+
+
+namespace blaze {
+
+namespace threadpool {
+
+//=================================================================================================
+//
+// TYPE DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Handle for a single, executable task.
+// \ingroup threads
+*/
+typedef std::function<void(void)> Task;
+//*************************************************************************************************
+
+} // namespace threadpool
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/threadpool/TaskQueue.h b/src/cpu/blaze/util/threadpool/TaskQueue.h
new file mode 100644
index 00000000..2db7ae38
--- /dev/null
+++ b/src/cpu/blaze/util/threadpool/TaskQueue.h
@@ -0,0 +1,315 @@
+//=================================================================================================
+/*!
+// \file blaze/util/threadpool/TaskQueue.h
+// \brief Task queue for the thread pool
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_THREADPOOL_TASKQUEUE_H_
+#define _BLAZE_UTIL_THREADPOOL_TASKQUEUE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <deque>
+#include <blaze/util/threadpool/Task.h>
+
+
+namespace blaze {
+
+namespace threadpool {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Task queue for the thread pool.
+// \ingroup threads
+//
+// The TaskQueue class represents the internal task container of a thread pool. It uses a FIFO
+// (first in, first out) strategy to store and remove the assigned tasks.
+*/
+class TaskQueue
+{
+ private:
+ //**Type definitions****************************************************************************
+ typedef std::deque<Task> Tasks; //!< FIFO container for tasks.
+ //**********************************************************************************************
+
+ public:
+ //**Type definitions****************************************************************************
+ typedef Tasks::size_type SizeType; //!< Size type of the task queue.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline TaskQueue();
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ /*!\name Destructor */
+ //@{
+ inline ~TaskQueue();
+ //@}
+ //**********************************************************************************************
+
+ //**Get functions*******************************************************************************
+ /*!\name Get functions */
+ //@{
+ inline SizeType maxSize() const;
+ inline SizeType size() const;
+ inline bool isEmpty() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Element functions***************************************************************************
+ /*!\name Element functions */
+ //@{
+ inline void push ( Task task );
+ inline Task pop ();
+ inline void clear();
+ //@}
+ //**********************************************************************************************
+
+ //**Utility functions***************************************************************************
+ /*!\name Utility functions */
+ //@{
+ inline void swap( TaskQueue& tq ) noexcept;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ //**Member variables****************************************************************************
+ /*!\name Member variables */
+ //@{
+ Tasks tasks_; //!< FIFO container for the contained tasks.
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Default constructor for TaskQueue.
+*/
+inline TaskQueue::TaskQueue()
+ : tasks_() // FIFO container for the contained tasks
+{}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// DESTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Destructor for the TaskQueue class.
+//
+// The destructor destroys any remaining task in the task queue.
+*/
+TaskQueue::~TaskQueue()
+{
+ clear();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GET FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the maximum possible size of a task queue.
+//
+// \return The maximum possible size.
+*/
+inline TaskQueue::SizeType TaskQueue::maxSize() const
+{
+ return tasks_.max_size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the current size of the task queue.
+//
+// \return The current size.
+//
+// This function returns the number of the currently contained tasks.
+*/
+inline TaskQueue::SizeType TaskQueue::size() const
+{
+ return tasks_.size();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns \a true if the task queue has no elements.
+//
+// \return \a true if the task queue is empty, \a false if it is not.
+*/
+inline bool TaskQueue::isEmpty() const
+{
+ return tasks_.empty();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// ELEMENT FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Adding a task to the end of the task queue.
+//
+// \param task The task to be added to the end of the task queue.
+// \return void
+//
+// This function adds the given task to the end of the task queue. It runs in constant time.
+*/
+inline void TaskQueue::push( Task task )
+{
+ tasks_.push_back( task );
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the task from the front of the task queue.
+//
+// \return The first task in the task queue.
+*/
+inline Task TaskQueue::pop()
+{
+ const Task task( tasks_.front() );
+ tasks_.pop_front();
+ return task;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Removing all tasks from the task queue.
+//
+// \return void
+*/
+inline void TaskQueue::clear()
+{
+ tasks_.clear();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// UTILITY FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two task queues.
+//
+// \param tq The task queue to be swapped.
+// \return void
+// \exception no-throw guarantee.
+*/
+inline void TaskQueue::swap( TaskQueue& tq ) noexcept
+{
+ tasks_.swap( tq.tasks_ );
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GLOBAL OPERATORS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\name TaskQueue operators */
+//@{
+inline void swap( TaskQueue& a, TaskQueue& b ) noexcept;
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Swapping the contents of two task queues.
+//
+// \param a The first task queue to be swapped.
+// \param b The second task queue to be swapped.
+// \return void
+// \exception no-throw guarantee.
+*/
+inline void swap( TaskQueue& a, TaskQueue& b ) noexcept
+{
+ a.swap( b );
+}
+//*************************************************************************************************
+
+} // namespace threadpool
+
+} // namespace blaze
+
+
+#endif
diff --git a/src/cpu/blaze/util/threadpool/ThreadPool.h b/src/cpu/blaze/util/threadpool/ThreadPool.h
new file mode 100644
index 00000000..edf10ff1
--- /dev/null
+++ b/src/cpu/blaze/util/threadpool/ThreadPool.h
@@ -0,0 +1,54 @@
+//=================================================================================================
+/*!
+// \file blaze/util/threadpool/ThreadPool.h
+// \brief Threadpool module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_THREADPOOL_THREADPOOL_H_
+#define _BLAZE_UTIL_THREADPOOL_THREADPOOL_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+//! Namespace for the threadpool module.
+namespace threadpool {}
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/timing/CpuPolicy.h b/src/cpu/blaze/util/timing/CpuPolicy.h
new file mode 100644
index 00000000..518d465b
--- /dev/null
+++ b/src/cpu/blaze/util/timing/CpuPolicy.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/timing/CpuPolicy.h
+// \brief CPU timing policy for the Timer class.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TIMING_CPUPOLICY_H_
+#define _BLAZE_UTIL_TIMING_CPUPOLICY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Time.h>
+
+
+namespace blaze {
+
+namespace timing {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Timing policy for the measurement of the CPU time.
+// \ingroup timing
+//
+// The CpuPolicy class represents the timing policy for CPU time measurements that can be used
+// in combination with the Timer class template. This combination is realized with the CpuTimer
+// type definition.
+*/
+struct CpuPolicy
+{
+ public:
+ //**Timing functions****************************************************************************
+ /*!\name Timing functions */
+ //@{
+ static inline double getTimestamp();
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TIMING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns a timestamp of the current CPU time in seconds.
+//
+// \return CPU timestamp in seconds.
+*/
+inline double CpuPolicy::getTimestamp()
+{
+ return getCpuTime();
+}
+//*************************************************************************************************
+
+} // timing
+
+} // blaze
+
+#endif
diff --git a/src/cpu/blaze/util/timing/CpuTimer.h b/src/cpu/blaze/util/timing/CpuTimer.h
new file mode 100644
index 00000000..c151412d
--- /dev/null
+++ b/src/cpu/blaze/util/timing/CpuTimer.h
@@ -0,0 +1,72 @@
+//=================================================================================================
+/*!
+// \file blaze/util/timing/CpuTimer.h
+// \brief Progress timer for CPU time measurements
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TIMING_CPUTIMER_H_
+#define _BLAZE_UTIL_TIMING_CPUTIMER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/timing/CpuPolicy.h>
+#include <blaze/util/timing/Timer.h>
+
+
+namespace blaze {
+
+namespace timing {
+
+//=================================================================================================
+//
+// TYPE DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Progress timer for CPU time measurements.
+// \ingroup timing
+//
+// The CpuTimer combines the Timer class template with the CpuPolicy timing policy. It measures
+// the amount of time the measured program or code fragment uses in processing central processing
+// unit (CPU) instructions.
+*/
+typedef Timer<CpuPolicy> CpuTimer;
+//*************************************************************************************************
+
+} // timing
+
+} // blaze
+
+#endif
diff --git a/src/cpu/blaze/util/timing/Timer.h b/src/cpu/blaze/util/timing/Timer.h
new file mode 100644
index 00000000..e8bc13d3
--- /dev/null
+++ b/src/cpu/blaze/util/timing/Timer.h
@@ -0,0 +1,370 @@
+//=================================================================================================
+/*!
+// \file blaze/util/timing/Timer.h
+// \brief Progress timer for time and performance measurements
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TIMING_TIMER_H_
+#define _BLAZE_UTIL_TIMING_TIMER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <limits>
+#include <blaze/util/Time.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+namespace timing {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Progress timer for time and performance measurements.
+// \ingroup timing
+//
+// The Timer class offers timing & benchmarking functionality for all kinds of applications.
+// The following example code demonstrates the use of the WcTimer class, which combines the
+// Timer class template with the WcPolicy for wall clock time measurements, for a single time
+// measurement:
+
+ \code
+ // Creating a new wall clock timer immediately starts a new time measurement
+ WcTimer timer;
+
+ ... // Programm or code fragment to be measured
+
+ // Stopping the time measurement
+ timer.end();
+
+ // Evaluation of the measured time
+ double time = timer.last();
+ \endcode
+
+// The timer class additionally offers the functionality to start several time measurments in
+// order to evaluate minimal, maximal or average times. The next example demonstrates a possible
+// setup for such a series of time measurements:
+
+ \code
+ // Creating a new wall clock timer
+ WcTimer timer;
+
+ ... // Additional setup code
+
+ // Starting 10 wall clock time measurements
+ for( unsigned int i=0; i<10; ++i ) {
+ timer.start();
+ ... // Programm or code fragment to be measured
+ timer.end();
+ }
+
+ // After the measurements, the desired timing results can be calculated, as for instance the
+ // average wall clock time
+ double average = timer.average();
+ \endcode
+*/
+template< typename TP > // Timing policy
+class Timer
+{
+ public:
+ //**Type definitions****************************************************************************
+ typedef TP TimingPolicy; //!< Timing policy of the Timer.
+ //**********************************************************************************************
+
+ //**Constructor*********************************************************************************
+ /*!\name Constructor */
+ //@{
+ explicit inline Timer();
+ //@}
+ //**********************************************************************************************
+
+ //**Destructor**********************************************************************************
+ // No explicitly declared destructor.
+ //**********************************************************************************************
+
+ //**Timing functions****************************************************************************
+ /*!\name Timing functions */
+ //@{
+ inline void start();
+ inline void end ();
+ inline void reset();
+ //@}
+ //**********************************************************************************************
+
+ //**Get functions*******************************************************************************
+ /*!\name Get functions */
+ //@{
+ inline size_t getCounter() const;
+ //@}
+ //**********************************************************************************************
+
+ //**Time evaluation functions*******************************************************************
+ /*!\name Time evaluation functions */
+ //@{
+ inline double total() const;
+ inline double average() const;
+ inline double min() const;
+ inline double max() const;
+ inline double last() const;
+ //@}
+ //**********************************************************************************************
+
+ private:
+ size_t counter_; //!< Number of performed time measurements.
+ double start_; //!< Start of the current time measurement.
+ double end_; //!< End of the current time measurement.
+ double time_; //!< The total elapsed time of all measurements.
+ double min_; //!< The minimal time of all measurements.
+ double max_; //!< The maximal time of all measurements.
+ double last_; //!< The last measured time.
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CONSTRUCTOR
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Constructor of the Timer class.
+//
+// The creation of a new timer immediately starts a new time measurement. It is possible to
+// either restart the time measurement at a specific point of time or to continue the time
+// measurement and to end it via the end() function.
+*/
+template< typename TP > // Timing policy
+inline Timer<TP>::Timer()
+ : counter_( 0 )
+ , start_ ( 0.0 )
+ , end_ ( 0.0 )
+ , time_ ( 0.0 )
+ , min_ ( std::numeric_limits<double>::max() )
+ , max_ ( 0.0 )
+ , last_ ( 0.0 )
+{
+ // Starting the time measurement
+ start();
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TIMING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Starting a single time measurement.
+//
+// \return void
+//
+// This function starts a single time measurement.
+*/
+template< typename TP > // Timing policy
+inline void Timer<TP>::start()
+{
+ // Starting the time measurement and calculating a time stamp
+ start_ = TimingPolicy::getTimestamp();
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Ending a single time measurement.
+//
+// \return void
+//
+// This function ends the currently running time measurement and performs the necessary
+// statistical calculations.
+*/
+template< typename TP > // Timing policy
+inline void Timer<TP>::end()
+{
+ // Stopping the time measurement and calculating a time stamp
+ end_ = TimingPolicy::getTimestamp();
+
+ // Increasing the counter
+ ++counter_;
+
+ // Calculating the wallclock and CPU time
+ const double diff( end_ - start_ );
+
+ // Average time measurement
+ time_ += diff;
+
+ // Minimum time measurement
+ if( diff < min_ ) min_ = diff;
+
+ // Maximum time measurement
+ if( diff > max_ ) max_ = diff;
+
+ // Last time measurement
+ last_ = diff;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Resetting the timer.
+//
+// \return void
+//
+// This function completely resets the timer and all information on the performed time
+// measurements. In order to start a new time measurement, the start() function has to
+// be used.
+*/
+template< typename TP > // Timing policy
+inline void Timer<TP>::reset()
+{
+ counter_ = 0;
+ start_ = 0.0;
+ end_ = 0.0;
+ time_ = 0.0;
+ min_ = std::numeric_limits<double>::max();
+ max_ = 0.0;
+ last_ = 0.0;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// GET FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the total number of time measurements performed by this timer.
+//
+// \return The number of performed time measurements.
+*/
+template< typename TP > // Timing policy
+inline size_t Timer<TP>::getCounter() const
+{
+ return counter_;
+}
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TIME EVALUATION FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns the total elapsed time of all performed time measurements.
+//
+// \return The total elapsed time of all time measurements.
+*/
+template< typename TP > // Timing policy
+inline double Timer<TP>::total() const
+{
+ return time_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the average time of all performed time measurements.
+//
+// \return The average time.
+*/
+template< typename TP > // Timing policy
+inline double Timer<TP>::average() const
+{
+ return time_ / counter_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the minimal time of all performed time measurements.
+//
+// \return The minimal time.
+*/
+template< typename TP > // Timing policy
+inline double Timer<TP>::min() const
+{
+ return min_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the maximal time of all performed time measurements.
+//
+// \return The maximal time.
+*/
+template< typename TP > // Timing policy
+inline double Timer<TP>::max() const
+{
+ return max_;
+}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Returns the last measured time.
+//
+// \return The last measured time.
+*/
+template< typename TP > // Timing policy
+inline double Timer<TP>::last() const
+{
+ return last_;
+}
+//*************************************************************************************************
+
+} // timing
+
+} // blaze
+
+#endif
diff --git a/src/cpu/blaze/util/timing/Timing.h b/src/cpu/blaze/util/timing/Timing.h
new file mode 100644
index 00000000..56a09b3a
--- /dev/null
+++ b/src/cpu/blaze/util/timing/Timing.h
@@ -0,0 +1,108 @@
+//=================================================================================================
+/*!
+// \file blaze/util/timing/Timing.h
+// \brief Timing module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TIMING_TIMING_H_
+#define _BLAZE_UTIL_TIMING_TIMING_H_
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+//! Namespace for the time measurement module.
+namespace timing {}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\defgroup timing Time measurement
+// \ingroup util
+//
+// \image html clock.png
+// \image latex clock.eps "Timing submodule" width=200pt
+//
+// The timing submodule offers the necessary functionality for timing and benchmarking purposes.
+// The central element of the timing module is the Timer class. Depending on a chosen timing
+// policy, this class offers the possibility to measure both single times and time series. In
+// order to make time measurement as easy as possible, the Blaze library offers the two classes
+// WcTimer and CpuTimer (both using the Timer class) to measure both wall clock and CPU time.
+// The following example gives an impression on how time measurement for a single time works
+// with the the Blaze library. Note that in this example the WcTimer could be easily replaced
+// with the CpuTimer if instead of the wall clock time the CPU time was to be measured.
+
+ \code
+ // Creating a new wall clock timer immediately starts a new time measurement
+ WcTimer timer;
+
+ ... // Programm or code fragment to be measured
+
+ // Stopping the time measurement
+ timer.end();
+
+ // Evaluation of the measured time
+ double time = timer.last();
+ \endcode
+
+// As already mentioned, it is also possible to start several time measurements with a single
+// timer to evaluate for instance the minimal, the maximal or the average time of a specific
+// task. The next example demonstrates a possible setup for such a series of time measurements:
+
+ \code
+ // Creating a new wall clock timer
+ WcTimer timer;
+
+ ... // Additional setup code
+
+ // Starting 10 wall clock time measurements
+ for( unsigned int i=0; i<10; ++i ) {
+ timer.start();
+ ... // Programm or code fragment to be measured
+ timer.end();
+ }
+
+ // After the measurements, the desired timing results can be calculated, as for instance the
+ // average wall clock time
+ double average = timer.average();
+ \endcode
+*/
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/timing/WcPolicy.h b/src/cpu/blaze/util/timing/WcPolicy.h
new file mode 100644
index 00000000..17459896
--- /dev/null
+++ b/src/cpu/blaze/util/timing/WcPolicy.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/timing/WcPolicy.h
+// \brief Wall clock timing policy for the Timer class.
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TIMING_WCPOLICY_H_
+#define _BLAZE_UTIL_TIMING_WCPOLICY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Time.h>
+
+
+namespace blaze {
+
+namespace timing {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Timing policy for the measurement of the wall clock time.
+// \ingroup timing
+//
+// The WcPolicy class represents the timing policy for wall clock time measurements that can be
+// used in combination with the Timer class template. This combination is realized with the WcTimer
+// type definition.
+*/
+struct WcPolicy
+{
+ public:
+ //**Timing functions****************************************************************************
+ /*!\name Timing functions */
+ //@{
+ static inline double getTimestamp();
+ //@}
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// TIMING FUNCTIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Returns a timestamp of the current wall clock time in seconds.
+//
+// \return Wall clock timestamp in seconds.
+*/
+inline double WcPolicy::getTimestamp()
+{
+ return getWcTime();
+}
+//*************************************************************************************************
+
+} // timing
+
+} // blaze
+
+#endif
diff --git a/src/cpu/blaze/util/timing/WcTimer.h b/src/cpu/blaze/util/timing/WcTimer.h
new file mode 100644
index 00000000..8cf1fb06
--- /dev/null
+++ b/src/cpu/blaze/util/timing/WcTimer.h
@@ -0,0 +1,73 @@
+//=================================================================================================
+/*!
+// \file blaze/util/timing/WcTimer.h
+// \brief Progress timer for wall clock time measurements
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TIMING_WCTIMER_H_
+#define _BLAZE_UTIL_TIMING_WCTIMER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/timing/Timer.h>
+#include <blaze/util/timing/WcPolicy.h>
+
+
+namespace blaze {
+
+namespace timing {
+
+//=================================================================================================
+//
+// TYPE DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Progress timer for wall clock time measurements.
+// \ingroup timing
+//
+// The WcTimer combines the Timer class template with the WcPolicy timing policy. It measures
+// the amount of "wall clock" time elapsing for the processing of a programm or code fragment.
+// In contrast to the measurement of CPU time, the wall clock time also contains waiting times
+// such as input/output operations.
+*/
+typedef Timer<WcPolicy> WcTimer;
+//*************************************************************************************************
+
+} // timing
+
+} // blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/AddCV.h b/src/cpu/blaze/util/typetraits/AddCV.h
new file mode 100644
index 00000000..c0c458fd
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/AddCV.h
@@ -0,0 +1,101 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/AddCV.h
+// \brief Header file for the AddCV type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ADDCV_H_
+#define _BLAZE_UTIL_TYPETRAITS_ADDCV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of a top level 'const' and 'volatile' qualifier.
+// \ingroup type_traits
+//
+// The AddCV type trait adds both a top level 'const' and 'volatile' qualifier to the given
+// type \a T.
+
+ \code
+ blaze::AddCV<int>::Type // Results in 'int const volatile'
+ blaze::AddCV<int*>::Type // Results in 'int* const volatile'
+ blaze::AddCV<int&>::Type // Results in 'int&'
+ blaze::AddCV<int const>::Type // Results in 'int const volatile'
+ blaze::AddCV<int volatile>::Type // Results in 'int const volatile'
+ \endcode
+*/
+template< typename T >
+struct AddCV
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::add_cv<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the AddCV type trait.
+// \ingroup type_traits
+//
+// The AddCV_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the AddCV class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename AddCV<T>::Type;
+ using Type2 = AddCV_<T>;
+ \endcode
+*/
+template< typename T >
+using AddCV_ = typename AddCV<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/AddConst.h b/src/cpu/blaze/util/typetraits/AddConst.h
new file mode 100644
index 00000000..033a7357
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/AddConst.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/AddConst.h
+// \brief Header file for the AddConst type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ADDCONST_H_
+#define _BLAZE_UTIL_TYPETRAITS_ADDCONST_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of a top level 'const' qualifier.
+// \ingroup type_traits
+//
+// The AddConst type trait adds a top level 'const' qualifier to the given type \a T.
+
+ \code
+ blaze::AddConst<int>::Type // Results in 'int const'
+ blaze::AddConst<int*>::Type // Results in 'int* const'
+ blaze::AddConst<int&>::Type // Results in 'int&'
+ blaze::AddConst<int const>::Type // Results in 'int const'
+ blaze::AddConst<int volatile>::Type // Results in 'int volatile const'
+ \endcode
+*/
+template< typename T >
+struct AddConst
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::add_const<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the AddConst type trait.
+// \ingroup type_traits
+//
+// The AddConst_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the AddConst class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename AddConst<T>::Type;
+ using Type2 = AddConst_<T>;
+ \endcode
+*/
+template< typename T >
+using AddConst_ = typename AddConst<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/AddPointer.h b/src/cpu/blaze/util/typetraits/AddPointer.h
new file mode 100644
index 00000000..4f7c46da
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/AddPointer.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/AddPointer.h
+// \brief Header file for the AddPointer type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ADDPOINTER_H_
+#define _BLAZE_UTIL_TYPETRAITS_ADDPOINTER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of a top level pointer.
+// \ingroup type_traits
+//
+// The AddPointer type trait adds a top level pointer to the given type \a T. It has the same
+// effect as \c blaze::RemovePointer<T>::Type*.
+
+ \code
+ blaze::AddPointer<int>::Type // Results in 'int*'
+ blaze::AddPointer<int const>::Type // Results in 'int const*'
+ blaze::AddPointer<int*>::Type // Results in 'int**'
+ blaze::AddPointer<int*&>::Type // Results in 'int**'
+ \endcode
+*/
+template< typename T >
+struct AddPointer
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::add_pointer<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the AddPointer type trait.
+// \ingroup type_traits
+//
+// The AddPointer_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the AddPointer class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename AddPointer<T>::Type;
+ using Type2 = AddPointer_<T>;
+ \endcode
+*/
+template< typename T >
+using AddPointer_ = typename AddPointer<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/AddReference.h b/src/cpu/blaze/util/typetraits/AddReference.h
new file mode 100644
index 00000000..a19af78b
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/AddReference.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/AddReference.h
+// \brief Header file for the AddReference type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ADDREFERENCE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ADDREFERENCE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of a top level reference.
+// \ingroup type_traits
+//
+// In case the given type \a T is not a reference type, the AddReference type trait adds a top
+// level reference to the given type \a T. Else the resulting type \a Type is \a T.
+
+ \code
+ blaze::AddReference<int>::Type // Results in 'int&'
+ blaze::AddReference<int const&>::Type // Results in 'int const&'
+ blaze::AddReference<int*>::Type // Results in 'int*&'
+ blaze::AddReference<int*&>::Type // Results in 'int*&'
+ \endcode
+*/
+template< typename T >
+struct AddReference
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::add_lvalue_reference<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the AddReference type trait.
+// \ingroup type_traits
+//
+// The AddReference_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the AddReference class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename AddReference<T>::Type;
+ using Type2 = AddReference_<T>;
+ \endcode
+*/
+template< typename T >
+using AddReference_ = typename AddReference<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/AddVolatile.h b/src/cpu/blaze/util/typetraits/AddVolatile.h
new file mode 100644
index 00000000..9bd7abc5
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/AddVolatile.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/AddVolatile.h
+// \brief Header file for the AddVolatile type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ADDVOLATILE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ADDVOLATILE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Addition of a top level 'volatile' qualifier.
+// \ingroup type_traits
+//
+// The AddVolatile type trait adds a top level 'volatile' qualifier to the given type \a T.
+
+ \code
+ blaze::AddVolatile<int>::Type // Results in 'int volatile'
+ blaze::AddVolatile<int*>::Type // Results in 'int* volatile'
+ blaze::AddVolatile<int&>::Type // Results in 'int&'
+ blaze::AddVolatile<int volatile>::Type // Results in 'int volatile'
+ blaze::AddVolatile<int const>::Type // Results in 'int const volatile'
+ \endcode
+*/
+template< typename T >
+struct AddVolatile
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::add_volatile<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the AddVolatile type trait.
+// \ingroup type_traits
+//
+// The AddVolatile_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the AddVolatile class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename AddVolatile<T>::Type;
+ using Type2 = AddVolatile_<T>;
+ \endcode
+*/
+template< typename T >
+using AddVolatile_ = typename AddVolatile<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/AlignmentOf.h b/src/cpu/blaze/util/typetraits/AlignmentOf.h
new file mode 100644
index 00000000..5f5adac8
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/AlignmentOf.h
@@ -0,0 +1,249 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/AlignmentOf.h
+// \brief Header file for the AlignmentOf type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ALIGNMENTOF_H_
+#define _BLAZE_UTIL_TYPETRAITS_ALIGNMENTOF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/Complex.h>
+#include <blaze/util/typetraits/IsVectorizable.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the AlignmentOf type trait.
+// \ingroup type_traits
+*/
+template< typename T >
+struct AlignmentOfHelper
+{
+ private:
+ //**********************************************************************************************
+ static constexpr size_t defaultAlignment = std::alignment_of<T>::value;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+#if BLAZE_MIC_MODE
+ static constexpr size_t value = ( IsVectorizable<T>::value )?( 64UL ):( defaultAlignment );
+#elif BLAZE_AVX2_MODE
+ static constexpr size_t value = ( IsVectorizable<T>::value )?( 32UL ):( defaultAlignment );
+#elif BLAZE_SSE2_MODE
+ static constexpr size_t value = ( IsVectorizable<T>::value )?( 16UL ):( defaultAlignment );
+#else
+ static constexpr size_t value = defaultAlignment;
+#endif
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of \c AlignmentOfHelper for 'float'.
+// \ingroup type_traits
+*/
+template<>
+struct AlignmentOfHelper<float>
+{
+ public:
+ //**********************************************************************************************
+#if BLAZE_MIC_MODE
+ static constexpr size_t value = 64UL;
+#elif BLAZE_AVX_MODE
+ static constexpr size_t value = 32UL;
+#elif BLAZE_SSE_MODE
+ static constexpr size_t value = 16UL;
+#else
+ static constexpr size_t value = std::alignment_of<float>::value;
+#endif
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of \c AlignmentOfHelper for 'double'.
+// \ingroup type_traits
+*/
+template<>
+struct AlignmentOfHelper<double>
+{
+ public:
+ //**********************************************************************************************
+#if BLAZE_MIC_MODE
+ static constexpr size_t value = 64UL;
+#elif BLAZE_AVX_MODE
+ static constexpr size_t value = 32UL;
+#elif BLAZE_SSE_MODE
+ static constexpr size_t value = 16UL;
+#else
+ static constexpr size_t value = std::alignment_of<double>::value;
+#endif
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of \c AlignmentOfHelper for 'complex<float>'.
+// \ingroup type_traits
+*/
+template<>
+struct AlignmentOfHelper< complex<float> >
+{
+ public:
+ //**********************************************************************************************
+#if BLAZE_MIC_MODE
+ static constexpr size_t value = 64UL;
+#elif BLAZE_AVX_MODE
+ static constexpr size_t value = 32UL;
+#elif BLAZE_SSE_MODE
+ static constexpr size_t value = 16UL;
+#else
+ static constexpr size_t value = std::alignment_of< complex<float> >::value;
+#endif
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of \c AlignmentOfHelper for 'complex<double>'.
+// \ingroup type_traits
+*/
+template<>
+struct AlignmentOfHelper< complex<double> >
+{
+ public:
+ //**********************************************************************************************
+#if BLAZE_MIC_MODE
+ static constexpr size_t value = 64UL;
+#elif BLAZE_AVX_MODE
+ static constexpr size_t value = 32UL;
+#elif BLAZE_SSE_MODE
+ static constexpr size_t value = 16UL;
+#else
+ static constexpr size_t value = std::alignment_of< complex<double> >::value;
+#endif
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Evaluation of the required alignment of the given data type.
+// \ingroup type_traits
+//
+// The AlignmentOf type trait template evaluates the required alignment for the given data type.
+// For instance, for fundamental data types that can be vectorized via SSE or AVX instructions,
+// the proper alignment is 16 or 32 bytes, respectively. For all other data types, a multiple
+// of the alignment chosen by the compiler is returned. The evaluated alignment can be queried
+// via the nested \a value member.
+
+ \code
+ AlignmentOf<unsigned int>::value // Evaluates to 32 if AVX2 is available, to 16 if only
+ // SSE2 is available, and a multiple of the alignment
+ // chosen by the compiler otherwise.
+ AlignmentOf<double>::value // Evaluates to 32 if AVX is available, to 16 if only
+ // SSE is available, and a multiple of the alignment
+ // chosen by the compiler otherwise.
+ \endcode
+*/
+template< typename T >
+struct AlignmentOf : IntegralConstant<size_t,AlignmentOfHelper<T>::value>
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of \c AlignmentOf for 'const' data types.
+// \ingroup type_traits
+*/
+template< typename T >
+struct AlignmentOf< const T > : IntegralConstant<size_t,AlignmentOfHelper<T>::value>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of \c AlignmentOf for 'volatile' data types.
+// \ingroup type_traits
+*/
+template< typename T >
+struct AlignmentOf< volatile T > : IntegralConstant<size_t,AlignmentOfHelper<T>::value>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of \c AlignmentOf for 'const volatile' data types.
+// \ingroup type_traits
+*/
+template< typename T >
+struct AlignmentOf< const volatile T > : IntegralConstant<size_t,AlignmentOfHelper<T>::value>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/All.h b/src/cpu/blaze/util/typetraits/All.h
new file mode 100644
index 00000000..7265125b
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/All.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/All.h
+// \brief Header file for the All type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ALL_H_
+#define _BLAZE_UTIL_TYPETRAITS_ALL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/And.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// This type trait determines whether the given type trait \a TypeTrait evaluates to \a true for
+// all given types \a Ts. If the expression
+
+ \code
+ And< TypeTrait<Ts>... >::value
+ \endcode
+
+// evaluates to \a true, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType. Examples:
+
+ \code
+ blaze::All< IsIntegral, int, short, long >::value // Evaluates to 'true'
+ blaze::All< IsPointer, int*, float* >::Type // Results in TrueType
+ blaze::All< IsCharacter, char, signed char, wchar_t > // Is derived from TrueType
+ blaze::All< IsIntegral, int, float, double >::value // Evaluates to 'false'
+ blaze::All< IsPointer, int*, float& >::Type // Results in FalseType
+ blaze::All< IsCharacter, char, signed int, wchar_t > // Is derived from FalseType
+ \endcode
+*/
+template< template< typename > class TypeTrait, typename... Ts >
+struct All : public BoolConstant< And< TypeTrait<Ts>... >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/Any.h b/src/cpu/blaze/util/typetraits/Any.h
new file mode 100644
index 00000000..bf3945fb
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/Any.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/Any.h
+// \brief Header file for the Any type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ANY_H_
+#define _BLAZE_UTIL_TYPETRAITS_ANY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/Or.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// This type trait determines whether the given type trait \a TypeTrait evaluates to \a true for
+// at least one of the given types \a Ts. If the expression
+
+ \code
+ Or< TypeTrait<Ts>... >::value
+ \endcode
+
+// evaluates to \a true, the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType. Examples:
+
+ \code
+ blaze::Any< IsIntegral, int, float >::value // Evaluates to 'true'
+ blaze::Any< IsPointer, int&, float* >::Type // Results in TrueType
+ blaze::Any< IsCharacter, float, wchar_t > // Is derived from TrueType
+ blaze::Any< IsIntegral, float, double >::value // Evaluates to 'false'
+ blaze::Any< IsPointer, int, float& >::Type // Results in FalseType
+ blaze::Any< IsCharacter, int, double > // Is derived from FalseType
+ \endcode
+*/
+template< template< typename > class TypeTrait, typename... Ts >
+struct Any : public BoolConstant< Or< TypeTrait<Ts>... >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/CommonType.h b/src/cpu/blaze/util/typetraits/CommonType.h
new file mode 100644
index 00000000..7689e297
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/CommonType.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/CommonType.h
+// \brief Header file for the CommonType type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_COMMONTYPE_H_
+#define _BLAZE_UTIL_TYPETRAITS_COMMONTYPE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Deduction of a type common to several types.
+// \ingroup type_traits
+//
+// The CommonType type trait deduces the result type of a mixed-mode arithmetic expression between
+// all types T..., that is the type all T... can be implicitly converted to. Note that cv and
+// reference qualifiers are generally ignored.
+
+ \code
+ blaze::CommonType<short,int>::Type // Results in 'int'
+ blaze::CommonType<const double,int&>::Type // Results in 'double'
+ blaze::CommonType<char&, volatile int, const float>::Type // Results in 'float'
+ \endcode
+*/
+template< typename... T >
+struct CommonType
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::common_type<T...>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the CommonType type trait.
+// \ingroup type_traits
+//
+// The CommonType_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the CommonType class template. For instance, given the types \a T1 and \a T2 the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename CommonType<T1,T2>::Type;
+ using Type2 = CommonType_<T1,T2>;
+ \endcode
+*/
+template< typename... T >
+using CommonType_ = typename CommonType<T...>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/Decay.h b/src/cpu/blaze/util/typetraits/Decay.h
new file mode 100644
index 00000000..b36db732
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/Decay.h
@@ -0,0 +1,103 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/Decay.h
+// \brief Header file for the Decay type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_DECAY_H_
+#define _BLAZE_UTIL_TYPETRAITS_DECAY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Applies the type conversions for by-value function arguments.
+// \ingroup type_traits
+//
+// This type trait applies the type conversions that are used for by-value function arguments.
+// This conversions include lvalue-to-rvalue, array-to-pointer, and function-to-pointer implicit
+// conversions to the type \c T, and the removal of top level cv-qualifiers.
+
+ \code
+ blaze::Decay<int>::Type // Results in 'int'
+ blaze::Decay<int&>::Type // Results in 'int'
+ blaze::Decay<int&&>::Type // Results in 'int'
+ blaze::Decay<const int&>::Type // Results in 'int'
+ blaze::Decay<int[2]>::Type // Results in 'int*'
+ blaze::Decay<int(int)>::Type // Results in 'int(*)(int)'
+ \endcode
+*/
+template< typename T >
+struct Decay
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::decay<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the Decay type trait.
+// \ingroup type_traits
+//
+// The Decay_ alias declaration provides a convenient shortcut to access the nested \a Type of
+// the Decay class template. For instance, given the type \a T the following two type definitions
+// are identical:
+
+ \code
+ using Type1 = typename Decay<T>::Type;
+ using Type2 = Decay_<T>;
+ \endcode
+*/
+template< typename T >
+using Decay_ = typename Decay<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/Extent.h b/src/cpu/blaze/util/typetraits/Extent.h
new file mode 100644
index 00000000..fed1a259
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/Extent.h
@@ -0,0 +1,127 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/Extent.h
+// \brief Header file for the Extent type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_EXTENT_H_
+#define _BLAZE_UTIL_TYPETRAITS_EXTENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for the size of array bounds.
+// \ingroup type_traits
+//
+// Via this type trait it is possible to query at compile time for the size of a particular
+// array extent. In case the given template argument is an array type with a rank greater
+// than N, the \a value member constant is set to the number of elements of the N'th array
+// dimension. In all other cases, and especially in case the N'th array dimension is
+// incomplete, \a value is set to 0.
+
+ \code
+ blaze::Extent< int[4], 0 >::value // Evaluates to 4
+ blaze::Extent< int[2][3][4], 0 >::value // Evaluates to 2
+ blaze::Extent< int[2][3][4], 1 >::value // Evaluates to 3
+ blaze::Extent< int[2][3][4], 2 >::value // Evaluates to 4
+ blaze::Extent< int[][2], 0 >::value // Evaluates to 0
+ blaze::Extent< int[][2], 1 >::value // Evaluates to 2
+ blaze::Extent< int*, 0 >::value // Evaluates to 0
+ blaze::Extent< std::vector<int>, 0 >::value // Evaluates to 0 (std::vector is NOT an array type)
+ \endcode
+*/
+template< typename T, unsigned int N >
+struct Extent
+ : public IntegralConstant<unsigned int,0U>
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Partial specialization of the Extent type trait for empty array extents.
+template< typename T, unsigned int N >
+struct Extent<T[],N>
+ : public IntegralConstant<unsigned int,Extent<T,N-1U>::value>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Partial specialization of the Extent type trait for non-empty array extents.
+template< typename T, unsigned int N, unsigned int E >
+struct Extent<T[E],N>
+ : public IntegralConstant<unsigned int,Extent<T,N-1U>::value>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Terminating partial specialization of the Extent type trait for empty array extents.
+template< typename T >
+struct Extent<T[],0UL>
+ : public IntegralConstant<unsigned int,0U>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Terminating partial specialization of the Extent type trait for non-empty array extents.
+template< typename T, unsigned int E >
+struct Extent<T[E],0U>
+ : public IntegralConstant<unsigned int,E>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/GetMemberType.h b/src/cpu/blaze/util/typetraits/GetMemberType.h
new file mode 100644
index 00000000..da222a51
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/GetMemberType.h
@@ -0,0 +1,116 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/GetMemberType.h
+// \brief Header file for the GetMemberType type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_GETMEMBERTYPE_H_
+#define _BLAZE_UTIL_TYPETRAITS_GETMEMBERTYPE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/typetraits/HasMember.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// MACRO DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Macro for the creation of a type trait to acquire member types.
+// \ingroup math_type_traits
+//
+// This macro creates the definition of a type trait \a TYPE_TRAIT_NAME that can determine a
+// specified member type of a given type. The first macro parameter \a TYPE_TRAIT_NAME specifies
+// the resulting name of the type trait. The second parameter \a MEMBER_NAME specifies the name
+// of the member type to be acquired and the third parameter \a FALLBACK_TYPE specifies the type
+// to acquire in case the given type doesn't contain the specified member type. The following
+// example demonstrates the use of the macro and the resulting type trait:
+
+ \code
+ struct MyType1 {
+ typedef float ElementType;
+ };
+
+ struct MyType2 {
+ typedef double ElementType;
+ };
+
+ struct MyType3 {};
+
+ BLAZE_CREATE_GET_TYPE_MEMBER_TYPE_TRAIT( GetElementType, ElementType, int );
+
+ GetElementType<MyType1>::Type // Results in 'float'
+ GetElementType<MyType2>::Type // Results in 'double'
+ GetElementType<MyType3>::Type // Results in 'int'
+ \endcode
+
+// The macro results in the definition of a new class with the specified name \a TYPE_TRAIT_NAME
+// within the current namespace. This may cause name collisions with any other entity called
+// \a TYPE_TRAIT_NAME in the same namespace. Therefore it is advisable to create the type trait
+// as locally as possible to minimize the probability of name collisions. Note however that the
+// macro cannot be used within function scope since a template declaration cannot appear at
+// block scope.
+//
+// Please note that due to an error in the Intel compilers prior to version 14.0 the type trait
+// generated from this macro does NOT work properly, i.e. will not correctly determine whether
+// the specified element is a type member of the given type!
+*/
+#define BLAZE_CREATE_GET_TYPE_MEMBER_TYPE_TRAIT( TYPE_TRAIT_NAME, MEMBER_NAME, FALLBACK_TYPE ) \
+ \
+template< typename Type1233 > \
+struct TYPE_TRAIT_NAME \
+{ \
+ private: \
+ struct SUCCESS { typedef typename Type1233::MEMBER_NAME Type; }; \
+ struct FAILURE { typedef FALLBACK_TYPE Type; }; \
+ \
+ BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( LOCAL_TYPE_TRAIT, MEMBER_NAME ); \
+ \
+ public: \
+ using Type = typename blaze::If< LOCAL_TYPE_TRAIT<Type1233> \
+ , SUCCESS \
+ , FAILURE \
+ >::Type::Type; \
+};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/HasMember.h b/src/cpu/blaze/util/typetraits/HasMember.h
new file mode 100644
index 00000000..113a30e6
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/HasMember.h
@@ -0,0 +1,284 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/HasMember.h
+// \brief Header file for the HasMember type traits
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_HASMEMBER_H_
+#define _BLAZE_UTIL_TYPETRAITS_HASMEMBER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+
+
+
+
+//=================================================================================================
+//
+// MACRO DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Macro for the creation of a type trait for compile time checks for member data and functions.
+// \ingroup math_type_traits
+//
+// This macro creates the definition of a type trait \a TYPE_TRAIT_NAME that can determine whether
+// the specified element \a MEMBER_NAME is a data or function member of a given type. The following
+// example demonstrates the use of the macro and the resulting type trait:
+
+ \code
+ class MyType {
+ public:
+ void publicCompute();
+
+ private:
+ void privateCompute();
+
+ int value_;
+ };
+
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasPublicCompute , publicCompute );
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasPrivateCompute, privateCompute );
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasValue , value_ );
+
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasEvaluate , evalute );
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasDetermine, determine );
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasData , data_ );
+
+ HasPublicCompute<MyType>::value // Evaluates to 'true'
+ HasPrivateCompute<MyType>::Type // Results in TrueType
+ HasValue<MyType> // Is derived from TrueType
+ HasEvaluate<MyType>::value // Evaluates to 'false'
+ HasDetermine<MyType>::Type // Results in FalseType
+ HasData<MyType> // Is derived from FalseType
+ \endcode
+
+// The macro results in the definition of a new class with the specified name \a TYPE_TRAIT_NAME
+// within the current namespace. This may cause name collisions with any other entity called
+// \a TYPE_TRAIT_NAME in the same namespace. Therefore it is advisable to create the type trait
+// as locally as possible to minimize the probability of name collisions. Note however that the
+// macro cannot be used within function scope since a template declaration cannot appear at
+// block scope.
+*/
+#define BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( TYPE_TRAIT_NAME, MEMBER_NAME ) \
+ \
+template < typename TYPE1230 > \
+class TYPE_TRAIT_NAME##HELPER \
+{ \
+ private: \
+ using Yes = char[1]; \
+ using No = char[2]; \
+ \
+ struct Base {}; \
+ \
+ template< typename U, U > struct Check; \
+ \
+ struct Fallback { int MEMBER_NAME; }; \
+ \
+ struct Derived \
+ : blaze::If< blaze::IsBuiltin<TYPE1230>, Base, TYPE1230 >::Type \
+ , Fallback \
+ {}; \
+ \
+ template < typename U > \
+ static No& test( Check<int Fallback::*, &U::MEMBER_NAME>* ); \
+ \
+ template < typename U > \
+ static Yes& test( ... ); \
+ \
+ public: \
+ enum : bool { value = ( sizeof( test<Derived>( nullptr ) ) == sizeof( Yes ) ) }; \
+}; \
+ \
+template< typename TYPE1230 > \
+struct TYPE_TRAIT_NAME \
+ : public blaze::BoolConstant< TYPE_TRAIT_NAME##HELPER<TYPE1230>::value > \
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Macro for the creation of a type trait for compile time checks for member types.
+// \ingroup math_type_traits
+//
+// This macro creates the definition of a type trait \a TYPE_TRAIT_NAME that can determine whether
+// the specified element \a MEMBER_NAME is a type member of a given type. The following example
+// demonstrates the use of the macro and the resulting type trait:
+
+ \code
+ class MyType {
+ public:
+ typedef int PublicType;
+
+ protected:
+ typedef float ProtectedType;
+
+ private:
+ typedef double PrivateType;
+ };
+
+ BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( HasPublicType , PublicType );
+ BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( HasProtectedType, ProtectedType );
+ BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( HasPrivateType , PrivateType );
+
+ BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( HasValueType , ValueType );
+ BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( HasElementType, ElementTypeType );
+ BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( HasDataType , DataType );
+
+ HasPublicType<MyType>::value // Evaluates to 'true'
+ HasProtectedType<MyType>::Type // Results in TrueType
+ HasPrivateType<MyType> // Is derived from TrueType
+ HasValueType<MyType>::value // Evaluates to 'false'
+ HasElementType<MyType>::Type // Results in FalseType
+ HasDataType<MyType> // Is derived from FalseType
+ \endcode
+
+// The macro results in the definition of a new class with the specified name \a TYPE_TRAIT_NAME
+// within the current namespace. This may cause name collisions with any other entity called
+// \a TYPE_TRAIT_NAME in the same namespace. Therefore it is advisable to create the type trait
+// as locally as possible to minimize the probability of name collisions. Note however that the
+// macro cannot be used within function scope since a template declaration cannot appear at
+// block scope.
+//
+// Please note that due to an error in the Intel compilers prior to version 14.0 the type trait
+// generated from this macro does NOT work properly, i.e. will not correctly determine whether
+// the specified element is a type member of the given type!
+*/
+#define BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( TYPE_TRAIT_NAME, MEMBER_NAME ) \
+ \
+template < typename TYPE1231 > \
+struct TYPE_TRAIT_NAME##HELPER \
+{ \
+ private: \
+ using Yes = char[1]; \
+ using No = char[2]; \
+ \
+ struct Base {}; \
+ \
+ struct Fallback { struct MEMBER_NAME { }; }; \
+ \
+ struct Derived \
+ : blaze::If< blaze::IsBuiltin<TYPE1231>, Base, TYPE1231 >::Type \
+ , Fallback \
+ {}; \
+ \
+ template < class U > \
+ static No& test( typename U::MEMBER_NAME* ); \
+ \
+ template < typename U > \
+ static Yes& test( U* ); \
+ \
+ public: \
+ enum : bool { value = ( sizeof( test<Derived>( nullptr ) ) == sizeof( Yes ) ) }; \
+}; \
+ \
+template< typename TYPE1231 > \
+struct TYPE_TRAIT_NAME \
+ : public blaze::BoolConstant< TYPE_TRAIT_NAME##HELPER<TYPE1231>::value > \
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Macro for the creation of a type trait for compile time checks for members.
+// \ingroup math_type_traits
+//
+// This macro creates the definition of a type trait \a TYPE_TRAIT_NAME that can determine whether
+// the specified element \a MEMBER_NAME is a data, function, or type member of a given type. The
+// following example demonstrates the use of the macro and the resulting type trait:
+
+ \code
+ class MyType {
+ public:
+ void publicCompute();
+
+ protected:
+ typedef float ProtectedType;
+
+ private:
+ int value_;
+ };
+
+ BLAZE_CREATE_HAS_MEMBER_TYPE_TRAIT( HasCompute , publicCompute );
+ BLAZE_CREATE_HAS_MEMBER_TYPE_TRAIT( HasProtectedType, ProtectedType );
+ BLAZE_CREATE_HAS_MEMBER_TYPE_TRAIT( HasValue , value_ );
+
+ BLAZE_CREATE_HAS_MEMBER_TYPE_TRAIT( HasPublicType, PublicType );
+ BLAZE_CREATE_HAS_MEMBER_TYPE_TRAIT( HasDetermine , determine );
+ BLAZE_CREATE_HAS_MEMBER_TYPE_TRAIT( HasData , data_ );
+
+ HasCompute<MyType>::value // Evaluates to 'true'
+ HasProtectedType<MyType>::Type // Results in TrueType
+ HasValue<MyType> // Is derived from TrueType
+ HasPublicType<MyType>::value // Evaluates to 'false'
+ HasDetermine<MyType>::Type // Results in FalseType
+ HasData<MyType> // Is derived from FalseType
+ \endcode
+
+// The macro results in the definition of a new class with the specified name \a TYPE_TRAIT_NAME
+// within the current namespace. This may cause name collisions with any other entity called
+// \a TYPE_TRAIT_NAME in the same namespace. Therefore it is advisable to create the type trait
+// as locally as possible to minimize the probability of name collisions. Note however that the
+// macro cannot be used within function scope since a template declaration cannot appear at
+// block scope.
+//
+// Please note that due to an error in the Intel compilers prior to version 14.0 the type trait
+// generated from this macro does NOT work properly, i.e. will not correctly determine whether
+// the specified element is a type member of the given type!
+*/
+#define BLAZE_CREATE_HAS_MEMBER_TYPE_TRAIT( TYPE_TRAIT_NAME, MEMBER_NAME ) \
+ \
+template< typename Type1232 > \
+struct TYPE_TRAIT_NAME##HELPER \
+{ \
+ private: \
+ BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( LOCAL_TYPE_TRAIT_1, MEMBER_NAME ); \
+ BLAZE_CREATE_HAS_TYPE_MEMBER_TYPE_TRAIT( LOCAL_TYPE_TRAIT_2, MEMBER_NAME ); \
+ \
+ public: \
+ static constexpr bool value = ( LOCAL_TYPE_TRAIT_1<Type1232>::value || \
+ LOCAL_TYPE_TRAIT_2<Type1232>::value ); \
+}; \
+ \
+template< typename Type1232 > \
+struct TYPE_TRAIT_NAME \
+ : public blaze::BoolConstant< TYPE_TRAIT_NAME##HELPER<Type1232>::value > \
+{};
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/HasSize.h b/src/cpu/blaze/util/typetraits/HasSize.h
new file mode 100644
index 00000000..4eece7c5
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/HasSize.h
@@ -0,0 +1,285 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/HasSize.h
+// \brief Header file for the HasSize type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_HASSIZE_H_
+#define _BLAZE_UTIL_TYPETRAITS_HASSIZE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/Types.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS HASSIZE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time size check.
+// \ingroup type_traits
+//
+// This class offers the possibility to test the size of a type at compile time. If the type
+// \a T is exactly \a Size bytes large, the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ blaze::HasSize<int,4>::value // Evaluates to 'true' (on most architectures)
+ blaze::HasSize<float,4>::Type // Results in TrueType (on most architectures)
+ blaze::HasSize<const double,8> // Is derived from TrueType (on most architectures)
+ blaze::HasSize<volatile double,2>::value // Evaluates to 'false'
+ blaze::HasSize<const char,8>::Type // Results in FalseType
+ blaze::HasSize<unsigned char,4> // Is derived from FalseType
+ \endcode
+*/
+template< typename T, size_t Size >
+struct HasSize : public BoolConstant< sizeof( T ) == Size >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the compile time size constraint.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the HasSize template for the type \a void. This
+// specialization assumes that an object of type \a void has a size of 0. Therefore \a value
+// is set to \a true, \a Type is \a TrueType, and the class derives from \a TrueType only if the
+// \a Size template argument is 0. Otherwise \a value is set to \a false, \a Type is \a FalseType,
+// and the class derives from \a FalseType.
+*/
+template< size_t Size >
+struct HasSize<void,Size> : public BoolConstant< 0 == Size >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the compile time size constraint.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the HasSize template for constant \a void. This
+// specialization assumes that an object of type \a void has a size of 0. Therefore \a value
+// is set to \a true, \a Type is \a TrueType, and the class derives from \a TrueType only if
+// the \a Size template argument is 0. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+*/
+template< size_t Size >
+struct HasSize<const void,Size> : public BoolConstant< 0 == Size >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the compile time size constraint.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the HasSize template for volatile \a void. This
+// specialization assumes that an object of type \a void has a size of 0. Therefore \a value
+// is set to \a true, \a Type is \a TrueType, and the class derives from \a TrueType only if
+// the \a Size template argument is 0. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+*/
+template< size_t Size >
+struct HasSize<volatile void,Size> : public BoolConstant< 0 == Size >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the compile time size constraint.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the HasSize template for constant volatile \a void.
+// This specialization assumes that an object of type \a void has a size of 0. Therefore \a value
+// is set to \a true, \a Type is \a TrueType, and the class derives from \a TrueType only if the
+// \a Size template argument is 0. Otherwise \a value is set to \a false, \a Type is \a FalseType,
+// and the class derives from \a FalseType.
+*/
+template< size_t Size >
+struct HasSize<const volatile void,Size> : public BoolConstant< 0 == Size >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS HAS1BYTE
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time size check.
+// \ingroup type_traits
+//
+// This type trait offers the possibility to test whether a given type has a size of exactly
+// one byte. If the type \a T has one byte, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ blaze::Has1Byte<const char>::value // Evaluates to 'true' (on most architectures)
+ blaze::Has1Byte<unsigned char>::Type // Results in TrueType (on most architectures)
+ blaze::Has1Byte<signed char> // Is derived from TrueType (on most architectures)
+ blaze::Has1Byte<volatile double>::value // Evaluates to 'false'
+ blaze::Has1Byte<const float>::Type // Results in FalseType
+ blaze::Has1Byte<unsigned short> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct Has1Byte : public HasSize<T,1UL>
+{};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS HAS2BYTES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time size check.
+// \ingroup type_traits
+//
+// This type trait offers the possibility to test whether a given type has a size of exactly
+// two bytes. If the type \a T has two bytes, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ blaze::Has2Bytes<const short>::value // Evaluates to 'true' (on most architectures)
+ blaze::Has2Bytes<unsigned short>::Type // Results in TrueType (on most architectures)
+ blaze::Has2Bytes<volatile short> // Is derived from TrueType (on most architectures)
+ blaze::Has2Bytes<volatile double>::value // Evaluates to 'false'
+ blaze::Has2Bytes<const float>::Type // Results in FalseType
+ blaze::Has2Bytes<unsigned int> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct Has2Bytes : public HasSize<T,2UL>
+{};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS HAS4BYTES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time size check.
+// \ingroup type_traits
+//
+// This type trait offers the possibility to test whether a given type has a size of exactly
+// four bytes. If the type \a T has four bytes, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ blaze::Has4Bytes<const int>::value // Evaluates to 'true' (on most architectures)
+ blaze::Has4Bytes<unsigned int>::Type // Results in TrueType (on most architectures)
+ blaze::Has4Bytes<volatile float> // Is derived from TrueType (on most architectures)
+ blaze::Has4Bytes<volatile double>::value // Evaluates to 'false'
+ blaze::Has4Bytes<const float>::Type // Results in FalseType
+ blaze::Has4Bytes<short> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct Has4Bytes : public HasSize<T,4UL>
+{};
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS HAS8BYTES
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time size check.
+// \ingroup type_traits
+//
+// This type trait offers the possibility to test whether a given type has a size of exactly
+// four bytes. If the type \a T has four bytes, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from\a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the classderives from
+// \a FalseType.
+
+ \code
+ blaze::Has8Bytes<double>::value // Evaluates to 'true' (on most architectures)
+ blaze::Has8Bytes<const double>::Type // Results in TrueType (on most architectures)
+ blaze::Has8Bytes<volatile double> // Is derived from TrueType (on most architectures)
+ blaze::Has8Bytes<unsigned int>::value // Evaluates to 'false'
+ blaze::Has8Bytes<const float>::Type // Results in FalseType
+ blaze::Has8Bytes<volatile short> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct Has8Bytes : public HasSize<T,8UL>
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/HaveSameSize.h b/src/cpu/blaze/util/typetraits/HaveSameSize.h
new file mode 100644
index 00000000..99b03fd3
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/HaveSameSize.h
@@ -0,0 +1,150 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/HaveSameSize.h
+// \brief Header file for the HaveSameSize type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_HAVESAMESIZE_H_
+#define _BLAZE_UTIL_TYPETRAITS_HAVESAMESIZE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time size check.
+// \ingroup type_traits
+//
+// This class offers the possibility to test the size of two types at compile time. If an object
+// of type \a T1 has the same size as an object of type \a T2, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::HaveSameSize<int,unsigned int>::value // Evaluates to 'true'
+ blaze::HaveSameSize<int,unsigned int>::Type // Results in TrueType
+ blaze::HaveSameSize<int,unsigned int> // Is derived from TrueType
+ blaze::HaveSameSize<char,wchar_t>::value // Evalutes to 'false'
+ blaze::HaveSameSize<char,wchar_t>::Type // Results in FalseType
+ blaze::HaveSameSize<char,wchar_t> // Is derived from FalseType
+ \endcode
+
+// One example for the application of this type trait is a compile time check if the compiler
+// supports the 'Empty Derived class Optimization (EDO)':
+
+ \code
+ // Definition of the base class A
+ struct A {
+ int i_;
+ };
+
+ // Definition of the derived class B
+ struct B : public A {};
+
+ // Testing whether or not an object of type B has the same size as the
+ // base class A and whether the compiler supports EDO
+ blaze::HaveSameSize( A, B );
+ \endcode
+*/
+template< typename T1, typename T2 >
+class HaveSameSize : public BoolConstant< sizeof(T1) == sizeof(T2) >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the compile time size constraint.
+// \ingroup type_traits
+//
+// This class is a partial specialization of the HaveSameSize template for the type \a void
+// as first template argument. The \a value member constant is automatically set to \a false,
+// the nested type definition \a Type is \a FalseType, and the class derives from \a FalseType
+// for any given type \a T since the \a void type has no size.
+*/
+template< typename T >
+class HaveSameSize<void,T> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the compile time size constraint.
+// \ingroup type_traits
+//
+// This class is a partial specialization of the HaveSameSize template for the type \a void
+// as second template argument. The \a value member constant is automatically set to \a false,
+// the nested type definition \a Type is \a FalseType, and the class derives from \a FalseType
+// for any given type \a T since the \a void type has no size.
+*/
+template< typename T >
+class HaveSameSize<T,void> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Full specialization of the compile time size constraint.
+// \ingroup type_traits
+//
+// This class is a full specialization of the HaveSameSize template for the type \a void
+// as first and second template argument. The \a value member constant is automatically set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType since both arguments are \a void.
+*/
+template<>
+class HaveSameSize<void,void> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsArithmetic.h b/src/cpu/blaze/util/typetraits/IsArithmetic.h
new file mode 100644
index 00000000..f3fba57c
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsArithmetic.h
@@ -0,0 +1,84 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsArithmetic.h
+// \brief Header file for the IsArithmetic type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISARITHMETIC_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISARITHMETIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for arithmetic data types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a (possibly cv-qualified)
+// arithmetic (integral or floating point) data type. In case the type is an arithmetic type,
+// the \a value member constant is set to \a true, the nested type definition \a Type is
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType and the class derives from \a FalseType.
+
+ \code
+ class MyClass {};
+
+ blaze::IsArithmetic<int>::value // Evaluates to 'true'
+ blaze::IsArithmetic<float const>::Type // Results in TrueType
+ blaze::IsArithmetic<short volatile> // Is derived from TrueType
+ blaze::IsArithmetic<void>::value // Evaluates to 'false'
+ blaze::IsArithmetic<int*>::value // Evaluates to 'false'
+ blaze::IsArithmetic<int&>::Type // Results in FalseType
+ blaze::IsArithmetic<MyClass> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsArithmetic : public BoolConstant< std::is_arithmetic<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsArray.h b/src/cpu/blaze/util/typetraits/IsArray.h
new file mode 100644
index 00000000..350657a0
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsArray.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsArray.h
+// \brief Header file for the IsArray type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISARRAY_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISARRAY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsArray type trait tests whether or not the given template parameter is an array type. In
+// case the given data type is an array type, the \a value member constant is set to \a true, the
+// nested type definition \a Type is set to \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType and the class derives from
+// \a FalseType.
+
+ \code
+ blaze::IsArray< int[3] >::value // Evaluates to 'true'
+ blaze::IsArray< const int[] >::Type // Results in TrueType
+ blaze::IsArray< int[][3] > // Is derived from TrueType
+ blaze::IsArray< int >::value // Evaluates to 'false'
+ blaze::IsArray< int const* >::Type // Results in FalseType
+ blaze::IsArray< std::vector<int> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsArray : public BoolConstant< std::is_array<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsAssignable.h b/src/cpu/blaze/util/typetraits/IsAssignable.h
new file mode 100644
index 00000000..fa410c41
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsAssignable.h
@@ -0,0 +1,191 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsAssignable.h
+// \brief Header file for the IsAssignable type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISASSIGNABLE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISASSIGNABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsAssignable type trait tests whether the expression
+
+ \code
+ std::declval<T>() = std::declval<U>();
+ \endcode
+
+// is well formed. If an object of type \a U can be assigned to an object of type \a T in this
+// way, the \a value member constant is set to \a true, the nested type definition \a Type is set
+// to \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T, typename U >
+struct IsAssignable
+ : public BoolConstant< std::is_assignable<T,U>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsNothrowAssignable type trait tests whether the expression
+
+ \code
+ std::declval<T>() = std::declval<U>();
+ \endcode
+
+// is well formed and guaranteed to not throw an exception (i.e. noexcept). If an object of type
+// \a U can be assigned to an object of type \a T in this way, the \a value member constant is set
+// to \a true, the nested type definition \a Type is set to \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType and the class
+// derives from \a FalseType.
+*/
+template< typename T, typename U >
+struct IsNothrowAssignable
+ : public BoolConstant< std::is_nothrow_assignable<T,U>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsCopyAssignable type trait tests whether the expression
+
+ \code
+ std::declval<T>() = std::declval<T>();
+ \endcode
+
+// is well formed. If an object of type \a T can be copy assigned to another object of type \a T,
+// the \a value member constant is set to \a true, the nested type definition \a Type is set to
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsCopyAssignable
+ : public BoolConstant< std::is_copy_assignable<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsNothrowCopyAssignable type trait tests whether the expression
+
+ \code
+ std::declval<T>() = std::declval<T>();
+ \endcode
+
+// is well formed and guaranteed to not throw an exception (i.e. noexcept). If an object of
+// type \a T can be copy assigned to another object of type \a T in this way, the \a value
+// member constant is set to \a true, the nested type definition \a Type is set to \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsNothrowCopyAssignable
+ : public BoolConstant< std::is_nothrow_copy_assignable<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsMoveAssignable type trait tests whether the expression
+
+ \code
+ std::declval<T>() = std::move( std::declval<T>() );
+ \endcode
+
+// is well formed. If an object of type \a T can be move assigned to another object of type \a T,
+// the \a value member constant is set to \a true, the nested type definition \a Type is set to
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMoveAssignable
+ : public BoolConstant< std::is_move_assignable<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsNothrowMoveAssignable type trait tests whether the expression
+
+ \code
+ std::declval<T>() = std::move( std::declval<T>() );
+ \endcode
+
+// is well formed and guaranteed to not throw an exception (i.e. noexcept). If an object of
+// type \a T can be move assigned to another object of type \a T in this way, the \a value
+// member constant is set to \a true, the nested type definition \a Type is set to \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsNothrowMoveAssignable
+ : public BoolConstant< std::is_nothrow_move_assignable<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsBaseOf.h b/src/cpu/blaze/util/typetraits/IsBaseOf.h
new file mode 100644
index 00000000..5bb8d1f2
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsBaseOf.h
@@ -0,0 +1,86 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsBaseOf.h
+// \brief Header file for the IsBaseOf type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISBASEOF_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISBASEOF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time analysis of an inheritance relationship.
+// \ingroup type_traits
+//
+// This type trait tests for an inheritance relationship between the two types \a Base and
+// \a Derived. If \a Derived is a type derived from \a Base or the same type as \a Base the
+// \a value member contant is set to \a true, the nested type definition \a Type is \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ class A { ... };
+ class B : public A { ... };
+ class C { ... };
+
+ blaze::IsBaseOf<A,B>::value // Evaluates to 'true'
+ blaze::IsBaseOf<A,B>::Type // Results in TrueType
+ blaze::IsBaseOf<A,B> // Is derived from TrueType
+ blaze::IsBaseOf<A,C>::value // Evaluates to 'false'
+ blaze::IsBaseOf<B,A>::Type // Results in FalseType
+ blaze::IsBaseOf<B,A> // Is derived from FalseType
+ \endcode
+*/
+template< typename Base, typename Derived >
+class IsBaseOf : public BoolConstant< std::is_base_of< RemoveCV_<Base>, RemoveCV_<Derived> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsBoolean.h b/src/cpu/blaze/util/typetraits/IsBoolean.h
new file mode 100644
index 00000000..ccf30339
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsBoolean.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsBoolean.h
+// \brief Header file for the IsBoolean type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISBOOLEAN_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISBOOLEAN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for boolean types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is of boolean type. In
+// case the type is a boolean (ignoring the cv-qualifiers), the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsBoolean<bool>::value // Evaluates to 'true'
+ blaze::IsBoolean<const bool>::Type // Results in TrueType
+ blaze::IsBoolean<const volatile bool> // Is derived from TrueType
+ blaze::IsBoolean<float>::value // Evaluates to 'false' (float is not a boolean)
+ blaze::IsBoolean<const int>::Type // Results in FalseType
+ blaze::IsBoolean<volatile short> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsBoolean : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsBoolean type trait for the plain 'bool' type.
+template<>
+struct IsBoolean<bool> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsBoolean type trait for 'const bool'.
+template<>
+struct IsBoolean<const bool> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsBoolean type trait for 'volatile bool'.
+template<>
+struct IsBoolean<volatile bool> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsBoolean type trait for 'const volatile bool'
+template<>
+struct IsBoolean<const volatile bool> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsBuiltin.h b/src/cpu/blaze/util/typetraits/IsBuiltin.h
new file mode 100644
index 00000000..885b6440
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsBuiltin.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsBuiltin.h
+// \brief Header file for the IsBuiltin type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISBUILTIN_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISBUILTIN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for built-in data types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a built-in/fundamental
+// data type. In case the type is a built-in type, the \a value member constant is set to \a true,
+// the nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ blaze::IsBuiltin<void>::value // Evaluates to 'true'
+ blaze::IsBuiltin<float const>::Type // Results in TrueType
+ blaze::IsBuiltin<short volatile> // Is derived from TrueType
+ blaze::IsBuiltin<std::string>::value // Evaluates to 'false'
+ blaze::IsBuiltin<int*>::Type // Results in FalseType
+ blaze::IsBuiltin<int&> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsBuiltin : public BoolConstant< std::is_fundamental<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsCharacter.h b/src/cpu/blaze/util/typetraits/IsCharacter.h
new file mode 100644
index 00000000..f66cd010
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsCharacter.h
@@ -0,0 +1,152 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsCharacter.h
+// \brief Header file for the IsCharacter type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISCHARACTER_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISCHARACTER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for character types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a character type
+// (i.e., either char, signed char, unsigned char, or wchar_t, possibly cv-qualified).
+// In case the type is a character type (ignoring the cv-qualifiers), the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsCharacter<char>::value // Evaluates to 'true'
+ blaze::IsCharacter<const unsigned char>::Type // Results in TrueType
+ blaze::IsCharacter<const volatile wchar_t> // Is derived from TrueType
+ blaze::IsCharacter<unsigned short>::value // Evaluates to 'false'
+ blaze::IsCharacter<const int>::Type // Results in FalseType
+ blaze::IsCharacter<volatile long> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsCharacter : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsCharacter type trait for the plain 'char' type.
+template<>
+struct IsCharacter<char> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsCharacter type trait for the plain 'signed char' type.
+template<>
+struct IsCharacter<signed char> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsCharacter type trait for the plain 'unsigned char' type.
+template<>
+struct IsCharacter<unsigned char> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsCharacter type trait for the plain 'wchar_t' type.
+template<>
+struct IsCharacter<wchar_t> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Partial specialization of the IsCharacter type trait 'const' qualified types.
+template< typename T >
+struct IsCharacter<const T> : public IsCharacter<T>::Type
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Partial specialization of the IsCharacter type trait 'volatile' qualified types.
+template< typename T >
+struct IsCharacter<volatile T> : public IsCharacter<T>::Type
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Partial specialization of the IsCharacter type trait 'const volatile' types.
+template< typename T >
+struct IsCharacter<const volatile T> : public IsCharacter<T>::Type
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsClass.h b/src/cpu/blaze/util/typetraits/IsClass.h
new file mode 100644
index 00000000..2be6c3f9
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsClass.h
@@ -0,0 +1,83 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsClass.h
+// \brief Header file for the IsClass type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISCLASS_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISCLASS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsClass type trait tests whether or not the given template parameter is a (possibly
+// cv-qualified) class type. In case the given data type is a class type, the \a value member
+// constant is set to \a true, the nested type definition \a Type is set to \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType and the class derives from \a FalseType.
+
+ \code
+ class MyClass {};
+
+ blaze::IsClass<MyClass>::value // Evaluates to 'true'
+ blaze::IsClass<MyClass const>::Type // Results in TrueType
+ blaze::IsClass<std::string volatile> // Is derived from TrueType
+ blaze::IsClass<int>::value // Evaluates to 'false' (int is a built-in data type)
+ blaze::IsClass<MyClass&>::Type // Results in FalseType
+ blaze::IsClass<MyClass*> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsClass : public BoolConstant< std::is_class<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsComplex.h b/src/cpu/blaze/util/typetraits/IsComplex.h
new file mode 100644
index 00000000..f3dbaf53
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsComplex.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsComplex.h
+// \brief Header file for the IsComplex type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISCOMPLEX_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISCOMPLEX_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for complex types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a complex data type.
+// In case the type is a complex data type (ignoring the cv-qualifiers), the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType,
+// and the class derives from \a FalseType.
+
+ \code
+ blaze::IsComplex< complex<double> >::value // Evaluates to 'true'
+ blaze::IsComplex< const complex<float> >::Type // Results in TrueType
+ blaze::IsComplex< volatile complex<int> > // Is derived from TrueType
+ blaze::IsComplex< float >::value // Evaluates to 'false'
+ blaze::IsComplex< const double >::Type // Results in FalseType
+ blaze::IsComplex< const volatile int > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsComplex : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplex type trait for the plain 'complex' type.
+template< typename T >
+struct IsComplex< complex<T> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplex type trait for 'const complex'.
+template< typename T >
+struct IsComplex< const complex<T> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplex type trait for 'volatile complex'.
+template< typename T >
+struct IsComplex< volatile complex<T> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplex type trait for 'const volatile complex'
+template< typename T >
+struct IsComplex< const volatile complex<T> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsComplexDouble.h b/src/cpu/blaze/util/typetraits/IsComplexDouble.h
new file mode 100644
index 00000000..c5bdd282
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsComplexDouble.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsComplexDouble.h
+// \brief Header file for the IsComplexDouble type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISCOMPLEXDOUBLE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISCOMPLEXDOUBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for single precision complex types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is of type \c complex<double>.
+// In case the type is \c complex<double> (ignoring the cv-qualifiers), the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and
+// the class derives from \a FalseType.
+
+ \code
+ blaze::IsComplexDouble< complex<double> >::value // Evaluates to 'true'
+ blaze::IsComplexDouble< const complex<double> >::Type // Results in TrueType
+ blaze::IsComplexDouble< volatile complex<double> > // Is derived from TrueType
+ blaze::IsComplexDouble< double >::value // Evaluates to 'false'
+ blaze::IsComplexDouble< const complex<float> >::Type // Results in FalseType
+ blaze::IsComplexDouble< const volatile complex<int> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsComplexDouble : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplexDouble type trait for the plain 'complex<double>' type.
+template<>
+struct IsComplexDouble< complex<double> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplexDouble type trait for 'const complex<double>'.
+template<>
+struct IsComplexDouble< const complex<double> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplexDouble type trait for 'volatile complex<double>'.
+template<>
+struct IsComplexDouble< volatile complex<double> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplexDouble type trait for 'const volatile complex<double>'
+template<>
+struct IsComplexDouble< const volatile complex<double> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsComplexFloat.h b/src/cpu/blaze/util/typetraits/IsComplexFloat.h
new file mode 100644
index 00000000..ca41c9d0
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsComplexFloat.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsComplexFloat.h
+// \brief Header file for the IsComplexFloat type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISCOMPLEXFLOAT_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISCOMPLEXFLOAT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for single precision complex types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is of type \c complex<float>.
+// In case the type is \c complex<float> (ignoring the cv-qualifiers), the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and
+// the class derives from \a FalseType.
+
+ \code
+ blaze::IsComplexFloat< complex<float> >::value // Evaluates to 'true'
+ blaze::IsComplexFloat< const complex<float> >::Type // Results in TrueType
+ blaze::IsComplexFloat< volatile complex<float> > // Is derived from TrueType
+ blaze::IsComplexFloat< float >::value // Evaluates to 'false'
+ blaze::IsComplexFloat< const complex<double> >::Type // Results in FalseType
+ blaze::IsComplexFloat< const volatile complex<int> > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsComplexFloat : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplexFloat type trait for the plain 'complex<float>' type.
+template<>
+struct IsComplexFloat< complex<float> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplexFloat type trait for 'const complex<float>'.
+template<>
+struct IsComplexFloat< const complex<float> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplexFloat type trait for 'volatile complex<float>'.
+template<>
+struct IsComplexFloat< volatile complex<float> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsComplexFloat type trait for 'const volatile complex<float>'
+template<>
+struct IsComplexFloat< const volatile complex<float> > : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsConst.h b/src/cpu/blaze/util/typetraits/IsConst.h
new file mode 100644
index 00000000..77348b44
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsConst.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsConst.h
+// \brief Header file for the IsConst type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISCONST_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISCONST_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for constant data types.
+// \ingroup type_traits
+//
+// The IsConst type trait tests whether or not the given template parameter is a (top level)
+// const-qualified data type. In case the given data type is const-qualified, the \a value
+// member constant is set to \a true, the nested type definition \a Type is \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsConst<const int>::value // Evaluates to 'true'
+ blaze::IsConst<const volatile int>::Type // Results in TrueType
+ blaze::IsConst<int* const> // Is derived from TrueType
+ blaze::IsConst<int>::value // Evaluates to 'false'
+ blaze::IsConst<const int*>::Type // Results in FalseType (the const-qualifier is not at the top level)
+ blaze::IsConst<const int* volatile> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsConst : public BoolConstant< std::is_const<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsConstructible.h b/src/cpu/blaze/util/typetraits/IsConstructible.h
new file mode 100644
index 00000000..ba3eb0c6
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsConstructible.h
@@ -0,0 +1,232 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsConstructible.h
+// \brief Header file for the IsConstructible type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISCONSTRUCTIBLE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISCONSTRUCTIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsConstructible type trait tests whether the expression
+
+ \code
+ T obj( std::declval<Args>()... );
+ \endcode
+
+// is well formed. If an object of type \a T can be created in this way, the \a value member
+// constant is set to \a true, the nested type definition \a Type is set to \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T, typename... Args >
+struct IsConstructible
+ : public BoolConstant< std::is_constructible<T,Args...>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsNothrowConstructible type trait tests whether the expression
+
+ \code
+ T obj( std::declval<Args>()... );
+ \endcode
+
+// is well formed and guaranteed to not throw an exception (i.e. noexcept). If an object of type
+// \a T can be created in this way, the \a value member constant is set to \a true, the nested
+// type definition \a Type is set to \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T, typename... Args >
+struct IsNothrowConstructible
+ : public BoolConstant< std::is_nothrow_constructible<T,Args...>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsDefaultConstructible type trait tests whether the expression
+
+ \code
+ T obj;
+ \endcode
+
+// is well formed. If an object of type \a T can be default constructed, the \a value member
+// constant is set to \a true, the nested type definition \a Type is set to \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsDefaultConstructible
+ : public BoolConstant< std::is_default_constructible<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsDefaultConstructible type trait tests whether the expression
+
+ \code
+ T obj;
+ \endcode
+
+// is well formed and guaranteed to not throw an exception (i.e. noexcept). If an object of type
+// \a T can be default constructed, the \a value member constant is set to \a true, the nested
+// type definition \a Type is set to \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsNothrowDefaultConstructible
+ : public BoolConstant< std::is_nothrow_default_constructible<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsCopyConstructible type trait tests whether the expression
+
+ \code
+ T obj( std::declval<T>() );
+ \endcode
+
+// is well formed. If an object of type \a T can be copy constructed, the \a value member
+// constant is set to \a true, the nested type definition \a Type is set to \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsCopyConstructible
+ : public BoolConstant< std::is_copy_constructible<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsNothrowCopyConstructible type trait tests whether the expression
+
+ \code
+ T obj( std::declval<T>() );
+ \endcode
+
+// is well formed and guaranteed to not throw an exception (i.e. noexcept). If an object of type
+// \a T can be copy constructed, the \a value member constant is set to \a true, the nested type
+// definition \a Type is set to \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsNothrowCopyConstructible
+ : public BoolConstant< std::is_copy_constructible<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsMoveConstructible type trait tests whether the expression
+
+ \code
+ T obj( std::move( std::declval<T>() ) );
+ \endcode
+
+// is well formed. If an object of type \a T can be move constructed, the \a value member
+// constant is set to \a true, the nested type definition \a Type is set to \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsMoveConstructible
+ : public BoolConstant< std::is_move_constructible<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsNothrowMoveConstructible type trait tests whether the expression
+
+ \code
+ T obj( std::move( std::declval<T>() ) );
+ \endcode
+
+// is well formed and guaranteed to not throw an exception (i.e. noexcept). If an object of type
+// \a T can be move constructed, the \a value member constant is set to \a true, the nested type
+// definition \a Type is set to \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsNothrowMoveConstructible
+ : public BoolConstant< std::is_nothrow_move_constructible<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsConvertible.h b/src/cpu/blaze/util/typetraits/IsConvertible.h
new file mode 100644
index 00000000..a683d9dc
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsConvertible.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsConvertible.h
+// \brief Header file for the IsConvertible type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISCONVERTIBLE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISCONVERTIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time pointer relationship constraint.
+// \ingroup type_traits
+//
+// This type traits tests whether the first given template argument can be converted to the
+// second template argument via copy construction. If the first argument can be converted
+// to the second argument, the \a value member constnt is set to \a true, the nested type
+// definition \a type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ struct A {};
+ struct B : public A {};
+
+ struct C {};
+ struct D {
+ D( const C& c ) {}
+ };
+
+ blaze::IsConvertible<int,unsigned int>::value // Evaluates to 'true'
+ blaze::IsConvertible<float,const double>::value // Evaluates to 'true'
+ blaze::IsConvertible<B,A>::Type // Results in TrueType
+ blaze::IsConvertible<B*,A*>::Type // Results in TrueType
+ blaze::IsConvertible<C,D> // Is derived from TrueType
+ blaze::IsConvertible<char*,std::string> // Is derived from TrueType
+ blaze::IsConvertible<std::string,char*>::value // Evaluates to 'false'
+ blaze::IsConvertible<A,B>::Type // Results in FalseType
+ blaze::IsConvertible<A*,B*> // Is derived from FalseType
+ \endcode
+*/
+template< typename From, typename To >
+struct IsConvertible : public BoolConstant< std::is_convertible<From,To>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsDestructible.h b/src/cpu/blaze/util/typetraits/IsDestructible.h
new file mode 100644
index 00000000..b5ca5143
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsDestructible.h
@@ -0,0 +1,102 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsDestructible.h
+// \brief Header file for the IsDestructible type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISDESTRUCTIBLE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISDESTRUCTIBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITIONS
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsDestructible type trait tests whether the expression
+
+ \code
+ std::declval<U&>().~U();
+ \endcode
+
+// is well formed, where \a U represents the type \a T stripped of all extents. If an object of
+// type \a T can be destroyed in this way, the \a value member constant is set to \a true, the
+// nested type definition \a Type is set to \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType and the class derives from
+// \a FalseType.
+*/
+template< typename T >
+struct IsDestructible
+ : public BoolConstant< std::is_destructible<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// The IsDestructible type trait tests whether the expression
+
+ \code
+ std::declval<U&>().~U();
+ \endcode
+
+// is well formed and guaranteed to not throw an exception (i.e. noexcept), where \a U represents
+// the type \a T stripped of all extents. If an object of type \a T can be destroyed in this way,
+// the \a value member constant is set to \a true, the nested type definition \a Type is set to
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType and the class derives from \a FalseType.
+*/
+template< typename T >
+struct IsNothrowDestructible
+ : public BoolConstant< std::is_nothrow_destructible<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsDouble.h b/src/cpu/blaze/util/typetraits/IsDouble.h
new file mode 100644
index 00000000..3bdb926b
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsDouble.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsDouble.h
+// \brief Header file for the IsDouble type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISDOUBLE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISDOUBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for double precision floating point types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is of double type. In
+// case the type is double (ignoring the cv-qualifiers), the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsDouble<double>::value // Evaluates to 'true'
+ blaze::IsDouble<const double>::Type // Results in TrueType
+ blaze::IsDouble<const volatile double> // Is derived from TrueType
+ blaze::IsDouble<float>::value // Evaluates to 'false'
+ blaze::IsDouble<const int>::Type // Results in FalseType
+ blaze::IsDouble<volatile short> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsDouble : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsDouble type trait for the plain 'double' type.
+template<>
+struct IsDouble<double> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsDouble type trait for 'const double'.
+template<>
+struct IsDouble<const double> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsDouble type trait for 'volatile double'.
+template<>
+struct IsDouble<volatile double> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsDouble type trait for 'const volatile double'.
+template<>
+struct IsDouble<const volatile double> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsEmpty.h b/src/cpu/blaze/util/typetraits/IsEmpty.h
new file mode 100644
index 00000000..f10f4bf7
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsEmpty.h
@@ -0,0 +1,84 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsEmpty.h
+// \brief Header file for the IsEmpty type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISEMPTY_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISEMPTY_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// This class tests whether the given template parameter is an empty class type, i.e. a type
+// without member data and virtual functions. If it is an empty class type, the \a value
+// member constant is set to \a true, the nested type definition \a Type is \a TrueType,
+// and the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type
+// is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ class A {};
+ class B { int i; };
+
+ blaze::IsEmpty<A>::value // Evaluates to 'true'
+ blaze::IsEmpty<A volatile>::Type // Results in TrueType
+ blaze::IsEmpty<A const> // Is derived from TrueType
+ blaze::IsEmpty<int>::value // Evaluates to 'false'
+ blaze::IsEmpty<std::string>::Type // Results in FalseType
+ blaze::IsEmpty<B> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsEmpty : public BoolConstant< std::is_empty<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsFloat.h b/src/cpu/blaze/util/typetraits/IsFloat.h
new file mode 100644
index 00000000..54062ba0
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsFloat.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsFloat.h
+// \brief Header file for the IsFloat type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISFLOAT_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISFLOAT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for single precision floating point types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is of float type. In
+// case the type is float (ignoring the cv-qualifiers), the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsFloat<float>::value // Evaluates to 'true'
+ blaze::IsFloat<const float>::Type // Results in TrueType
+ blaze::IsFloat<const volatile float> // Is derived from TrueType
+ blaze::IsFloat<double>::value // Evaluates to 'false'
+ blaze::IsFloat<const int>::Type // Results in FalseType
+ blaze::IsFloat<volatile short> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsFloat : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsFloat type trait for the plain 'float' type.
+template<>
+struct IsFloat<float> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsFloat type trait for 'const float'.
+template<>
+struct IsFloat<const float> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsFloat type trait for 'volatile float'.
+template<>
+struct IsFloat<volatile float> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsFloat type trait for 'const volatile float'.
+template<>
+struct IsFloat<const volatile float> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsFloatingPoint.h b/src/cpu/blaze/util/typetraits/IsFloatingPoint.h
new file mode 100644
index 00000000..34c8c056
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsFloatingPoint.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsFloatingPoint.h
+// \brief Header file for the IsFloatingPoint type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISFLOATINGPOINT_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISFLOATINGPOINT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for floating point data types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a floating point
+// data type (ignoring the cv-qualifiers). In case the type is a floating point data type,
+// the \a value member constant is set to \a true, the nested type definition \a Type is
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsFloatingPoint<float>::value // Evaluates to 'true'
+ blaze::IsFloatingPoint<volatile double>::Type // Result in TrueType
+ blaze::IsFloatingPoint<const long double> // Is derived from TrueType
+ blaze::IsFloatingPoint<int>::value // Evaluates to 'false'
+ blaze::IsFloatingPoint<const short>::Type // Results in FalseType
+ blaze::IsFloatingPoint<volatile wchar_t> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsFloatingPoint : public BoolConstant< std::is_floating_point<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsInteger.h b/src/cpu/blaze/util/typetraits/IsInteger.h
new file mode 100644
index 00000000..c209f125
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsInteger.h
@@ -0,0 +1,166 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsInteger.h
+// \brief Header file for the IsInteger type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISINTEGER_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISINTEGER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for integer types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is an integer type (i.e.,
+// either (signed) int or unsigned int, possibly cv-qualified). In case the type is an integer
+// type (ignoring the cv-qualifiers), the \a value member constant is set to \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsInteger<int>::value // Evaluates to 'true'
+ blaze::IsInteger<const unsigned int>::Type // Results in TrueType
+ blaze::IsInteger<const volatile signed int> // Is derived from TrueType
+ blaze::IsInteger<unsigned short>::value // Evaluates to 'false'
+ blaze::IsInteger<const long>::Type // Results in FalseType
+ blaze::IsInteger<volatile float> // Is derived from FalseType
+ \endcode
+
+// Note the difference between the IsInteger and IsIntegral type traits: Whereas the IsInteger
+// type trait specifically tests whether the given data type is either int or unsigned int
+// (possibly cv-qualified), the IsIntegral type trait tests whether the given template argument
+// is an integral data type (char, short, int, long, etc.).
+*/
+template< typename T >
+struct IsInteger : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsInteger type trait for the plain 'int' type.
+template<>
+struct IsInteger<int> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsInteger type trait for 'const int'.
+template<>
+struct IsInteger<const int> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsInteger type trait for 'volatile int'.
+template<>
+struct IsInteger<volatile int> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsInteger type trait for 'const volatile int'.
+template<>
+struct IsInteger<const volatile int> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsInteger type trait for the plain 'unsigned int' type.
+template<>
+struct IsInteger<unsigned int> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsInteger type trait for 'const unsigned int'.
+template<>
+struct IsInteger<const unsigned int> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsInteger type trait for 'volatile unsigned int'.
+template<>
+struct IsInteger<volatile unsigned int> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsInteger type trait for 'const volatile unsigned int'.
+template<>
+struct IsInteger<const volatile unsigned int> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsIntegral.h b/src/cpu/blaze/util/typetraits/IsIntegral.h
new file mode 100644
index 00000000..0a18e8d8
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsIntegral.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsIntegral.h
+// \brief Header file for the IsIntegral type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISINTEGRAL_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISINTEGRAL_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for integral data types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is an integral data
+// type. In case the type is an integral data type, the \a value member constant is set to
+// \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsIntegral<int>::value // Evaluates to 'true'
+ blaze::IsIntegral<const char>::Type // Results in TrueType (char is an integral data type)
+ blaze::IsIntegral<volatile short> // Is derived from TrueType
+ blaze::IsIntegral<float>::value // Evaluates to 'false'
+ blaze::IsIntegral<const double>::Type // Results in FalseType
+ blaze::IsIntegral<volatile long double> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsIntegral : public BoolConstant< std::is_integral<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsLong.h b/src/cpu/blaze/util/typetraits/IsLong.h
new file mode 100644
index 00000000..ad4f57d8
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsLong.h
@@ -0,0 +1,162 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsLong.h
+// \brief Header file for the IsLong type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISLONG_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISLONG_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for long integer types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a long integer type
+// (i.e., either (signed) long or unsigned long, possibly cv-qualified). In case the type
+// is a long integer type (ignoring the cv-qualifiers), the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsLong<long>::value // Evaluates to 'true'
+ blaze::IsLong<const unsigned long>::Type // Results in TrueType
+ blaze::IsLong<const volatile signed long> // Is derived from TrueType
+ blaze::IsLong<unsigned short>::value // Evaluates to 'false'
+ blaze::IsLong<const int>::Type // Results in FalseType
+ blaze::IsLong<volatile float> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsLong : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLong type trait for the plain 'long' type.
+template<>
+struct IsLong<long> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLong type trait for 'const long'.
+template<>
+struct IsLong<const long> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLong type trait for 'volatile long'.
+template<>
+struct IsLong<volatile long> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLong type trait for 'const volatile long'.
+template<>
+struct IsLong<const volatile long> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLong type trait for the plain 'unsigned long' type.
+template<>
+struct IsLong<unsigned long> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLong type trait for 'const unsigned long'.
+template<>
+struct IsLong<const unsigned long> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLong type trait for 'volatile unsigned long'.
+template<>
+struct IsLong<volatile unsigned long> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLong type trait for 'const volatile unsigned long'.
+template<>
+struct IsLong<const volatile unsigned long> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsLongDouble.h b/src/cpu/blaze/util/typetraits/IsLongDouble.h
new file mode 100644
index 00000000..482fbfe6
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsLongDouble.h
@@ -0,0 +1,121 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsLongDouble.h
+// \brief Header file for the IsLongDouble type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISLONGDOUBLE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISLONGDOUBLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for extended precision floating point types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is of long double type. In
+// case the type is long double (ignoring the cv-qualifiers), the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsLongDouble<long double>::value // Evaluates to 'true'
+ blaze::IsLongDouble<const long double>::Type // Results in TrueType
+ blaze::IsLongDouble<const volatile long double> // Is derived from TrueType
+ blaze::IsLongDouble<float>::value // Evaluates to 'false'
+ blaze::IsLongDouble<const unsigned int>::Type // Results in FalseType
+ blaze::IsLongDouble<volatile const short> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsLongDouble : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLongDouble type trait for the plain 'long double' type.
+template<>
+struct IsLongDouble<long double> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLongDouble type trait for 'const long double'.
+template<>
+struct IsLongDouble<const long double> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLongDouble type trait for 'volatile long double'.
+template<>
+struct IsLongDouble<volatile long double> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsLongDouble type trait for 'const volatile long double'.
+template<>
+struct IsLongDouble<const volatile long double> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsNumeric.h b/src/cpu/blaze/util/typetraits/IsNumeric.h
new file mode 100644
index 00000000..f46d0b41
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsNumeric.h
@@ -0,0 +1,125 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsNumeric.h
+// \brief Header file for the IsNumeric type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISNUMERIC_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISNUMERIC_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/Complex.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/typetraits/IsBoolean.h>
+#include <blaze/util/typetraits/IsBuiltin.h>
+#include <blaze/util/typetraits/IsVoid.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for numeric types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a numeric data type.
+// Blaze considers all integral (except \a bool), floating point, and complex data types as
+// numeric data types. In case the type is a numeric type, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsNumeric<int>::value // Evaluates to 'true' (int is a numeric data type)
+ blaze::IsNumeric<const double>::Type // Results in TrueType (float is a numeric data type)
+ blaze::IsNumeric<volatile complex<float> > // Is derived from TrueType (complex<float> is a numeric data type)
+ blaze::IsNumeric<void>::value // Evaluates to 'false' (void is not a numeric data type)
+ blaze::IsNumeric<bool>::Type // Results in FalseType (bool is not a numeric data type)
+ blaze::IsNumeric<const bool> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsNumeric : public BoolConstant< IsBuiltin<T>::value && !IsBoolean<T>::value && !IsVoid<T>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsNumeric type trait for the plain 'complex' type.
+template< typename T >
+struct IsNumeric< complex<T> > : public IsNumeric<T>::Type
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsNumeric type trait for 'const complex'.
+template< typename T >
+struct IsNumeric< const complex<T> > : public IsNumeric<T>::Type
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsNumeric type trait for 'volatile complex'.
+template< typename T >
+struct IsNumeric< volatile complex<T> > : public IsNumeric<T>::Type
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsNumeric type trait for 'const volatile complex'.
+template< typename T >
+struct IsNumeric< const volatile complex<T> > : public IsNumeric<T>::Type
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsObject.h b/src/cpu/blaze/util/typetraits/IsObject.h
new file mode 100644
index 00000000..6b2d57f1
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsObject.h
@@ -0,0 +1,82 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsObject.h
+// \brief Header file for the IsObject type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISOBJECT_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISOBJECT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// This class tests whether the given template parameter \a T is an object type. All types are
+// considered object types except references, \a void, and function types. If \a T is an object
+// type, the \a value member constant is set to \a true, the nested type definition \a Type is
+// \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to \a false,
+// \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsObject<int>::value // Evaluates to 'true'
+ blaze::IsObject<int*>::Type // Results in TrueType
+ blaze::IsObject<int (*)(void)> // Is derived from TrueType
+ blaze::IsObject<int (MyClass::*)(void)const> // Also derived from TrueType
+ blaze::IsObject<int&>::value // Evaluates to 'false'
+ blaze::IsObject<const void>::Type // Results in FalseType
+ blaze::IsObject<int (double)> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsObject : public BoolConstant< std::is_object<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsPod.h b/src/cpu/blaze/util/typetraits/IsPod.h
new file mode 100644
index 00000000..8165b599
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsPod.h
@@ -0,0 +1,93 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsPod.h
+// \brief Header file for the IsPod type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISPOD_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISPOD_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for pod data types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a POD (Plain Old Data).
+// In case the type is a POD, the \a value member constant is set to \a true, the nested type
+// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
+// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ class A {
+ int i_;
+ double d_;
+ };
+
+ class B {
+ virtual ~B() {}
+ };
+
+ class C {
+ std::string s_;
+ };
+
+ blaze::IsPod<int>::value // Evaluates to 'true'
+ blaze::IsPod<double const>::Type // Results in TrueType
+ blaze::IsPod<A volatile> // Is derived from TrueType
+ blaze::IsPod< std::vector<int> >::value // Evaluates to 'false'
+ blaze::IsPod<B>::Type // Results in FalseType
+ blaze::IsPod<C> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsPod : public BoolConstant< std::is_pod<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsPointer.h b/src/cpu/blaze/util/typetraits/IsPointer.h
new file mode 100644
index 00000000..adc7e963
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsPointer.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsPointer.h
+// \brief Header file for the IsPointer type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISPOINTER_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISPOINTER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// This class tests whether the given template parameter is a pointer type (including function
+// pointers, but excluding pointers to members) or not. If it is a pointer type, the \a value
+// member constant is set to \a true, the nested type definition \a Type is \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsPointer<char* const>::value // Evaluates to 'true'
+ blaze::IsPointer<volatile float*>::Type // Results in TrueType
+ blaze::IsPointer<int (*)(long)> // Is derived from TrueType
+ blaze::IsPointer<int>::value // Evaluates to 'false'
+ blaze::IsPointer<int MyClass::*>::Type // Results in FalseType
+ blaze::IsPointer<int (MyClass::*)(long)> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsPointer : public BoolConstant< std::is_pointer<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsReference.h b/src/cpu/blaze/util/typetraits/IsReference.h
new file mode 100644
index 00000000..f47ed39d
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsReference.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsReference.h
+// \brief Header file for the IsReference type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISREFERENCE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISREFERENCE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// This class tests whether the given template parameter \a T is a reference type (including
+// references to functions). If it is a reference type, the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsReference<int&>::value // Evaluates to 'true'
+ blaze::IsReference<int const&>::Type // Results in TrueType
+ blaze::IsReference<int (&)(long)> // Is derived from TrueType
+ blaze::IsReference<int>::value // Evaluates to 'false'
+ blaze::IsReference<double*>::Type // Results in FalseType
+ blaze::IsReference<int (MyClass::*)(long)> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsReference : public BoolConstant< std::is_reference<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsSame.h b/src/cpu/blaze/util/typetraits/IsSame.h
new file mode 100644
index 00000000..9add8fcf
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsSame.h
@@ -0,0 +1,144 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsSame.h
+// \brief Header file for the IsSame and IsStrictlySame type traits
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISSAME_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISSAME_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type relationship analysis.
+// \ingroup type_traits
+//
+// This class tests if the two data types \a A and \a B are equal. For this type comparison,
+// the cv-qualifiers of both data types are not ignored. If \a A and \a B are the same data
+// type, then the \a value member constant is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsStrictlySame<int,int>::value // Evaluates to 'true'
+ blaze::IsStrictlySame<const double,const double>::Type // Results in TrueType
+ blaze::IsStrictlySame<volatile float,volatile float> // Is derived from TrueType
+ blaze::IsStrictlySame<char,wchar_t>::value // Evaluates to 'false'
+ blaze::IsStrictlySame<int,const int>::Type // Results in FalseType
+ blaze::IsStrictlySame<float,volatile float> // Is derived from FalseType
+ \endcode
+*/
+template< typename A, typename B >
+struct IsStrictlySame : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsStrictlySame class template for a single, matching data type.
+template< typename T >
+struct IsStrictlySame<T,T> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the IsSame type trait.
+// \ingroup type_traits
+*/
+template< typename A, typename B >
+struct IsSameHelper
+{
+ public:
+ //**********************************************************************************************
+ enum : bool { value = IsStrictlySame< RemoveCV_<A>, RemoveCV_<B> >::value };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Type relationship analysis.
+// \ingroup type_traits
+//
+// This class tests if the two data types \a A and \a B are equal. For this type comparison,
+// the cv-qualifiers of both data types are ignored. If \a A and \a B are the same data type
+// (ignoring the cv-qualifiers), then the \a value member constant is set to \a true, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType.
+// Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class derives from
+// \a FalseType.
+
+ \code
+ blaze::IsSame<int,int>::value // Evaluates to 'true'
+ blaze::IsSame<int,const int>::Type // Results in TrueType
+ blaze::IsSame<float,volatile float> // Is derived from TrueType
+ blaze::IsSame<char,wchar_t>::value // Evaluates to 'false'
+ blaze::IsSame<char,volatile float>::Type // Results in FalseType
+ blaze::IsSame<int,double> // Is derived from FalseType
+ \endcode
+*/
+template< typename A, typename B >
+struct IsSame : public BoolConstant< IsSameHelper<A,B>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsShort.h b/src/cpu/blaze/util/typetraits/IsShort.h
new file mode 100644
index 00000000..16d43831
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsShort.h
@@ -0,0 +1,162 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsShort.h
+// \brief Header file for the IsShort type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISSHORT_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISSHORT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for short integer types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a short integer type
+// (i.e., either (signed) short or unsigned short, possibly cv-qualified). In case the type
+// is a short integer type (ignoring the cv-qualifiers), the \a value member constant is set
+// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from
+// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class
+// derives from \a FalseType.
+
+ \code
+ blaze::IsShort<short>::value // Evaluates to 'true'
+ blaze::IsShort<const unsigned short>::Type // Results in TrueType
+ blaze::IsShort<const volatile signed short> // Is derived from TrueType
+ blaze::IsShort<unsigned int>::value // Evaluates to 'false'
+ blaze::IsShort<const long>::Type // Results in FalseType
+ blaze::IsShort<volatile float> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsShort : public FalseType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsShort type trait for the plain 'short' type.
+template<>
+struct IsShort<short> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsShort type trait for 'const short'.
+template<>
+struct IsShort<const short> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsShort type trait for 'volatile short'.
+template<>
+struct IsShort<volatile short> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsShort type trait for 'const volatile short'.
+template<>
+struct IsShort<const volatile short> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsShort type trait for the plain 'unsigned short' type.
+template<>
+struct IsShort<unsigned short> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsShort type trait for 'const unsigned short'.
+template<>
+struct IsShort<const unsigned short> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsShort type trait for 'volatile unsigned short'.
+template<>
+struct IsShort<volatile unsigned short> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsShort type trait for 'const volatile unsigned short'.
+template<>
+struct IsShort<const volatile unsigned short> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsSigned.h b/src/cpu/blaze/util/typetraits/IsSigned.h
new file mode 100644
index 00000000..51ddb39c
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsSigned.h
@@ -0,0 +1,83 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsSigned.h
+// \brief Header file for the IsSigned type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISSIGNED_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISSIGNED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for signed data types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a signed integral
+// or a floating point data type. In case the type is a signed (possibly cv-qualified) data
+// type, the \a value member constant is set to \a true, the nested type definition \a Type
+// is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set to
+// \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ class MyClass {};
+
+ blaze::IsSigned<short>::value // Evaluates to 'true'
+ blaze::IsSigned<const int>::Type // Results in TrueType
+ blaze::IsSigned<volatile float> // Is derived from TrueType
+ blaze::IsSigned<unsigned int>::value // Evaluates to 'false'
+ blaze::IsSigned<const unsigned long>::Type // Results in FalseType
+ blaze::IsSigned<MyClass> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsSigned : public BoolConstant< std::is_signed<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsUnion.h b/src/cpu/blaze/util/typetraits/IsUnion.h
new file mode 100644
index 00000000..d164686b
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsUnion.h
@@ -0,0 +1,84 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsUnion.h
+// \brief Header file for the IsUnion type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISUNION_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISUNION_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for union data types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is a union data type.
+// In case the type is a union, the \a value member constant is set o \a true, the nested
+// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise
+// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ union A {
+ // ...
+ };
+
+ blaze::IsUnion<A>::value // Evaluates to 'true'
+ blaze::IsUnion<A const>::Type // Results in TrueType
+ blaze::IsUnion<A volatile> // Is derived from TrueType
+ blaze::IsUnion<int>::value // Evaluates to 'false'
+ blaze::IsUnion<double>::Type // Results in FalseType
+ blaze::IsUnion<std::string> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsUnion : public BoolConstant< std::is_union<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsUnsigned.h b/src/cpu/blaze/util/typetraits/IsUnsigned.h
new file mode 100644
index 00000000..b1d91831
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsUnsigned.h
@@ -0,0 +1,83 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsUnsigned.h
+// \brief Header file for the IsUnsigned type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISUNSIGNED_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISUNSIGNED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for unsigned data types.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is an unsigned, integral
+// data type. In case the type is an unsigned (possibly cv-qualified) data type, the \a value
+// member constant is set to \a true, the nested type definition \a Type is \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ class MyClass {};
+
+ blaze::IsUnsigned<unsigned short>::value // Evaluates to 'true'
+ blaze::IsUnsigned<const unsigned int>::Type // Results in TrueType
+ blaze::IsUnsigned<volatile unsigned long> // Is derived from TrueType
+ blaze::IsUnsigned<float>::value // Evaluates to 'false'
+ blaze::IsUnsigned<const volatile int>::Type // Results in FalseType
+ blaze::IsUnsigned<MyClass> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsUnsigned : public BoolConstant< std::is_unsigned<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsValid.h b/src/cpu/blaze/util/typetraits/IsValid.h
new file mode 100644
index 00000000..6c3cca6f
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsValid.h
@@ -0,0 +1,122 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsValid.h
+// \brief Header file for the IsValid type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISVALID_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISVALID_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/InvalidType.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type check.
+// \ingroup type_traits
+//
+// This class tests whether the given template parameter is a valid or invalid data type (i.e.
+// if the type is the INVALID_TYPE). If \a T is not the INVALID_TYPE class type, the \a value
+// member constant is set to \a true, the nested type definition \a Type is \a TrueType, and
+// the class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsValid<int>::value // Evaluates to 'true'
+ blaze::IsValid<float const>::Type // Results in TrueType
+ blaze::IsValid<double volatile> // Is derived from TrueType
+ blaze::IsValid<INVALID_TYPE>::value // Evaluates to 'false'
+ blaze::IsValid<INVALID_TYPE const>::Type // Results in FalseType
+ blaze::IsValid<INVALID_TYPE volatile> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsValid : public TrueType
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsValid type trait for the plain 'INVALID_TYPE' type.
+template<>
+struct IsValid<INVALID_TYPE> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsValid type trait for 'const INVALID_TYPE'.
+template<>
+struct IsValid<const INVALID_TYPE> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsValid type trait for 'volatile INVALID_TYPE'.
+template<>
+struct IsValid<volatile INVALID_TYPE> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the IsValid type trait for 'const volatile INVALID_TYPE'.
+template<>
+struct IsValid<const volatile INVALID_TYPE> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsVectorizable.h b/src/cpu/blaze/util/typetraits/IsVectorizable.h
new file mode 100644
index 00000000..cb73f894
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsVectorizable.h
@@ -0,0 +1,139 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsVectorizable.h
+// \brief Header file for the IsVectorizable type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISVECTORIZABLE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISVECTORIZABLE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/system/Vectorization.h>
+#include <blaze/util/mpl/If.h>
+#include <blaze/util/typetraits/IsComplex.h>
+#include <blaze/util/typetraits/IsFloat.h>
+#include <blaze/util/typetraits/IsNumeric.h>
+#include <blaze/util/typetraits/RemoveCV.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Auxiliary helper struct for the IsVectorizable type trait.
+// \ingroup type_traits
+*/
+template< typename T >
+struct IsVectorizableHelper
+{
+ private:
+ //**struct Builtin******************************************************************************
+ template< typename BT >
+ struct Builtin { typedef BT Type; };
+ //**********************************************************************************************
+
+ //**struct Complex******************************************************************************
+ template< typename CT >
+ struct Complex { typedef typename CT::value_type Type; };
+ //**********************************************************************************************
+
+ //**********************************************************************************************
+ typedef typename If_< IsComplex<T>, Complex<T>, Builtin<T> >::Type T2;
+ //**********************************************************************************************
+
+ public:
+ //**********************************************************************************************
+ enum : bool { value = ( bool( BLAZE_SSE_MODE ) && IsFloat<T2>::value ) ||
+ ( bool( BLAZE_SSE2_MODE ) && IsNumeric<T2>::value ) ||
+ ( bool( BLAZE_MIC_MODE ) && IsNumeric<T2>::value && sizeof(T2) >= 4UL ) };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Specialization of the IsVectorizableHelper class template for 'void'.
+// \ingroup type_traits
+*/
+template<>
+struct IsVectorizableHelper<void>
+{
+ public:
+ //**********************************************************************************************
+ enum : bool { value = false };
+ //**********************************************************************************************
+};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Compile time check for vectorizable types.
+// \ingroup type_traits
+//
+// Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...),
+// this type trait tests whether or not the given template parameter is a vectorizable type,
+// i.e. a type for which intrinsic vector operations and optimizations can be used. Currently,
+// all built-in data types except \c bool and the according complex numbers are considered to
+// be vectorizable types. In case the type is vectorizable, the \a value member constant is
+// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsVectorizable< int >::value // Evaluates to 'true'
+ blaze::IsVectorizable< const float >::Type // Results in TrueType
+ blaze::IsVectorizable< volatile double > // Is derived from TrueType
+ blaze::IsVectorizable< void >::value // Evaluates to 'false'
+ blaze::IsVectorizable< const bool >::Type // Results in FalseType
+ blaze::IsVectorizable< volatile MyClass > // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsVectorizable : public BoolConstant< IsVectorizableHelper< RemoveCV_<T> >::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsVoid.h b/src/cpu/blaze/util/typetraits/IsVoid.h
new file mode 100644
index 00000000..f82b1dbc
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsVoid.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsVoid.h
+// \brief Header file for the IsVoid type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISVOID_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISVOID_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for the \a void data type.
+// \ingroup type_traits
+//
+// This type trait tests whether or not the given template parameter is of type \a void
+// (ignoring the cv-qualifiers). In case the type is of type \a void, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the
+// class derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is
+// \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsVoid<void>::value // Evaluates to 'true'
+ blaze::IsVoid<const void>::Type // Results in TrueType
+ blaze::IsVoid<const volatile void> // Is derived from TrueType
+ blaze::IsVoid<int>::value // Evaluates to 'false'
+ blaze::IsVoid<const char>::Type // Results in FalseType
+ blaze::IsVoid<volatile float> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsVoid : public BoolConstant< std::is_void<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/IsVolatile.h b/src/cpu/blaze/util/typetraits/IsVolatile.h
new file mode 100644
index 00000000..297da60c
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/IsVolatile.h
@@ -0,0 +1,81 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/IsVolatile.h
+// \brief Header file for the IsVolatile type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_ISVOLATILE_H_
+#define _BLAZE_UTIL_TYPETRAITS_ISVOLATILE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for volatile data types.
+// \ingroup type_traits
+//
+// The IsVolatile type trait tests whether or not the given template parameter is a (top level)
+// volatile-qualified data type. In case the given data type is volatile, the \a value member
+// constant is set to \a true, the nested type definition \a Type is \a TrueType, and the class
+// derives from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType,
+// and the class derives from \a FalseType.
+
+ \code
+ blaze::IsVolatile<volatile int>::value // Evaluates to 'true'
+ blaze::IsVolatile<const volatile int>::Type // Results in TrueType
+ blaze::IsVolatile<int* volatile> // Is derived from TrueType
+ blaze::IsVolatile<volatile int*>::value // Evaluates to 'false' (the volatile qualifier is not at the top level)
+ blaze::IsVolatile<const int>::Type // Results in FalseType
+ blaze::IsVolatile<int> // Is derived from FalseType
+ \endcode
+*/
+template< typename T >
+struct IsVolatile : public BoolConstant< std::is_volatile<T>::value >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/MakeSigned.h b/src/cpu/blaze/util/typetraits/MakeSigned.h
new file mode 100644
index 00000000..52ac3947
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/MakeSigned.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/MakeSigned.h
+// \brief Header file for the MakeSigned type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_MAKESIGNED_H_
+#define _BLAZE_UTIL_TYPETRAITS_MAKESIGNED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type conversion into a signed integral type.
+// \ingroup type_traits
+//
+// This type trait provides the feature to convert the given integral or constant type \a T to
+// the corresponding signed integral data type with the same size and with the same cv-qualifiers.
+// Note that in case \a T is bool or a non-integral data type, a compilation error is created.
+
+ \code
+ enum MyEnum { ... };
+
+ blaze::MakeSigned<int>::Type // Results in 'int'
+ blaze::MakeSigned<const unsigned int>::Type // Results in 'const int'
+ blaze::MakeSigned<const unsigned long>::Type // Results in 'const long'
+ blaze::MakeSigned<MyEnum>::Type // Signed integer type with the same width as the enum
+ blaze::MakeSigned<wchar_t>::Type // Signed integer type with the same width as wchar_t
+ \endcode
+*/
+template< typename T >
+struct MakeSigned
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::make_signed<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the MakeSigned type trait.
+// \ingroup type_traits
+//
+// The MakeSigned_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the MakeSigned class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename MakeSigned<T>::Type;
+ using Type2 = MakeSigned_<T>;
+ \endcode
+*/
+template< typename T >
+using MakeSigned_ = typename MakeSigned<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/MakeUnsigned.h b/src/cpu/blaze/util/typetraits/MakeUnsigned.h
new file mode 100644
index 00000000..b02f9b5e
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/MakeUnsigned.h
@@ -0,0 +1,104 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/MakeUnsigned.h
+// \brief Header file for the MakeUnsigned type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_MAKEUNSIGNED_H_
+#define _BLAZE_UTIL_TYPETRAITS_MAKEUNSIGNED_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time type conversion into an unsigned integral type.
+// \ingroup type_traits
+//
+// This type trait provides the feature to convert the given integral or constant type \a T to
+// the corresponding unsigned integral data type with the same size and with the same cv-qualifiers.
+// Note that in case \a T is bool or a non-integral data type, a compilation error is created.
+
+ \code
+ enum MyEnum { ... };
+
+ blaze::MakeUnsigned<int>::Type // Results in 'unsigned int'
+ blaze::MakeUnsigned<const unsigned int>::Type // Results in 'const unsigned int'
+ blaze::MakeUnsigned<const unsigned long>::Type // Results in 'const unsigned long'
+ blaze::MakeUnsigned<MyEnum>::Type // Unsigned integer type with the same width as the enum
+ blaze::MakeUnsigned<wchar_t>::Type // Unsigned integer type with the same width as wchar_t
+ \endcode
+*/
+template< typename T >
+struct MakeUnsigned
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::make_unsigned<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the MakeUnsigned type trait.
+// \ingroup type_traits
+//
+// The MakeUnsigned_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the MakeUnsigned class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename MakeUnsigned<T>::Type;
+ using Type2 = MakeUnsigned_<T>;
+ \endcode
+*/
+template< typename T >
+using MakeUnsigned_ = typename MakeUnsigned<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/Rank.h b/src/cpu/blaze/util/typetraits/Rank.h
new file mode 100644
index 00000000..406ea9e5
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/Rank.h
@@ -0,0 +1,98 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/Rank.h
+// \brief Header file for the Rank type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_RANK_H_
+#define _BLAZE_UTIL_TYPETRAITS_RANK_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for array ranks.
+// \ingroup type_traits
+//
+// This type trait determines the rank of the given template argument. In case the given type
+// is an array type, the nested \a value member constant is set to the number of dimensions
+// of \a T. Otherwise \a value is set to 0.
+
+ \code
+ blaze::Rank< int[] >::value // Evaluates to 1
+ blaze::Rank< int[3] >::value // Evaluates to 1
+ blaze::Rank< const int[2][3][4] >::value // Evaluates to 3
+ blaze::Rank< int[][3] >::value // Evaluates to 2
+ blaze::Rank< int const* >::value // Evaluates to 0
+ blaze::Rank< std::vector<int> >::value // Evaluates to 0
+ \endcode
+*/
+template< typename T >
+struct Rank : public IntegralConstant<size_t,0UL>
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the Rank type trait for empty arrays.
+template< typename T >
+struct Rank<T[]> : public IntegralConstant<size_t,1UL+Rank<T>::value>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+//! Specialization of the Rank type trait for non-empty arrays.
+template< typename T, unsigned int N >
+struct Rank<T[N]> : public IntegralConstant<size_t,1UL+Rank<T>::value>
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/RemoveAllExtents.h b/src/cpu/blaze/util/typetraits/RemoveAllExtents.h
new file mode 100644
index 00000000..18c4d482
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/RemoveAllExtents.h
@@ -0,0 +1,101 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/RemoveAllExtents.h
+// \brief Header file for the RemoveAllExtents type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_REMOVEALLEXTENTS_H_
+#define _BLAZE_UTIL_TYPETRAITS_REMOVEALLEXTENTS_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Removal of all array extents.
+// \ingroup type_traits
+//
+// The RemoveAllExtents type trait removes all array extents from the given type \a T.
+
+ \code
+ blaze::RemoveAllExtents<int>::Type // Results in 'int'
+ blaze::RemoveAllExtents<int const[2]>::Type // Results in 'int const'
+ blaze::RemoveAllExtents<int[2][4]>::Type // Results in 'int'
+ blaze::RemoveAllExtents<int[][2]>::Type // Results in 'int'
+ blaze::RemoveAllExtents<int[2][3][4]>::Type // Results in 'int'
+ blaze::RemoveAllExtents<int const*>::Type // Results in 'int const*'
+ \endcode
+*/
+template< typename T >
+struct RemoveAllExtents
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::remove_all_extents<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RemoveAllExtents type trait.
+// \ingroup type_traits
+//
+// The RemoveAllExtents_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the RemoveAllExtents class template. For instance, given the type \a T the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename RemoveAllExtents<T>::Type;
+ using Type2 = RemoveAllExtents_<T>;
+ \endcode
+*/
+template< typename T >
+using RemoveAllExtents_ = typename RemoveAllExtents<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/RemoveCV.h b/src/cpu/blaze/util/typetraits/RemoveCV.h
new file mode 100644
index 00000000..6e661c84
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/RemoveCV.h
@@ -0,0 +1,102 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/RemoveCV.h
+// \brief Header file for the RemoveCV type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_REMOVECV_H_
+#define _BLAZE_UTIL_TYPETRAITS_REMOVECV_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Removal of top level cv-qualifiers.
+// \ingroup type_traits
+//
+// The RemoveCV type trait removes all top level cv-qualifiers from the given type \a T.
+
+ \code
+ blaze::RemoveCV<short>::Type // Results in 'short'
+ blaze::RemoveCV<const double>::Type // Results in 'double'
+ blaze::RemoveCV<volatile float>::Type // Results in 'float'
+ blaze::RemoveCV<const volatile int>::Type // Results in 'int'
+ blaze::RemoveCV<int const*>::Type // Results in 'int const*'
+ blaze::RemoveCV<int const* const>::Type // Results in 'int const*'
+ blaze::RemoveCV<int const&>::Type // Results in 'int const&'
+ \endcode
+*/
+template< typename T >
+struct RemoveCV
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::remove_cv<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RemoveCV type trait.
+// \ingroup type_traits
+//
+// The RemoveCV_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the RemoveCV class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename RemoveCV<T>::Type;
+ using Type2 = RemoveCV_<T>;
+ \endcode
+*/
+template< typename T >
+using RemoveCV_ = typename RemoveCV<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/RemoveConst.h b/src/cpu/blaze/util/typetraits/RemoveConst.h
new file mode 100644
index 00000000..dca77e03
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/RemoveConst.h
@@ -0,0 +1,101 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/RemoveConst.h
+// \brief Header file for the RemoveConst type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_REMOVECONST_H_
+#define _BLAZE_UTIL_TYPETRAITS_REMOVECONST_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Removal of const-qualifiers.
+// \ingroup type_traits
+//
+// The RemoveConst type trait removes all top level 'const' qualifiers from the given type \a T.
+
+ \code
+ blaze::RemoveConst<short>::Type // Results in 'short'
+ blaze::RemoveConst<const double>::Type // Results in 'double'
+ blaze::RemoveConst<const volatile int>::Type // Results in 'volatile int'
+ blaze::RemoveConst<int const*>::Type // Results in 'const int*'
+ blaze::RemoveConst<int const* const>::Type // Results in 'const int*'
+ blaze::RemoveConst<int const&>::Type // Results in 'const int&'
+ \endcode
+*/
+template< typename T >
+struct RemoveConst
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::remove_const<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RemoveConst type trait.
+// \ingroup type_traits
+//
+// The RemoveConst_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the RemoveConst class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename RemoveConst<T>::Type;
+ using Type2 = RemoveConst_<T>;
+ \endcode
+*/
+template< typename T >
+using RemoveConst_ = typename RemoveConst<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/RemoveExtent.h b/src/cpu/blaze/util/typetraits/RemoveExtent.h
new file mode 100644
index 00000000..70e9aeae
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/RemoveExtent.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/RemoveExtent.h
+// \brief Header file for the RemoveExtent type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_REMOVEEXTENT_H_
+#define _BLAZE_UTIL_TYPETRAITS_REMOVEEXTENT_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Removal of the top level array extent.
+// \ingroup type_traits
+//
+// The RemoveExtent type trait removes the top level array extent from the given type \a T.
+
+ \code
+ blaze::RemoveExtent<int>::Type // Results in 'int'
+ blaze::RemoveExtent<int const[2]>::Type // Results in 'int const'
+ blaze::RemoveExtent<int[2][4]>::Type // Results in 'int[4]'
+ blaze::RemoveExtent<int[][2]>::Type // Results in 'int[2]'
+ blaze::RemoveExtent<int const*>::Type // Results in 'int const*'
+ \endcode
+*/
+template< typename T >
+struct RemoveExtent
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::remove_extent<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RemoveExtent type trait.
+// \ingroup type_traits
+//
+// The RemoveExtent_ alias declaration provides a convenient shortcut to access the nested \a Type
+// of the RemoveExtent class template. For instance, given the type \a T the following two type
+// definitions are identical:
+
+ \code
+ using Type1 = typename RemoveExtent<T>::Type;
+ using Type2 = RemoveExtent_<T>;
+ \endcode
+*/
+template< typename T >
+using RemoveExtent_ = typename RemoveExtent<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/RemovePointer.h b/src/cpu/blaze/util/typetraits/RemovePointer.h
new file mode 100644
index 00000000..eea4ff49
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/RemovePointer.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/RemovePointer.h
+// \brief Header file for the RemovePointer type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_REMOVEPOINTER_H_
+#define _BLAZE_UTIL_TYPETRAITS_REMOVEPOINTER_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Removal of pointer modifiers.
+// \ingroup type_traits
+//
+// The RemovePointer type trait removes any pointer modifiers from the given type \a T.
+
+ \code
+ blaze::RemovePointer<int>::Type // Results in 'int'
+ blaze::RemovePointer<const int*>::Type // Results in 'const int'
+ blaze::RemovePointer<volatile int**>::Type // Results in 'volatile int*'
+ blaze::RemovePointer<int&>::Type // Results in 'int&'
+ blaze::RemovePointer<int*&>::Type // Results in 'int*&'
+ \endcode
+*/
+template< typename T >
+struct RemovePointer
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::remove_pointer<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RemovePointer type trait.
+// \ingroup type_traits
+//
+// The RemovePointer_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the RemovePointer class template. For instance, given the type \a T the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename RemovePointer<T>::Type;
+ using Type2 = RemovePointer_<T>;
+ \endcode
+*/
+template< typename T >
+using RemovePointer_ = typename RemovePointer<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/RemoveReference.h b/src/cpu/blaze/util/typetraits/RemoveReference.h
new file mode 100644
index 00000000..bba8ec19
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/RemoveReference.h
@@ -0,0 +1,100 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/RemoveReference.h
+// \brief Header file for the RemoveReference type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_REMOVEREFERENCE_H_
+#define _BLAZE_UTIL_TYPETRAITS_REMOVEREFERENCE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Removal of reference modifiers.
+// \ingroup type_traits
+//
+// The RemoveReference type trait removes any reference modifiers from the given type \a T.
+
+ \code
+ blaze::RemoveReference<int>::Type // Results in 'int'
+ blaze::RemoveReference<const int&>::Type // Results in 'const int'
+ blaze::RemoveReference<volatile int&&>::Type // Results in 'volatile int'
+ blaze::RemoveReference<int*>::Type // Results in 'int*'
+ blaze::RemoveReference<int*&>::Type // Results in 'int*'
+ \endcode
+*/
+template< typename T >
+struct RemoveReference
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::remove_reference<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RemoveReference type trait.
+// \ingroup type_traits
+//
+// The RemoveReference_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the RemoveReference class template. For instance, given the type \a T the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename RemoveReference<T>::Type;
+ using Type2 = RemoveReference_<T>;
+ \endcode
+*/
+template< typename T >
+using RemoveReference_ = typename RemoveReference<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/RemoveVolatile.h b/src/cpu/blaze/util/typetraits/RemoveVolatile.h
new file mode 100644
index 00000000..31a502da
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/RemoveVolatile.h
@@ -0,0 +1,102 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/RemoveVolatile.h
+// \brief Header file for the RemoveVolatile type trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_REMOVEVOLATILE_H_
+#define _BLAZE_UTIL_TYPETRAITS_REMOVEVOLATILE_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <type_traits>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Removal of volatile-qualifiers.
+// \ingroup type_traits
+//
+// The RemoveVolatile type trait removes all top level 'volatile' qualifiers from the given
+// type \a T.
+
+ \code
+ blaze::RemoveVolatile<short>::Type // Results in 'short'
+ blaze::RemoveVolatile<volatile double>::Type // Results in 'double'
+ blaze::RemoveVolatile<const volatile int>::Type // Results in 'const int'
+ blaze::RemoveVolatile<int volatile*>::Type // Results in 'int volatile*'
+ blaze::RemoveVolatile<int volatile* volatile>::Type // Results in 'int volatile*'
+ blaze::RemoveVolatile<int volatile&>::Type // Results in 'int volatile&'
+ \endcode
+*/
+template< typename T >
+struct RemoveVolatile
+{
+ public:
+ //**********************************************************************************************
+ /*! \cond BLAZE_INTERNAL */
+ typedef typename std::remove_volatile<T>::type Type;
+ /*! \endcond */
+ //**********************************************************************************************
+};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Auxiliary alias declaration for the RemoveVolatile type trait.
+// \ingroup type_traits
+//
+// The RemoveVolatile_ alias declaration provides a convenient shortcut to access the nested
+// \a Type of the RemoveVolatile class template. For instance, given the type \a T the following
+// two type definitions are identical:
+
+ \code
+ using Type1 = typename RemoveVolatile<T>::Type;
+ using Type2 = RemoveVolatile_<T>;
+ \endcode
+*/
+template< typename T >
+using RemoveVolatile_ = typename RemoveVolatile<T>::Type;
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/typetraits/TypeTraits.h b/src/cpu/blaze/util/typetraits/TypeTraits.h
new file mode 100644
index 00000000..ae6824fb
--- /dev/null
+++ b/src/cpu/blaze/util/typetraits/TypeTraits.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/util/typetraits/TypeTraits.h
+// \brief Type traits module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_TYPETRAITS_TYPETRAITS_H_
+#define _BLAZE_UTIL_TYPETRAITS_TYPETRAITS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup type_traits Type traits
+// \ingroup util
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/blaze/util/valuetraits/IsEven.h b/src/cpu/blaze/util/valuetraits/IsEven.h
new file mode 100644
index 00000000..60046d13
--- /dev/null
+++ b/src/cpu/blaze/util/valuetraits/IsEven.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/util/valuetraits/IsEven.h
+// \brief Header file for the IsEven value trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_VALUETRAITS_ISEVEN_H_
+#define _BLAZE_UTIL_VALUETRAITS_ISEVEN_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether a compile time constant expression is even.
+// \ingroup value_traits
+//
+// This value trait tests whether the given integral value \a N is an even value. In case the
+// value is even, the \a value member enumeration is set to \a true, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to \a false, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsEven<2>::value // Evaluates to 1
+ blaze::IsEven<4>::Type // Results in TrueType
+ blaze::IsEven<6> // Is derived from TrueType
+ blaze::IsEven<1>::value // Evaluates to 0
+ blaze::IsEven<3>::Type // Results in FalseType
+ blaze::IsEven<5> // Is derived from FalseType
+ \endcode
+*/
+template< size_t N >
+struct IsEven : public BoolConstant< N % 2UL == 0UL >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/valuetraits/IsMultipleOf.h b/src/cpu/blaze/util/valuetraits/IsMultipleOf.h
new file mode 100644
index 00000000..c03be1ec
--- /dev/null
+++ b/src/cpu/blaze/util/valuetraits/IsMultipleOf.h
@@ -0,0 +1,109 @@
+//=================================================================================================
+/*!
+// \file blaze/util/valuetraits/IsMultipleOf.h
+// \brief Header file for the IsMultipleOf value trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_VALUETRAITS_ISMULTIPLEOF_H_
+#define _BLAZE_UTIL_VALUETRAITS_ISMULTIPLEOF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for a multiplicative relationship of two integral values.
+// \ingroup value_traits
+//
+// This value trait tests whether the first given integral value \a M is a multiple of the second
+// integral value \a N (i.e. if \f$ M = x*N \f$, where x is any positive integer in the range
+// \f$ [0..\infty) \f$). In case the value is a multiple of \a N, the \a value member enumeration
+// is set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsMultipleOf<8,2>::value // Evaluates to 1 (x*2 = 8 for x = 4)
+ blaze::IsMultipleOf<2,2>::value // Evaluates to 1 (x*2 = 2 for x = 1)
+ blaze::IsMultipleOf<0,2>::Type // Results in TrueType (x*2 = 0 for x = 0)
+ blaze::IsMultipleOf<0,0> // Is derived from TrueType (x*0 = 0 for any x)
+
+ blaze::IsMultipleOf<5,3>::value // Evaluates to 0 (5 is no integral multiple of 3)
+ blaze::IsMultipleOf<2,3>::Type // Results in TrueType (2 is no integral multiple of 3)
+ blaze::IsMultipleOf<2,0> // Is derived from TrueType (2 is no multiple of 0)
+ \endcode
+*/
+template< size_t M, size_t N >
+struct IsMultipleOf : public BoolConstant< M % N == 0UL >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsMultipleOf value trait for M > 0 and N = 0.
+// \ingroup type_traits
+*/
+template< size_t M >
+struct IsMultipleOf<M,0UL> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsMultipleOf value trait for M = 0 and N = 0.
+// \ingroup type_traits
+*/
+template<>
+struct IsMultipleOf<0,0> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/valuetraits/IsOdd.h b/src/cpu/blaze/util/valuetraits/IsOdd.h
new file mode 100644
index 00000000..a9186b9d
--- /dev/null
+++ b/src/cpu/blaze/util/valuetraits/IsOdd.h
@@ -0,0 +1,79 @@
+//=================================================================================================
+/*!
+// \file blaze/util/valuetraits/IsOdd.h
+// \brief Header file for the IsEven value trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_VALUETRAITS_ISODD_H_
+#define _BLAZE_UTIL_VALUETRAITS_ISODD_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/IntegralConstant.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check whether a compile time constant expression is odd.
+// \ingroup value_traits
+//
+// This value trait tests whether the given integral value \a N is an odd value. In case the
+// value is odd, the \a value member enumeration is set to 1, the nested type definition
+// \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value is set
+// to 0, \a Type is \a FalseType, and the class derives from \a FalseType.
+
+ \code
+ blaze::IsOdd<1>::value // Evaluates to 1
+ blaze::IsOdd<3>::Type // Results in TrueType
+ blaze::IsOdd<5> // Is derived from TrueType
+ blaze::IsOdd<2>::value // Evaluates to 0
+ blaze::IsOdd<4>::Type // Results in FalseType
+ blaze::IsOdd<6> // Is derived from FalseType
+ \endcode
+*/
+template< size_t N >
+struct IsOdd : public BoolConstant< N % 2UL != 0UL >
+{};
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/valuetraits/IsPowerOf.h b/src/cpu/blaze/util/valuetraits/IsPowerOf.h
new file mode 100644
index 00000000..5fa03129
--- /dev/null
+++ b/src/cpu/blaze/util/valuetraits/IsPowerOf.h
@@ -0,0 +1,221 @@
+//=================================================================================================
+/*!
+// \file blaze/util/valuetraits/IsPowerOf.h
+// \brief Header file for the IsPowerOf value trait
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_VALUETRAITS_ISPOWEROF_H_
+#define _BLAZE_UTIL_VALUETRAITS_ISPOWEROF_H_
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <blaze/util/FalseType.h>
+#include <blaze/util/IntegralConstant.h>
+#include <blaze/util/TrueType.h>
+
+
+namespace blaze {
+
+//=================================================================================================
+//
+// CLASS DEFINITION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\brief Compile time check for a power relationship of integral values to a given base.
+// \ingroup value_traits
+//
+// This value trait tests whether the given integral value \a N is a power of the base \a B
+// according to the equation \f$ B^x = N \f$, where x is any positive integer in the range
+// \f$ [0..\infty) \f$. In case the value is a power of \a B, the \a value member enumeration
+// is set to \a true, the nested type definition \a Type is \a TrueType, and the class derives
+// from \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the
+// class derives from \a FalseType.
+
+ \code
+ blaze::IsPowerOf<2,8>::value // Evaluates to 1 (2^3 = 8)
+ blaze::IsPowerOf<3,27>::value // Evaluates to 1 (3^3 = 27)
+ blaze::IsPowerOf<5,1>::value // Evaluates to 1 (5^0 = 1)
+ blaze::IsPowerOf<1,1>::Type // Results in TrueType (1^x = 1)
+ blaze::IsPowerOf<0,0> // Is derived from TrueType (0^x = 0)
+ blaze::IsPowerOf<2,14>::value // Evaluates to 0
+ blaze::IsPowerOf<1,5>::value // Evaluates to 0
+ blaze::IsPowerOf<0,5>::Type // Results in FalseType
+ blaze::IsPowerOf<2,0> // Is derived from FalseType
+ \endcode
+*/
+template< size_t B, size_t N >
+struct IsPowerOf : public BoolConstant< IsPowerOf<B,N/B>::value >
+{};
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsPowerOf value trait.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the IsPowerOf value trait for any value \a N to
+// the base 2. In case \a N is a power of 2, the \a value member enumeration is set to 1, the
+// nested type definition \a Type is \a TrueType, and the class derives from \a TrueType. If
+// not, \a value is set to 0, \a Type is \a FalseType, and the class derives from \a FalseType.
+*/
+template< size_t N >
+struct IsPowerOf<2,N> : public BoolConstant< ( N & (N-1) ) == 0UL >
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsPowerOf value trait.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the IsPowerOf value trait for the value 0 to the
+// base 2. Since 0 is no power of 2, this specialization sets the \a value member enumeration
+// to 0, the nested type definition \a Type to \a FalseType, and it derives from \a FalseType.
+*/
+template<>
+struct IsPowerOf<2,0> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsPowerOf value trait.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the IsPowerOf value trait for the value 1 to any
+// given base \a B larger than 1. According to the equation \f$ B^0 = 1 \f$ this specialization
+// always sets the \a value member enumeration to 1, the nested type definition \a Type to
+// \a TrueType, and it derives from \a TrueType.
+*/
+template< size_t B >
+struct IsPowerOf<B,1> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsPowerOf value trait.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the IsPowerOf value trait for any value \a N larger
+// than 1 to the base 1. Since N is no power of 1, this specialization always sets the \a value
+// member enumeration to 0, the nested type definition \a Type to \a FalseType, and it derives
+// from \a FalseType.
+*/
+template< size_t N >
+struct IsPowerOf<1,N> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsPowerOf value trait.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the IsPowerOf value trait for the value 1 to
+// the base 1. Since 1 is a power of 1, this specialization always sets the \a value member
+// enumeration to 1, the nested type definition \a Type to \a TrueType, and it derives from
+// \a TrueType.
+*/
+template<>
+struct IsPowerOf<1,1> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsPowerOf value trait.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the IsPowerOf value trait for the value 0 to the
+// base \a B. Since 0 is no power of \a B, this specialization always sets the \a value member
+// enumeration to 0, the nested type definition \a Type to \a FalseType, and it derives from
+// \a FalseType.
+*/
+template< size_t B >
+struct IsPowerOf<B,0> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsPowerOf value trait.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the IsPowerOf value trait for any value \a N to
+// the base 0. Since N is no power of 0, this specialization always sets the \a value member
+// enumeration to 0, the nested type definition \a Type to \a FalseType, and it derives from
+// \a FalseType.
+*/
+template< size_t N >
+struct IsPowerOf<0,N> : public FalseType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*! \cond BLAZE_INTERNAL */
+/*!\brief Partial specialization of the IsPowerOf value trait.
+// \ingroup type_traits
+//
+// This class ia a partial specialization of the IsPowerOf value trait for the value 0 to
+// the base 0. Since 0 is a power of 0 (\f$ 0^x = 0 \f$), this specialization always sets
+// the \a value member enumeration to 1, the nested type definition \a Type to \a TrueType,
+// and it derives from \a TrueType.
+*/
+template<>
+struct IsPowerOf<0,0> : public TrueType
+{};
+/*! \endcond */
+//*************************************************************************************************
+
+} // namespace blaze
+
+#endif
diff --git a/src/cpu/blaze/util/valuetraits/ValueTraits.h b/src/cpu/blaze/util/valuetraits/ValueTraits.h
new file mode 100644
index 00000000..46d59ed6
--- /dev/null
+++ b/src/cpu/blaze/util/valuetraits/ValueTraits.h
@@ -0,0 +1,51 @@
+//=================================================================================================
+/*!
+// \file blaze/util/valuetraits/ValueTraits.h
+// \brief Value traits module documentation
+//
+// Copyright (C) 2013 Klaus Iglberger - All Rights Reserved
+//
+// This file is part of the Blaze library. You can redistribute it and/or modify it under
+// the terms of the New (Revised) BSD License. Redistribution and use in source and binary
+// forms, with or without modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+// 3. Neither the names of the Blaze development group nor the names of its contributors
+// may be used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+*/
+//=================================================================================================
+
+#ifndef _BLAZE_UTIL_VALUETRAITS_VALUETRAITS_H_
+#define _BLAZE_UTIL_VALUETRAITS_VALUETRAITS_H_
+
+
+//=================================================================================================
+//
+// DOXYGEN DOCUMENTATION
+//
+//=================================================================================================
+
+//*************************************************************************************************
+/*!\defgroup value_traits Value traits
+// \ingroup util
+*/
+//*************************************************************************************************
+
+#endif
diff --git a/src/cpu/dl4mt/decoder.h b/src/cpu/dl4mt/decoder.h
new file mode 100644
index 00000000..9ff843db
--- /dev/null
+++ b/src/cpu/dl4mt/decoder.h
@@ -0,0 +1,287 @@
+#pragma once
+
+#include "mblas/matrix.h"
+#include "dl4mt/model.h"
+#include "dl4mt/gru.h"
+
+class Decoder {
+ private:
+ template <class Weights>
+ class Embeddings {
+ public:
+ Embeddings(const Weights& model)
+ : w_(model)
+ {}
+
+ void Lookup(mblas::Matrix& Rows, const std::vector<size_t>& ids) {
+ using namespace mblas;
+ std::vector<size_t> tids = ids;
+ for(auto&& id : tids)
+ if(id >= w_.E_.rows())
+ id = 1;
+ Rows = Assemble<byRow, Matrix>(w_.E_, tids);
+ }
+
+ size_t GetCols() {
+ return w_.E_.columns();
+ }
+
+ size_t GetRows() const {
+ return w_.E_.rows();
+ }
+
+ private:
+ const Weights& w_;
+ };
+
+ //////////////////////////////////////////////////////////////
+ template <class Weights1, class Weights2>
+ class RNNHidden {
+ public:
+ RNNHidden(const Weights1& initModel, const Weights2& gruModel)
+ : w_(initModel), gru_(gruModel) {}
+
+ void InitializeState(mblas::Matrix& State,
+ const mblas::Matrix& SourceContext,
+ const size_t batchSize = 1) {
+ using namespace mblas;
+
+ // Calculate mean of source context, rowwise
+ // Repeat mean batchSize times by broadcasting
+ Temp1_ = Mean<byRow, Matrix>(SourceContext);
+ Temp2_.resize(batchSize, SourceContext.columns());
+ Temp2_ = 0.0f;
+ AddBiasVector<byRow>(Temp2_, Temp1_);
+
+ State = Temp2_ * w_.Wi_;
+ AddBiasVector<byRow>(State, w_.Bi_);
+
+ State = blaze::forEach(State, Tanh());
+ }
+
+ void GetNextState(mblas::Matrix& NextState,
+ const mblas::Matrix& State,
+ const mblas::Matrix& Context) {
+ gru_.GetNextState(NextState, State, Context);
+ }
+
+ private:
+ const Weights1& w_;
+ const GRU<Weights2> gru_;
+
+ mblas::Matrix Temp1_;
+ mblas::Matrix Temp2_;
+ };
+
+ //////////////////////////////////////////////////////////////
+ template <class Weights>
+ class RNNFinal {
+ public:
+ RNNFinal(const Weights& model)
+ : gru_(model) {}
+
+ void GetNextState(mblas::Matrix& NextState,
+ const mblas::Matrix& State,
+ const mblas::Matrix& Context) {
+ gru_.GetNextState(NextState, State, Context);
+ }
+
+ private:
+ const GRU<Weights> gru_;
+ };
+
+ //////////////////////////////////////////////////////////////
+ template <class Weights>
+ class Attention {
+ public:
+ Attention(const Weights& model)
+ : w_(model)
+ {
+ V_ = blaze::trans(blaze::row(w_.V_, 0));
+ }
+
+ void GetAlignedSourceContext(mblas::Matrix& AlignedSourceContext,
+ const mblas::Matrix& HiddenState,
+ const mblas::Matrix& SourceContext) {
+ using namespace mblas;
+
+ Temp1_ = SourceContext * w_.U_;
+ Temp2_ = HiddenState * w_.W_;
+ AddBiasVector<byRow>(Temp2_, w_.B_);
+
+ // For batching: create an A across different sentences,
+ // maybe by mapping and looping. In the and join different
+ // alignment matrices into one
+ // Or masking?
+ Temp1_ = Broadcast<Matrix>(Tanh(), Temp1_, Temp2_);
+
+ A_.resize(Temp1_.rows(), 1);
+ blaze::column(A_, 0) = Temp1_ * V_;
+ size_t words = SourceContext.rows();
+ // batch size, for batching, divide by numer of sentences
+ size_t batchSize = HiddenState.rows();
+ Reshape(A_, batchSize, words); // due to broadcasting above
+
+ float bias = w_.C_(0,0);
+ blaze::forEach(A_, [=](float x) { return x + bias; });
+
+ mblas::Softmax(A_);
+ AlignedSourceContext = A_ * SourceContext;
+ }
+
+ void GetAttention(mblas::Matrix& Attention) {
+ Attention = A_;
+ }
+
+ private:
+ const Weights& w_;
+
+ mblas::Matrix Temp1_;
+ mblas::Matrix Temp2_;
+ mblas::Matrix A_;
+ mblas::ColumnVector V_;
+ };
+
+ //////////////////////////////////////////////////////////////
+ template <class Weights>
+ class Softmax {
+ public:
+ Softmax(const Weights& model)
+ : w_(model),
+ filtered_(false)
+ {}
+
+ void GetProbs(mblas::ArrayMatrix& Probs,
+ const mblas::Matrix& State,
+ const mblas::Matrix& Embedding,
+ const mblas::Matrix& AlignedSourceContext) {
+ using namespace mblas;
+
+ T1_ = State * w_.W1_;
+ T2_ = Embedding * w_.W2_;
+ T3_ = AlignedSourceContext * w_.W3_;
+
+ AddBiasVector<byRow>(T1_, w_.B1_);
+ AddBiasVector<byRow>(T2_, w_.B2_);
+ AddBiasVector<byRow>(T3_, w_.B3_);
+
+ auto t = blaze::forEach(T1_ + T2_ + T3_, Tanh());
+
+ if(!filtered_) {
+ Probs_ = t * w_.W4_;
+ AddBiasVector<byRow>(Probs_, w_.B4_);
+ } else {
+ Probs_ = t * FilteredW4_;
+ AddBiasVector<byRow>(Probs_, FilteredB4_);
+ }
+ mblas::Softmax(Probs_);
+ Probs = blaze::forEach(Probs_, Log());
+ }
+
+ void Filter(const std::vector<size_t>& ids) {
+ filtered_ = true;
+ using namespace mblas;
+ FilteredW4_ = Assemble<byColumn, Matrix>(w_.W4_, ids);
+ FilteredB4_ = Assemble<byColumn, Matrix>(w_.B4_, ids);
+ }
+
+ private:
+ const Weights& w_;
+ bool filtered_;
+
+ mblas::Matrix FilteredW4_;
+ mblas::Matrix FilteredB4_;
+
+ mblas::Matrix T1_;
+ mblas::Matrix T2_;
+ mblas::Matrix T3_;
+ mblas::Matrix Probs_;
+ };
+
+ public:
+ Decoder(const Weights& model)
+ : embeddings_(model.decEmbeddings_),
+ rnn1_(model.decInit_, model.decGru1_),
+ rnn2_(model.decGru2_),
+ attention_(model.decAttention_),
+ softmax_(model.decSoftmax_)
+ {}
+
+ void MakeStep(mblas::Matrix& NextState,
+ mblas::ArrayMatrix& Probs,
+ const mblas::Matrix& State,
+ const mblas::Matrix& Embeddings,
+ const mblas::Matrix& SourceContext) {
+ GetHiddenState(HiddenState_, State, Embeddings);
+ GetAlignedSourceContext(AlignedSourceContext_, HiddenState_, SourceContext);
+ GetNextState(NextState, HiddenState_, AlignedSourceContext_);
+ GetProbs(Probs, NextState, Embeddings, AlignedSourceContext_);
+ }
+
+ void EmptyState(mblas::Matrix& State,
+ const mblas::Matrix& SourceContext,
+ size_t batchSize = 1) {
+ rnn1_.InitializeState(State, SourceContext, batchSize);
+ }
+
+ void EmptyEmbedding(mblas::Matrix& Embedding,
+ size_t batchSize = 1) {
+ Embedding.resize(batchSize, embeddings_.GetCols());
+ Embedding = 0.0f;
+ }
+
+ void Lookup(mblas::Matrix& Embedding,
+ const std::vector<size_t>& w) {
+ embeddings_.Lookup(Embedding, w);
+ }
+
+ void Filter(const std::vector<size_t>& ids) {
+ softmax_.Filter(ids);
+ }
+
+ void GetAttention(mblas::Matrix& attention) {
+ attention_.GetAttention(attention);
+ }
+
+ size_t GetVocabSize() const {
+ return embeddings_.GetRows();
+ }
+
+ private:
+
+ void GetHiddenState(mblas::Matrix& HiddenState,
+ const mblas::Matrix& PrevState,
+ const mblas::Matrix& Embedding) {
+ rnn1_.GetNextState(HiddenState, PrevState, Embedding);
+ }
+
+ void GetAlignedSourceContext(mblas::Matrix& AlignedSourceContext,
+ const mblas::Matrix& HiddenState,
+ const mblas::Matrix& SourceContext) {
+ attention_.GetAlignedSourceContext(AlignedSourceContext, HiddenState, SourceContext);
+ }
+
+ void GetNextState(mblas::Matrix& State,
+ const mblas::Matrix& HiddenState,
+ const mblas::Matrix& AlignedSourceContext) {
+ rnn2_.GetNextState(State, HiddenState, AlignedSourceContext);
+ }
+
+
+ void GetProbs(mblas::ArrayMatrix& Probs,
+ const mblas::Matrix& State,
+ const mblas::Matrix& Embedding,
+ const mblas::Matrix& AlignedSourceContext) {
+ softmax_.GetProbs(Probs, State, Embedding, AlignedSourceContext);
+ }
+
+ private:
+ mblas::Matrix HiddenState_;
+ mblas::Matrix AlignedSourceContext_;
+
+ Embeddings<Weights::Embeddings> embeddings_;
+ RNNHidden<Weights::DecInit, Weights::GRU> rnn1_;
+ RNNFinal<Weights::DecGRU2> rnn2_;
+ Attention<Weights::DecAttention> attention_;
+ Softmax<Weights::DecSoftmax> softmax_;
+};
diff --git a/src/cpu/dl4mt/dl4mt.h b/src/cpu/dl4mt/dl4mt.h
new file mode 100644
index 00000000..380928e1
--- /dev/null
+++ b/src/cpu/dl4mt/dl4mt.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "dl4mt/model.h"
+#include "dl4mt/encoder.h"
+#include "dl4mt/decoder.h"
diff --git a/src/cpu/dl4mt/encoder.cpp b/src/cpu/dl4mt/encoder.cpp
new file mode 100644
index 00000000..3cc55d7e
--- /dev/null
+++ b/src/cpu/dl4mt/encoder.cpp
@@ -0,0 +1,24 @@
+#include "encoder.h"
+
+using namespace std;
+
+void Encoder::GetContext(const std::vector<size_t>& words,
+ mblas::Matrix& context) {
+ std::vector<mblas::Matrix> embeddedWords;
+
+ context.resize(words.size(),
+ forwardRnn_.GetStateLength()
+ + backwardRnn_.GetStateLength());
+ for(auto& w : words) {
+ embeddedWords.emplace_back();
+ mblas::Matrix &embed = embeddedWords.back();
+ embeddings_.Lookup(embed, w);
+ }
+
+ forwardRnn_.GetContext(embeddedWords.cbegin(),
+ embeddedWords.cend(),
+ context, false);
+ backwardRnn_.GetContext(embeddedWords.crbegin(),
+ embeddedWords.crend(),
+ context, true);
+}
diff --git a/src/cpu/dl4mt/encoder.h b/src/cpu/dl4mt/encoder.h
new file mode 100644
index 00000000..b5bafe3b
--- /dev/null
+++ b/src/cpu/dl4mt/encoder.h
@@ -0,0 +1,93 @@
+#pragma once
+
+#include "mblas/matrix.h"
+#include "dl4mt/model.h"
+#include "dl4mt/gru.h"
+
+class Encoder {
+ private:
+
+ /////////////////////////////////////////////////////////////////
+ template <class Weights>
+ class Embeddings {
+ public:
+ Embeddings(const Weights& model)
+ : w_(model)
+ {}
+
+ void Lookup(mblas::Matrix& Row, size_t i) {
+ size_t len = w_.E_.columns();
+ if(i < w_.E_.rows())
+ Row = blaze::submatrix(w_.E_, i, 0, 1, len);
+ else
+ Row = blaze::submatrix(w_.E_, 1, 0, 1, len); // UNK
+ }
+
+ private:
+ const Weights& w_;
+ };
+
+ /////////////////////////////////////////////////////////////////
+ template <class Weights>
+ class RNN {
+ public:
+ RNN(const Weights& model)
+ : gru_(model) {}
+
+ void InitializeState(size_t batchSize = 1) {
+ State_.resize(batchSize, gru_.GetStateLength());
+ State_ = 0.0f;
+ }
+
+ void GetNextState(mblas::Matrix& NextState,
+ const mblas::Matrix& State,
+ const mblas::Matrix& Embd) {
+ gru_.GetNextState(NextState, State, Embd);
+ }
+
+ template <class It>
+ void GetContext(It it, It end,
+ mblas::Matrix& Context, bool invert) {
+ InitializeState();
+
+ size_t n = std::distance(it, end);
+ size_t i = 0;
+ while(it != end) {
+ GetNextState(State_, State_, *it++);
+
+ size_t len = gru_.GetStateLength();
+ if(invert)
+ blaze::submatrix(Context, n - i - 1, len, 1, len) = State_;
+ else
+ blaze::submatrix(Context, i, 0, 1, len) = State_;
+ ++i;
+ }
+ }
+
+ size_t GetStateLength() const {
+ return gru_.GetStateLength();
+ }
+
+ private:
+ // Model matrices
+ const GRU<Weights> gru_;
+
+ mblas::Matrix State_;
+ };
+
+ /////////////////////////////////////////////////////////////////
+ public:
+ Encoder(const Weights& model)
+ : embeddings_(model.encEmbeddings_),
+ forwardRnn_(model.encForwardGRU_),
+ backwardRnn_(model.encBackwardGRU_)
+ {}
+
+ void GetContext(const std::vector<size_t>& words,
+ mblas::Matrix& context);
+
+ private:
+ Embeddings<Weights::Embeddings> embeddings_;
+ RNN<Weights::GRU> forwardRnn_;
+ RNN<Weights::GRU> backwardRnn_;
+};
diff --git a/src/cpu/dl4mt/gru.h b/src/cpu/dl4mt/gru.h
new file mode 100644
index 00000000..993cc40f
--- /dev/null
+++ b/src/cpu/dl4mt/gru.h
@@ -0,0 +1,76 @@
+#pragma once
+#include "mblas/matrix.h"
+
+template <class Weights>
+class GRU {
+ public:
+ GRU(const Weights& model)
+ : w_(model) {
+ using namespace mblas;
+ WWx_ = Concat<byColumn, Matrix>(w_.W_, w_.Wx_);
+ UUx_ = Concat<byColumn, Matrix>(w_.U_, w_.Ux_);
+ }
+
+ void GetNextState(mblas::Matrix& NextState,
+ const mblas::Matrix& State,
+ const mblas::Matrix& Context) const {
+ RUH_ = Context * WWx_;
+ Temp_ = State * UUx_;
+
+ // @TODO: once broadcasting is available
+ // implement this using blaze idioms
+ ElementwiseOps(NextState, State);
+ }
+
+ void ElementwiseOps(mblas::Matrix& NextState,
+ const mblas::Matrix& State) const {
+
+ using namespace mblas;
+ using namespace blaze;
+
+ const size_t rowNo = State.rows();
+ const size_t colNo = State.columns();
+ NextState.resize(rowNo, colNo);
+
+ for(int j = 0; j < rowNo; ++j) {
+ auto rowOut = row(NextState, j);
+ auto rowState = row(State, j);
+
+ auto rowRuh = row(RUH_, j);
+ auto rowT = row(Temp_, j);
+
+ auto rowH = subvector(rowRuh, 2 * colNo, colNo);
+ auto rowT2 = subvector(rowT, 2 * colNo, colNo);
+
+ for(int i = 0; i < colNo; ++i) {
+ float ev1 = expapprox(-(rowRuh[i] + w_.B_(0, i) + rowT[i]));
+ float r = 1.0 / (1.0 + ev1);
+
+ int k = i + colNo;
+ float ev2 = expapprox(-(rowRuh[k] + w_.B_(0, k) + rowT[k]));
+ float u = 1.0 / (1.0 + ev2);
+
+ float hv = rowH[i] + w_.Bx1_(0, i);
+ float t2v = rowT2[i] + w_.Bx2_(0, i);
+ hv = tanhapprox(hv + r * t2v);
+ rowOut[i] = (1.0 - u) * hv + u * rowState[i];
+ }
+ }
+
+ }
+
+ size_t GetStateLength() const {
+ return w_.U_.rows();
+ }
+
+
+ private:
+ // Model matrices
+ const Weights& w_;
+ mutable mblas::Matrix WWx_;
+ mutable mblas::Matrix UUx_;
+
+ // reused to avoid allocation
+ mutable mblas::Matrix RUH_;
+ mutable mblas::Matrix Temp_;
+};
diff --git a/src/cpu/dl4mt/model.cpp b/src/cpu/dl4mt/model.cpp
new file mode 100644
index 00000000..29690358
--- /dev/null
+++ b/src/cpu/dl4mt/model.cpp
@@ -0,0 +1,74 @@
+#include "model.h"
+
+using namespace std;
+
+Weights::Embeddings::Embeddings(const NpzConverter& model, const std::string &key)
+: E_(model[key])
+{}
+
+Weights::GRU::GRU(const NpzConverter& model, const std::vector<std::string> &keys)
+: W_(model[keys.at(0)]),
+ B_(model(keys.at(1), true)),
+ U_(model[keys.at(2)]),
+ Wx_(model[keys.at(3)]),
+ Bx1_(model(keys.at(4), true)),
+ Bx2_(Bx1_.rows(), Bx1_.columns()),
+ Ux_(model[keys.at(5)])
+{
+ const_cast<mblas::Matrix&>(Bx2_) = 0.0f;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+Weights::DecInit::DecInit(const NpzConverter& model)
+: Wi_(model["ff_state_W"]),
+ Bi_(model("ff_state_b", true))
+{}
+
+Weights::DecGRU2::DecGRU2(const NpzConverter& model)
+: W_(model["decoder_Wc"]),
+ B_(model("decoder_b_nl", true)),
+ U_(model["decoder_U_nl"]),
+ Wx_(model["decoder_Wcx"]),
+ Bx2_(model("decoder_bx_nl", true)),
+ Bx1_(Bx2_.rows(), Bx2_.columns()),
+ Ux_(model["decoder_Ux_nl"])
+{
+ const_cast<mblas::Matrix&>(Bx1_) = 0.0f;
+}
+
+Weights::DecAttention::DecAttention(const NpzConverter& model)
+: V_(model("decoder_U_att", true)),
+W_(model["decoder_W_comb_att"]),
+B_(model("decoder_b_att", true)),
+U_(model["decoder_Wc_att"]),
+C_(model["decoder_c_tt"]) // scalar?
+{}
+
+Weights::DecSoftmax::DecSoftmax(const NpzConverter& model)
+: W1_(model["ff_logit_lstm_W"]),
+ B1_(model("ff_logit_lstm_b", true)),
+ W2_(model["ff_logit_prev_W"]),
+ B2_(model("ff_logit_prev_b", true)),
+ W3_(model["ff_logit_ctx_W"]),
+ B3_(model("ff_logit_ctx_b", true)),
+ W4_(model["ff_logit_W"]),
+ B4_(model("ff_logit_b", true))
+{}
+
+//////////////////////////////////////////////////////////////////////////////
+
+Weights::Weights(const NpzConverter& model, size_t device)
+: encEmbeddings_(model, "Wemb"),
+encForwardGRU_(model, {"encoder_W", "encoder_b", "encoder_U", "encoder_Wx", "encoder_bx", "encoder_Ux"}),
+encBackwardGRU_(model, {"encoder_r_W", "encoder_r_b", "encoder_r_U", "encoder_r_Wx", "encoder_r_bx", "encoder_r_Ux"}),
+decEmbeddings_(model, "Wemb_dec"),
+decInit_(model),
+decGru1_(model, {"decoder_W", "decoder_b", "decoder_U", "decoder_Wx", "decoder_bx", "decoder_Ux"}),
+decGru2_(model),
+decAttention_(model),
+decSoftmax_(model),
+device_(device)
+{
+ //cerr << *this << endl;
+}
diff --git a/src/cpu/dl4mt/model.h b/src/cpu/dl4mt/model.h
new file mode 100644
index 00000000..f47f3b16
--- /dev/null
+++ b/src/cpu/dl4mt/model.h
@@ -0,0 +1,184 @@
+#pragma once
+
+#include <iostream>
+#include <map>
+#include <string>
+
+#include "../npz_converter.h"
+
+#include "mblas/matrix.h"
+
+struct Weights {
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ struct Embeddings {
+ Embeddings(const NpzConverter& model, const std::string &key);
+
+ const mblas::Matrix E_;
+ };
+
+ struct GRU {
+ GRU(const NpzConverter& model, const std::vector<std::string> &keys);
+
+ const mblas::Matrix W_;
+ const mblas::Matrix B_;
+ const mblas::Matrix U_;
+ const mblas::Matrix Wx_;
+ const mblas::Matrix Bx1_;
+ const mblas::Matrix Bx2_;
+ const mblas::Matrix Ux_;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ struct DecInit {
+ DecInit(const NpzConverter& model);
+
+ const mblas::Matrix Wi_;
+ const mblas::Matrix Bi_;
+ };
+
+ struct DecGRU2 {
+ DecGRU2(const NpzConverter& model);
+
+ const mblas::Matrix W_;
+ const mblas::Matrix B_;
+ const mblas::Matrix U_;
+ const mblas::Matrix Wx_;
+ const mblas::Matrix Bx2_;
+ const mblas::Matrix Bx1_;
+ const mblas::Matrix Ux_;
+ };
+
+ struct DecAttention {
+ DecAttention(const NpzConverter& model);
+
+ const mblas::Matrix V_;
+ const mblas::Matrix W_;
+ const mblas::Matrix B_;
+ const mblas::Matrix U_;
+ const mblas::Matrix C_;
+ };
+
+ struct DecSoftmax {
+ DecSoftmax(const NpzConverter& model);
+
+ const mblas::Matrix W1_;
+ const mblas::Matrix B1_;
+ const mblas::Matrix W2_;
+ const mblas::Matrix B2_;
+ const mblas::Matrix W3_;
+ const mblas::Matrix B3_;
+ const mblas::Matrix W4_;
+ const mblas::Matrix B4_;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ Weights(const std::string& npzFile, size_t device = 0)
+ : Weights(NpzConverter(npzFile), device)
+ {}
+
+ Weights(const NpzConverter& model, size_t device = 0);
+
+ size_t GetDevice() {
+ return device_;
+ }
+
+ const Embeddings encEmbeddings_;
+ const Embeddings decEmbeddings_;
+ const GRU encForwardGRU_;
+ const GRU encBackwardGRU_;
+ const DecInit decInit_;
+ const GRU decGru1_;
+ const DecGRU2 decGru2_;
+ const DecAttention decAttention_;
+ const DecSoftmax decSoftmax_;
+
+ const size_t device_;
+};
+
+inline std::ostream& operator<<(std::ostream &out, const Weights::Embeddings &obj)
+{
+ out << "E_ \t" << obj.E_;
+ return out;
+}
+
+inline std::ostream& operator<<(std::ostream &out, const Weights::GRU &obj)
+{
+ out << "W_ \t" << obj.W_ << std::endl;
+ out << "B_ \t" << obj.B_ << std::endl;
+ out << "U_ \t" << obj.U_ << std::endl;
+ out << "Wx_ \t" << obj.Wx_ << std::endl;
+ out << "Bx1_ \t" << obj.Bx1_ << std::endl;
+ out << "Bx2_ \t" << obj.Bx2_ << std::endl;
+ out << "Ux_ \t" << obj.Ux_;
+ return out;
+}
+
+inline std::ostream& operator<<(std::ostream &out, const Weights::DecGRU2 &obj)
+{
+ out << "W_ \t" << obj.W_ << std::endl;
+ out << "B_ \t" << obj.B_ << std::endl;
+ out << "U_ \t" << obj.U_ << std::endl;
+ out << "Wx_ \t" << obj.Wx_ << std::endl;
+ out << "Bx1_ \t" << obj.Bx1_ << std::endl;
+ out << "Bx2_ \t" << obj.Bx2_ << std::endl;
+ out << "Ux_ \t" << obj.Ux_;
+ return out;
+}
+
+inline std::ostream& operator<<(std::ostream &out, const Weights::DecInit &obj)
+{
+ out << "Wi_ \t" << obj.Wi_ << std::endl;
+ out << "Bi_ \t" << obj.Bi_ ;
+ return out;
+}
+
+inline std::ostream& operator<<(std::ostream &out, const Weights::DecAttention &obj)
+{
+ out << "V_ \t" << obj.V_ << std::endl;
+ out << "W_ \t" << obj.W_ << std::endl;
+ out << "B_ \t" << obj.B_ << std::endl;
+ out << "U_ \t" << obj.U_ << std::endl;
+ out << "C_ \t" << obj.C_ ;
+ return out;
+}
+
+inline std::ostream& operator<<(std::ostream &out, const Weights::DecSoftmax &obj)
+{
+ out << "W1_ \t" << obj.W1_ << std::endl;
+ out << "B1_ \t" << obj.B1_ << std::endl;
+ out << "W2_ \t" << obj.W2_ << std::endl;
+ out << "B2_ \t" << obj.B2_ << std::endl;
+ out << "W3_ \t" << obj.W3_ << std::endl;
+ out << "B3_ \t" << obj.B3_ << std::endl;
+ out << "W4_ \t" << obj.W4_ << std::endl;
+ out << "B4_ \t" << obj.B4_ ;
+
+ return out;
+}
+
+inline std::ostream& operator<<(std::ostream &out, const Weights &obj)
+{
+ out << "\n encEmbeddings_ \n" << obj.encEmbeddings_ << std::endl;
+ out << "\n decEmbeddings_ \n" << obj.decEmbeddings_ << std::endl;
+
+ out << "\n encForwardGRU_ \n" << obj.encForwardGRU_ << std::endl;
+ out << "\n encBackwardGRU_ \n" << obj.encBackwardGRU_ << std::endl;
+
+ out << "\n decInit_ \n" << obj.decInit_ << std::endl;
+
+ out << "\n decGru1_ \n" << obj.decGru1_ << std::endl;
+ out << "\n decGru2_ \n" << obj.decGru2_ << std::endl;
+
+ out << "\n decAttention_ \n" << obj.decAttention_ << std::endl;
+
+ out << "\n decSoftmax_ \n" << obj.decSoftmax_ << std::endl;
+
+ //Debug2(obj.encEmbeddings_.E_);
+
+ return out;
+}
+
diff --git a/src/cpu/mblas/matrix.cpp b/src/cpu/mblas/matrix.cpp
new file mode 100644
index 00000000..da31bb75
--- /dev/null
+++ b/src/cpu/mblas/matrix.cpp
@@ -0,0 +1,40 @@
+#include "matrix.h"
+#include "simd_math_prims.h"
+
+#include "../blaze/Math.h"
+
+namespace mblas {
+
+//Matrix& Prod(Matrix& C, const Matrix& A, const Matrix& B,
+// bool transA, bool transB) {
+// Matrix::value_type alpha = 1.0;
+// Matrix::value_type beta = 0.0;
+//
+// size_t m = A.Rows();
+// size_t k = A.Cols();
+// if(transA)
+// std::swap(m, k);
+//
+// size_t l = B.Rows();
+// size_t n = B.Cols();
+// if(transB)
+// std::swap(l, n);
+//
+// size_t lda = A.Cols();
+// size_t ldb = B.Cols();
+// size_t ldc = B.Cols();
+//
+// if(transB)
+// ldc = B.Rows();
+//
+// C.Resize(m, n);
+//
+// auto opA = transA ? CblasTrans : CblasNoTrans;
+// auto opB = transB ? CblasTrans : CblasNoTrans;
+//
+// cblas_sgemm(CblasColMajor, opB, opA,
+// n, m, k, alpha, B.data(), ldb, A.data(), lda, beta, C.data(), ldc);
+// return C;
+//}
+
+}
diff --git a/src/cpu/mblas/matrix.h b/src/cpu/mblas/matrix.h
new file mode 100644
index 00000000..8864cf3c
--- /dev/null
+++ b/src/cpu/mblas/matrix.h
@@ -0,0 +1,269 @@
+#pragma once
+
+#include <cmath>
+#include <iostream>
+#include <vector>
+
+#include "../blaze/Math.h"
+#include "phoenix_functions.h"
+
+namespace mblas {
+
+typedef blaze::DynamicMatrix<float, blaze::rowMajor> Matrix;
+typedef blaze::DynamicVector<float, blaze::rowVector> Vector;
+typedef blaze::DynamicVector<float, blaze::columnVector> ColumnVector;
+
+template <typename T, bool SO = blaze::rowMajor>
+class BlazeMatrix : public blaze::CustomMatrix<T, blaze::unaligned,
+ blaze::unpadded,
+ blaze::rowMajor> {
+ public:
+ typedef T value_type;
+ typedef typename std::vector<value_type>::iterator iterator;
+ typedef typename std::vector<value_type>::const_iterator const_iterator;
+ typedef blaze::CustomMatrix<value_type,
+ blaze::unaligned,
+ blaze::unpadded,
+ SO> BlazeBase;
+
+ BlazeMatrix() {}
+
+ BlazeMatrix(size_t rows, size_t columns, value_type val = 0)
+ : data_(rows * columns, val) {
+ BlazeBase temp(data_.data(), rows, columns);
+ std::swap(temp, *(BlazeBase*)this);
+ }
+
+ template <class MT>
+ BlazeMatrix(const MT& rhs)
+ : data_(rhs.rows() * rhs.columns()) {
+ BlazeBase temp(data_.data(), rhs.rows(), rhs.columns());
+ temp = rhs;
+ std::swap(temp, *(BlazeBase*)this);
+ }
+
+ void resize(size_t rows, size_t columns) {
+ data_.resize(rows * columns);
+ BlazeBase temp(data_.data(), rows, columns);
+ std::swap(temp, *(BlazeBase*)this);
+ }
+
+ BlazeMatrix<T, SO>& operator=(const value_type& val) {
+ *(BlazeBase*)this = val;
+ return *this;
+ }
+
+ template <class MT>
+ BlazeMatrix<T, SO>& operator=(const MT& rhs) {
+ resize(rhs.rows(), rhs.columns());
+ BlazeBase temp(data_.data(), rhs.rows(), rhs.columns());
+ temp = rhs;
+ std::swap(temp, *(BlazeBase*)this);
+ return *this;
+ }
+
+ operator BlazeBase&() {
+ return *(BlazeBase*)this;
+ }
+
+ iterator begin() {
+ return data_.begin();
+ }
+
+ iterator end() {
+ return data_.end();
+ }
+
+ const_iterator begin() const{
+ return data_.begin();
+ }
+
+ const_iterator end() const {
+ return data_.end();
+ }
+
+ size_t size() const {
+ return data_.size();
+ }
+
+ void swap(BlazeMatrix<T, SO>& rhs) {
+ std::swap(data_, rhs.data_);
+ std::swap(static_cast<BlazeBase&>(*this), static_cast<BlazeBase&>(rhs));
+ }
+
+ private:
+ std::vector<value_type> data_;
+};
+
+typedef BlazeMatrix<float, blaze::rowMajor> ArrayMatrix;
+
+template <class M>
+void Debug(const M& m, size_t maxRows = 5, size_t maxCols = 5) {
+ std::cerr << m.rows() << " " << m.columns() << std::endl;
+ for(size_t i = 0; i < m.rows() && i < maxRows; ++i) {
+ for(size_t j = 0; j < m.columns() && j < maxCols; ++j) {
+ std::cerr << m(i, j) << " ";
+ }
+ std::cerr << std::endl;
+ }
+}
+
+template <class M>
+void Debug2(const M& m) {
+ std::cerr << m.rows() << " " << m.columns() << std::endl;
+ for(size_t i = 0; i < m.rows(); ++i) {
+ for(size_t j = 0; j < m.columns(); ++j) {
+ std::cerr << m(i, j) << " ";
+ }
+ std::cerr << std::endl;
+ }
+}
+
+template <bool byRow, class MT, class VT>
+MT& AddBiasVector(MT& m, const VT& b) {
+ if(byRow) {
+ for(size_t i = 0; i < m.rows(); ++i)
+ // @TODO: replace this with row vector
+ blaze::row(m, i) += blaze::row(b, 0);
+ }
+ else {
+ for(size_t i = 0; i < m.columns(); ++i)
+ // @TODO: replace this with row vector
+ blaze::column(m, i) += blaze::column(b, 0);
+ }
+ return m;
+}
+
+//Matrix& Swap(Matrix& Out, Matrix& In);
+
+template <class MT>
+MT& Reshape(MT& m, size_t rows, size_t cols) {
+ assert(rows * cols == m.rows() * m.columns());
+ MT temp(rows, cols);
+ for(size_t i = 0; i < m.rows(); ++i) {
+ for(size_t j = 0; j < m.columns(); ++j) {
+ size_t k = i * m.columns() + j;
+ size_t i2 = k / cols;
+ size_t j2 = k % cols;
+ temp(i2, j2) = m(i, j);
+ }
+ }
+ temp.swap(m);
+}
+
+template <bool byRow, class MT, class MT1>
+MT Mean(const MT1& in) {
+ MT out;
+ if(byRow) {
+ size_t rows = in.rows();
+ size_t cols = in.columns();
+ out.resize(1, cols);
+ blaze::row(out, 0) = blaze::row(in, 0);
+ for(size_t i = 1; i < rows; ++i)
+ blaze::row(out, 0) += blaze::row(in, i);
+ out *= 1.0f / rows;
+ }
+ else {
+ size_t rows = in.rows();
+ size_t cols = in.columns();
+ out.resize(rows, 1);
+ blaze::column(out, 0) = blaze::column(in, 0);
+ for(size_t i = 1; i < cols; ++i)
+ blaze::column(out, 0) += blaze::column(in, i);
+ out *= 1.0f / cols;
+ }
+ return std::move(out);
+}
+
+typedef std::pair<size_t, size_t> RowPair;
+typedef std::vector<RowPair> RowPairs;
+typedef std::vector<RowPair> DeviceRowPairs;
+
+const bool byRow = true;
+const bool byColumn = false;
+
+template <bool byRow, class MT, class MT1, class MT2>
+MT Concat(const MT1& m1, const MT2& m2) {
+ MT out = m1;
+ if(byRow) {
+ assert(m1.columns() == m2.columns());
+ size_t rows1 = m1.rows();
+ size_t rows2 = m2.rows();
+ size_t rows = rows1 + rows2;
+ size_t cols = m1.columns();
+ out.resize(rows, cols);
+ for(size_t i = 0; i < rows2; ++i)
+ blaze::row(out, rows1 + i) = blaze::row(m2, i);
+ }
+ else {
+ assert(m1.rows() == m2.rows());
+ size_t cols1 = m1.columns();
+ size_t cols2 = m2.columns();
+ size_t cols = cols1 + cols2;
+ size_t rows = m1.rows();
+ out.resize(rows, cols);
+ for(size_t i = 0; i < cols2; ++i)
+ blaze::column(out, cols1 + i) = blaze::column(m2, i);
+ }
+ return std::move(out);
+}
+
+template <bool byRow, class MT, class MT1>
+MT Assemble(const MT1& in,
+ const std::vector<size_t>& indeces) {
+ MT out;
+ if(byRow) {
+ size_t rows = indeces.size();
+ size_t cols = in.columns();
+ out.resize(rows, cols);
+ for(size_t i = 0; i < rows; ++i)
+ blaze::row(out, i) = blaze::row(in, indeces[i]);
+ }
+ else {
+ size_t rows = in.rows();
+ size_t cols = indeces.size();
+ out.resize(rows, cols);
+ for(size_t i = 0; i < cols; ++i)
+ blaze::column(out, i) = blaze::column(in, indeces[i]);
+ }
+ return std::move(out);
+}
+
+template <class MT>
+MT& Softmax(MT& Out) {
+ size_t rows = Out.rows();
+ size_t cols = Out.columns();
+ float sum[rows];
+ for(int j = 0; j < rows; ++j) {
+ sum[j] = 0;
+ for(int i = 0; i < cols; ++i) {
+ Out(j, i) = expapprox(Out(j, i));
+ sum[j] += Out(j, i);
+ }
+ for(int i = 0; i < cols; ++i) {
+ Out(j, i) /= sum[j];
+ }
+ }
+}
+
+template <class MT, class Functor, class MT1, class MT2>
+MT Broadcast(const Functor& functor, const MT1& m1, const MT2& m2) {
+ size_t rows1 = m1.rows();
+ size_t rows2 = m2.rows();
+
+ size_t rows = rows1 * rows2;
+ size_t cols = m1.columns();
+
+ MT out(rows, cols);
+ for(int j = 0; j < rows; ++j) {
+ size_t r1 = j % rows1;
+ size_t r2 = j / rows1;
+
+ blaze::row(out, j) =
+ blaze::forEach(blaze::row(m1, r1) + blaze::row(m2, r2),
+ functor);
+ }
+ return std::move(out);
+}
+
+}
diff --git a/src/cpu/mblas/phoenix_functions.cpp b/src/cpu/mblas/phoenix_functions.cpp
new file mode 100644
index 00000000..3c9a1b6b
--- /dev/null
+++ b/src/cpu/mblas/phoenix_functions.cpp
@@ -0,0 +1,9 @@
+#include <cmath>
+#include <algorithm>
+
+#include "phoenix_functions.h"
+
+namespace mblas
+{
+
+} \ No newline at end of file
diff --git a/src/cpu/mblas/phoenix_functions.h b/src/cpu/mblas/phoenix_functions.h
new file mode 100644
index 00000000..5a6e4f0c
--- /dev/null
+++ b/src/cpu/mblas/phoenix_functions.h
@@ -0,0 +1,107 @@
+#pragma once
+
+namespace mblas
+{
+/* Workaround a lack of optimization in gcc */
+ const float exp_cst1 = 2139095040.f;
+ const float exp_cst2 = 0.f;
+
+ /* Relative error bounded by 1e-5 for normalized outputs
+ Returns invalid outputs for nan inputs
+ Continuous error */
+ inline float expapprox(float val) {
+ union { int i; float f; } xu, xu2;
+ float val2, val3, val4, b;
+ int val4i;
+ val2 = 12102203.1615614f*val+1065353216.f;
+ val3 = val2 < exp_cst1 ? val2 : exp_cst1;
+ val4 = val3 > exp_cst2 ? val3 : exp_cst2;
+ val4i = (int) val4;
+ xu.i = val4i & 0x7F800000;
+ xu2.i = (val4i & 0x7FFFFF) | 0x3F800000;
+ b = xu2.f;
+
+ /* Generated in Sollya with:
+ > f=remez(1-x*exp(-(x-1)*log(2)),
+ [|1,(x-1)*(x-2), (x-1)*(x-2)*x, (x-1)*(x-2)*x*x|],
+ [1,2], exp(-(x-1)*log(2)));
+ > plot(exp((x-1)*log(2))/(f+x)-1, [1,2]);
+ > f+x;
+ */
+ return
+ xu.f * (0.510397365625862338668154f + b *
+ (0.310670891004095530771135f + b *
+ (0.168143436463395944830000f + b *
+ (-2.88093587581985443087955e-3f + b *
+ 1.3671023382430374383648148e-2f))));
+ }
+
+ /* Absolute error bounded by 1e-6 for normalized inputs
+ Returns a finite number for +inf input
+ Returns -inf for nan and <= 0 inputs.
+ Continuous error. */
+ inline float logapprox(float val) {
+ union { float f; int i; } valu;
+ float exp, addcst, x;
+ valu.f = val;
+ exp = valu.i >> 23;
+ /* 89.970756366f = 127 * log(2) - constant term of polynomial */
+ addcst = val > 0 ? -89.970756366f : -(float)INFINITY;
+ valu.i = (valu.i & 0x7FFFFF) | 0x3F800000;
+ x = valu.f;
+
+
+ /* Generated in Sollya using :
+ > f = remez(log(x)-(x-1)*log(2),
+ [|1,(x-1)*(x-2), (x-1)*(x-2)*x, (x-1)*(x-2)*x*x,
+ (x-1)*(x-2)*x*x*x|], [1,2], 1, 1e-8);
+ > plot(f+(x-1)*log(2)-log(x), [1,2]);
+ > f+(x-1)*log(2)
+ */
+ return
+ x * (3.529304993f + x * (-2.461222105f +
+ x * (1.130626167f + x * (-0.288739945f +
+ x * 3.110401639e-2f))))
+ + (addcst + 0.69314718055995f*exp);
+ }
+
+ inline float logitapprox(float x) {
+ return 1.0f / (1.0f + expapprox(-x));
+ }
+
+ inline float tanhapprox(float x) {
+ x = std::max(std::min(x, 4.97f), -4.97f);
+ float x2 = x * x;
+ float a = x * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2)));
+ float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f));
+ return a / b;
+ }
+
+ struct Exp {
+ template <typename T>
+ inline T operator()(T val) const {
+ return expapprox(val);
+ }
+ };
+
+ struct Log {
+ template <typename T>
+ inline T operator()(T val) const {
+ return logapprox(val);
+ }
+ };
+
+ struct Logit {
+ template <typename T>
+ inline T operator()(T val) const {
+ return logitapprox(val);
+ }
+ };
+
+ struct Tanh {
+ template <typename T>
+ inline T operator()(T val) const {
+ return tanhapprox(val);
+ }
+ };
+} \ No newline at end of file
diff --git a/src/cpu/mblas/simd_math_prims.h b/src/cpu/mblas/simd_math_prims.h
new file mode 100644
index 00000000..8aeabb04
--- /dev/null
+++ b/src/cpu/mblas/simd_math_prims.h
@@ -0,0 +1,117 @@
+/*
+
+The MIT License (MIT)
+
+Copyright (c) 2015 Jacques-Henri Jourdan <jourgun@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
+#ifndef SIMD_MATH_PRIMS_H
+#define SIMD_MATH_PRIMS_H
+
+#include<math.h>
+#include <iostream>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Workaround a lack of optimization in gcc */
+const float exp_cst1 = 2139095040.f;
+const float exp_cst2 = 0.f;
+
+/* Relative error bounded by 1e-5 for normalized outputs
+ Returns invalid outputs for nan inputs
+ Continuous error */
+inline float expapprox(float val) {
+ union { int i; float f; } xu, xu2;
+ float val2, val3, val4, b;
+ int val4i;
+ val2 = 12102203.1615614f*val+1065353216.f;
+ val3 = val2 < exp_cst1 ? val2 : exp_cst1;
+ val4 = val3 > exp_cst2 ? val3 : exp_cst2;
+ val4i = (int) val4;
+ xu.i = val4i & 0x7F800000;
+ xu2.i = (val4i & 0x7FFFFF) | 0x3F800000;
+ b = xu2.f;
+
+ /* Generated in Sollya with:
+ > f=remez(1-x*exp(-(x-1)*log(2)),
+ [|1,(x-1)*(x-2), (x-1)*(x-2)*x, (x-1)*(x-2)*x*x|],
+ [1,2], exp(-(x-1)*log(2)));
+ > plot(exp((x-1)*log(2))/(f+x)-1, [1,2]);
+ > f+x;
+ */
+ return
+ xu.f * (0.510397365625862338668154f + b *
+ (0.310670891004095530771135f + b *
+ (0.168143436463395944830000f + b *
+ (-2.88093587581985443087955e-3f + b *
+ 1.3671023382430374383648148e-2f))));
+}
+
+/* Absolute error bounded by 1e-6 for normalized inputs
+ Returns a finite number for +inf input
+ Returns -inf for nan and <= 0 inputs.
+ Continuous error. */
+inline float logapprox(float val) {
+ union { float f; int i; } valu;
+ float exp, addcst, x;
+ valu.f = val;
+ exp = valu.i >> 23;
+ /* 89.970756366f = 127 * log(2) - constant term of polynomial */
+ addcst = val > 0 ? -89.970756366f : -(float)INFINITY;
+ valu.i = (valu.i & 0x7FFFFF) | 0x3F800000;
+ x = valu.f;
+
+
+ /* Generated in Sollya using :
+ > f = remez(log(x)-(x-1)*log(2),
+ [|1,(x-1)*(x-2), (x-1)*(x-2)*x, (x-1)*(x-2)*x*x,
+ (x-1)*(x-2)*x*x*x|], [1,2], 1, 1e-8);
+ > plot(f+(x-1)*log(2)-log(x), [1,2]);
+ > f+(x-1)*log(2)
+ */
+ return
+ x * (3.529304993f + x * (-2.461222105f +
+ x * (1.130626167f + x * (-0.288739945f +
+ x * 3.110401639e-2f))))
+ + (addcst + 0.69314718055995f*exp);
+}
+
+inline float logitapprox(float x) {
+ return 1.0f / (1.0f + expapprox(-x));
+}
+
+inline float tanhapprox(float x) {
+ x = std::max(std::min(x, 4.97f), -4.97f);
+ float x2 = x * x;
+ float a = x * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2)));
+ float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f));
+ return a / b;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cpu/npz_converter.h b/src/cpu/npz_converter.h
new file mode 100644
index 00000000..59b958e5
--- /dev/null
+++ b/src/cpu/npz_converter.h
@@ -0,0 +1,88 @@
+#pragma once
+
+#include "cnpy/cnpy.h"
+#include "mblas/matrix.h"
+
+class NpzConverter {
+ private:
+ class NpyMatrixWrapper {
+ public:
+ NpyMatrixWrapper(const cnpy::NpyArray& npy)
+ : npy_(npy) {}
+
+ size_t size() const {
+ return size1() * size2();
+ }
+
+ float* data() const {
+ return (float*)npy_.data;
+ }
+
+ float operator()(size_t i, size_t j) const {
+ return ((float*)npy_.data)[i * size2() + j];
+ }
+
+ size_t size1() const {
+ return npy_.shape[0];
+ }
+
+ size_t size2() const {
+ if(npy_.shape.size() == 1)
+ return 1;
+ else
+ return npy_.shape[1];
+ }
+
+ private:
+ const cnpy::NpyArray& npy_;
+ };
+
+ public:
+
+ typedef blaze::CustomMatrix<float, blaze::unaligned,
+ blaze::unpadded, blaze::rowMajor> BlazeWrapper;
+
+
+ NpzConverter(const std::string& file)
+ : model_(cnpy::npz_load(file)),
+ destructed_(false) {
+ }
+
+ ~NpzConverter() {
+ if(!destructed_)
+ model_.destruct();
+ }
+
+ void Destruct() {
+ model_.destruct();
+ destructed_ = true;
+ }
+
+ mblas::Matrix operator[](const std::string& key) const {
+ mblas::Matrix matrix;
+ auto it = model_.find(key);
+ if(it != model_.end()) {
+ NpyMatrixWrapper np(it->second);
+ matrix = BlazeWrapper(np.data(), np.size1(), np.size2());
+ }
+ else {
+ std::cerr << "Missing " << key << std::endl;
+ }
+ return std::move(matrix);
+ }
+
+ mblas::Matrix operator()(const std::string& key,
+ bool transpose) const {
+ mblas::Matrix matrix;
+ auto it = model_.find(key);
+ if(it != model_.end()) {
+ NpyMatrixWrapper np(it->second);
+ matrix = BlazeWrapper(np.data(), np.size1(), np.size2());
+ }
+ return blaze::trans(matrix);
+ }
+
+ private:
+ cnpy::npz_t model_;
+ bool destructed_;
+};